Initial commit

This commit is contained in:
Looki2000 2023-02-19 21:41:32 +01:00
commit 74d5334e72
1522 changed files with 753891 additions and 0 deletions

33
.clang-format Normal file
View File

@ -0,0 +1,33 @@
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Always
TabWidth: 4
BreakBeforeBraces: Custom
Standard: Cpp11
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: false
BeforeElse: false
FixNamespaceComments: false
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
AccessModifierOffset: -4
ColumnLimit: 90
AllowShortFunctionsOnASingleLine: InlineOnly
SortIncludes: false
IncludeCategories:
- Regex: '^".*'
Priority: 2
- Regex: '^<.*'
Priority: 1
AlignAfterOpenBracket: DontAlign
ContinuationIndentWidth: 8
ConstructorInitializerIndentWidth: 8
BreakConstructorInitializers: AfterColon
AlwaysBreakTemplateDeclarations: Yes

5
.clang-tidy Normal file
View File

@ -0,0 +1,5 @@
Checks: '-*,modernize-use-emplace,modernize-avoid-bind,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,performance-*'
WarningsAsErrors: '-*,modernize-use-emplace,performance-type-promotion-in-math-fn,performance-faster-string-find,performance-implicit-cast-in-loop'
CheckOptions:
- key: performance-unnecessary-value-param.AllowedTypes
value: v[23]f;v[23][su](16|32)

4
.dockerignore Normal file
View File

@ -0,0 +1,4 @@
./cmake-build-*
./build/*
./cache/*
Dockerfile

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
[*]
end_of_line = lf
[*.{cpp,h,lua,txt,glsl,md,c,cmake,java,gradle}]
charset = utf8
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.cpp diff=cpp
*.h diff=cpp

183
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,183 @@
# Contributing
Contributions are welcome! Here's how you can help:
- [Contributing code](#code)
- [Reporting issues](#issues)
- [Requesting features](#feature-requests)
- [Translating](#translations)
- [Donating](#donations)
## Code
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and
[clone](https://help.github.com/articles/cloning-a-repository/) your fork.
2. Before you start coding, consider opening an
[issue at Github](https://github.com/minetest/minetest/issues) to discuss the
suitability and implementation of your intended contribution with the core
developers.
Any Pull Request that isn't a bug fix and isn't covered by
[the roadmap](../doc/direction.md) will be closed within a week unless it
receives a concept approval from a Core Developer. For this reason, it is
recommended that you open an issue for any such pull requests before doing
the work, to avoid disappointment.
You may also benefit from discussing on our IRC development channel
[#minetest-dev](http://www.minetest.net/irc/). Note that a proper IRC client
is required to speak on this channel.
3. Start coding!
- Refer to the
[Lua API](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt),
[Developer Wiki](http://dev.minetest.net/Main_Page) and other
[documentation](https://github.com/minetest/minetest/tree/master/doc).
- Follow the [C/C++](http://dev.minetest.net/Code_style_guidelines) and
[Lua](http://dev.minetest.net/Lua_code_style_guidelines) code style guidelines.
- Check your code works as expected and document any changes to the Lua API.
4. Commit & [push](https://help.github.com/articles/pushing-to-a-remote/) your changes to a new branch (not `master`, one change per branch)
- Commit messages should:
- Use the present tense.
- Be descriptive. See the commit messages by core developers for examples.
- The first line should:
- Start with a capital letter.
- Be a compact summary of the commit.
- Preferably have less than 70 characters.
- Have no full stop at the end.
- The second line should be empty.
- The following lines should describe the commit, starting a new line for each point.
5. Once you are happy with your changes, submit a pull request.
- Open the [pull-request form](https://github.com/minetest/minetest/pull/new/master).
- Add a description explaining what you've done (or if it's a
work-in-progress - what you need to do).
- Make sure to fill out the pull request template.
### A pull-request is considered merge-able when:
1. It follows [the roadmap](../doc/direction.md) in some way and fits the whole
picture of the project.
2. It works.
3. It follows the code style for
[C/C++](http://dev.minetest.net/Code_style_guidelines) or
[Lua](http://dev.minetest.net/Lua_code_style_guidelines).
4. The code's interfaces are well designed, regardless of other aspects that
might need more work in the future.
5. It uses protocols and formats which include the required compatibility.
### Important note about automated GitHub checks
When you submit a pull request, GitHub automatically runs checks on the Minetest
Engine combined with your changes. One of these checks is called 'cpp lint /
clang format', which checks code formatting. Because formatting for readability
requires human judgement this check often fails and often makes unsuitable
formatting requests which make code readability worse.
If this check fails, look at the details to check for any clear mistakes and
correct those. However, you should not apply everything ClangFormat requests.
Ignore requests that make code readability worse and any other clearly
unsuitable requests. Discuss in the pull request with a core developer about how
to progress.
## Issues
If you experience an issue, we would like to know the details - especially when
a stable release is on the way.
1. Do a quick search on GitHub to check if the issue has already been reported.
2. Is it an issue with the Minetest *engine*? If not, report it
[elsewhere](http://www.minetest.net/development/#reporting-issues).
3. [Open an issue](https://github.com/minetest/minetest/issues/new) and describe
the issue you are having - you could include:
- Error logs (check the bottom of the `debug.txt` file).
- Screenshots.
- Ways you have tried to solve the issue, and whether they worked or not.
- Your Minetest version and the content (games, mods or texture packs) you have installed.
- Your platform (e.g. Windows 10 or Ubuntu 15.04 x64).
After reporting you should aim to answer questions or clarifications as this
helps pinpoint the cause of the issue (if you don't do this your issue may be
closed after 1 month).
## Feature requests
Feature requests are welcome but take a moment to see if your idea follows
[the roadmap](../doc/direction.md) in some way and fits the whole picture of
the project. You should provide a clear explanation with as much detail as
possible.
## Translations
The core translations of Minetest are performed using Weblate. You can access
the project page with a list of current languages
[here](https://hosted.weblate.org/projects/minetest/minetest/).
Builtin (the component which contains things like server messages, chat command
descriptions, privilege descriptions) is translated separately; it needs to be
translated by editing a `.tr` text file. See
[Translation](https://dev.minetest.net/Translation) for more information.
## Donations
If you'd like to monetarily support Minetest development, you can find donation
methods on [our website](http://www.minetest.net/development/#donate).
# Maintaining
* This is a concise version of the
[Rules & Guidelines](http://dev.minetest.net/Category:Rules_and_Guidelines) on the developer wiki.*
These notes are for those who have push access Minetest (core developers / maintainers).
- See the [project organisation](http://dev.minetest.net/Organisation) for the people involved.
## Concept approvals and roadmaps
If a Pull Request is not a bug fix:
* If it matches a goal in [the roadmap](../doc/direction.md), then the PR should
be labelled as "Roadmap" and the goal stated by number in the description.
* If it doesn't match a goal, then it needs to receive a concept approval within
a week of being opened to remain open. This 1 week deadline does not apply to
PRs opened before the roadmap was adopted; instead, they may remain open or be
closed as needed. Use the "Concept Approved" label. Issues can be marked as
"Concept Approved" to give preapproval to future PRs.
## Reviewing pull requests
Pull requests should be reviewed and, if appropriate, checked if they achieve
their intended purpose. You can show that you are in the process of, or will
review the pull request by commenting *"Looks good"* or something similar.
**If the pull-request is not [merge-able](#a-pull-request-is-considered-merge-able-when):**
Submit a comment explaining to the author what they need to change to make the
pull-request merge-able.
- If the author comments or makes changes to the pull-request, it can be
reviewed again.
- If no response is made from the author within 1 month (when improvements are
suggested or a question is asked), it can be closed.
**If the pull-request is [merge-able](#a-pull-request-is-considered-merge-able-when):**
Submit a :+1: (+1) or "Looks good" comment to show you believe the pull-request should be merged. "Looks good" comments often signify that the patch might require (more) testing.
- Two core developers must agree to the merge before it is carried out and both should +1 the pull request.
- Who intends to merge the pull-request should follow the commit rules:
- The title should follow the commit guidelines (title starts with a capital letter, present tense, descriptive).
- Don't modify history older than 10 minutes.
- Use rebase, not merge to get linear history:
- `curl https://github.com/minetest/minetest/pull/1.patch | git am`
## Reviewing issues and feature requests
- If an issue does not get a response from its author within 1 month (when requiring more details), it can be closed.
- When an issue is a duplicate, refer to the first ones and close the later ones.
- Tag issues with the appropriate [labels](https://github.com/minetest/minetest/labels) for devices, platforms etc.
## Releasing a new version
*Refer to [dev.minetest.net/Releasing_Minetest](http://dev.minetest.net/Releasing_Minetest)*

32
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: Unconfirmed bug
assignees: ''
---
##### Minetest version
<!--
Paste Minetest version between quotes below.
If you are on a devel version, please add git commit hash.
You can use `minetest --version` to find it.
-->
```
```
##### OS / Hardware
<!-- General information about your hardware and operating system -->
Operating system:
CPU:
<!-- For graphical issues only -->
GPU model:
OpenGL version:
##### Summary
<!-- Describe your problem here -->
##### Steps to reproduce
<!-- Explain how the problem has happened, providing a minimal test (i.e. a code snippet reduced to the bone) where possible -->

View File

@ -0,0 +1,25 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: Feature request
assignees: ''
---
## Problem
A clear and concise description of what the problem is.
ie: Why is this needed?
Ex. I'm always frustrated when [...]
## Solutions
A clear and concise description of what you want to happen.
## Alternatives
A clear and concise description of any alternative solutions or features you've considered.
## Additional context
Add any other context or screenshots about the feature request here.

20
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,20 @@
Add compact, short information about your PR for easier understanding:
- Goal of the PR
- How does the PR work?
- Does it resolve any reported issue?
- Does this relate to a goal in [the roadmap](../doc/direction.md)?
- If not a bug fix, why is this PR needed? What usecases does it solve?
## To do
This PR is a Work in Progress / Ready for Review.
<!-- ^ delete one -->
- [ ] List
- [ ] Things
- [ ] To do
## How to test
<!-- Example code or instructions -->

20
.github/SECURITY.md vendored Normal file
View File

@ -0,0 +1,20 @@
# Security Policy
## Supported Versions
We only support the latest stable version for security issues.
See the [releases page](https://github.com/minetest/minetest/releases).
## Reporting a Vulnerability
We ask that you report vulnerabilities privately, by contacting a core developer,
to give us time to fix them. You can do that by emailing one of the following addresses:
* celeron55@gmail.com
* rubenwardy@minetest.net
Depending on severity, we will either create a private issue for the vulnerability
and release a patch version of Minetest, or give you permission to file the issue publicly.
For more information on the justification of this policy, see
[Responsible Disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure).

52
.github/workflows/android.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: android
# build on c/cpp changes or workflow changes
on:
push:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'android/**'
- '.github/workflows/android.yml'
pull_request:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'android/**'
- '.github/workflows/android.yml'
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends gettext openjdk-11-jdk-headless
- name: Build with Gradle
run: cd android; ./gradlew assemblerelease
- name: Save armeabi artifact
uses: actions/upload-artifact@v3
with:
name: Minetest-armeabi-v7a.apk
path: android/app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned.apk
- name: Save arm64 artifact
uses: actions/upload-artifact@v3
with:
name: Minetest-arm64-v8a.apk
path: android/app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk
- name: Save x86 artifact
uses: actions/upload-artifact@v3
with:
name: Minetest-x86.apk
path: android/app/build/outputs/apk/release/app-x86-release-unsigned.apk
- name: Save x86_64 artifact
uses: actions/upload-artifact@v3
with:
name: Minetest-x86_64.apk
path: android/app/build/outputs/apk/release/app-x86_64-release-unsigned.apk

271
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,271 @@
name: build
# build on c/cpp changes or workflow changes
on:
push:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/buildbot/**'
- 'util/ci/**'
- '.github/workflows/**.yml'
- 'Dockerfile'
- '.dockerignore'
pull_request:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/buildbot/**'
- 'util/ci/**'
- '.github/workflows/**.yml'
- 'Dockerfile'
- '.dockerignore'
jobs:
# Older gcc version (should be close to our minimum supported version)
gcc_5:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps g++-5
- name: Build
run: |
./util/ci/build.sh
env:
CC: gcc-5
CXX: g++-5
- name: Test
run: |
./bin/minetest --run-unittests
# Current gcc version
gcc_12:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps g++-12 libluajit-5.1-dev
- name: Build
run: |
./util/ci/build.sh
env:
CC: gcc-12
CXX: g++-12
- name: Test
run: |
./bin/minetest --run-unittests
# Older clang version (should be close to our minimum supported version)
clang_3_9:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-3.9 valgrind
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-3.9
CXX: clang++-3.9
- name: Unittest
run: |
./bin/minetest --run-unittests
- name: Valgrind
run: |
valgrind --leak-check=full --leak-check-heuristics=all --undef-value-errors=no --error-exitcode=9 ./bin/minetest --run-unittests
# Current clang version
clang_14:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-14 gdb
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-14
CXX: clang++-14
- name: Test
run: |
./bin/minetest --run-unittests
- name: Integration test + devtest
run: |
./util/test_multiplayer.sh
# Build with prometheus-cpp (server-only)
clang_9_prometheus:
name: "clang_9 (PROMETHEUS=1)"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-9
- name: Build prometheus-cpp
run: |
./util/ci/build_prometheus_cpp.sh
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-9
CXX: clang++-9
CMAKE_FLAGS: "-DENABLE_PROMETHEUS=1 -DBUILD_CLIENT=0"
- name: Test
run: |
./bin/minetestserver --run-unittests
docker:
name: "Docker image"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Build docker image
run: |
docker build . -t minetest:latest
docker run --rm minetest:latest /usr/local/bin/minetestserver --version
win32:
name: "MinGW cross-compiler (32-bit)"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install compiler
run: |
sudo apt-get update && sudo apt-get install -y gettext
wget http://minetest.kitsunemimi.pw/mingw-w64-i686_11.2.0_ubuntu20.04.tar.xz -O mingw.tar.xz
sudo tar -xaf mingw.tar.xz -C /usr
- name: Build
run: |
EXISTING_MINETEST_DIR=$PWD ./util/buildbot/buildwin32.sh winbuild
env:
NO_MINETEST_GAME: 1
NO_PACKAGE: 1
win64:
name: "MinGW cross-compiler (64-bit)"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install compiler
run: |
sudo apt-get update && sudo apt-get install -y gettext
wget http://minetest.kitsunemimi.pw/mingw-w64-x86_64_11.2.0_ubuntu20.04.tar.xz -O mingw.tar.xz
sudo tar -xaf mingw.tar.xz -C /usr
- name: Build
run: |
EXISTING_MINETEST_DIR=$PWD ./util/buildbot/buildwin64.sh winbuild
env:
NO_MINETEST_GAME: 1
NO_PACKAGE: 1
msvc:
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
runs-on: windows-2019
env:
VCPKG_VERSION: 5cf60186a241e84e8232641ee973395d4fde90e1
# 2022.02
vcpkg_packages: zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp opengl-registry
strategy:
fail-fast: false
matrix:
config:
- {
arch: x86,
generator: "-G'Visual Studio 16 2019' -A Win32",
vcpkg_triplet: x86-windows
}
- {
arch: x64,
generator: "-G'Visual Studio 16 2019' -A x64",
vcpkg_triplet: x64-windows
}
type: [portable]
# type: [portable, installer]
# The installer type is working, but disabled, to save runner jobs.
# Enable it, when working on the installer.
steps:
- uses: actions/checkout@v3
- name: Checkout IrrlichtMt
run: |
$ref = @(Get-Content misc\irrlichtmt_tag.txt)
git clone https://github.com/minetest/irrlicht lib\irrlichtmt --depth 1 -b $ref[0]
- name: Restore from cache and run vcpkg
uses: lukka/run-vcpkg@v7
with:
vcpkgArguments: ${{env.vcpkg_packages}}
vcpkgDirectory: '${{ github.workspace }}\vcpkg'
appendedCacheKey: ${{ matrix.config.vcpkg_triplet }}
vcpkgGitCommitId: ${{ env.VCPKG_VERSION }}
vcpkgTriplet: ${{ matrix.config.vcpkg_triplet }}
- name: Minetest CMake
run: |
cmake ${{matrix.config.generator}} `
-DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}\vcpkg\scripts\buildsystems\vcpkg.cmake" `
-DCMAKE_BUILD_TYPE=Release `
-DENABLE_POSTGRESQL=OFF `
-DRUN_IN_PLACE=${{ contains(matrix.type, 'portable') }} .
- name: Build Minetest
run: cmake --build . --config Release
- name: CPack
run: |
If ($env:TYPE -eq "installer")
{
cpack -G WIX -B "$env:GITHUB_WORKSPACE\Package"
}
ElseIf($env:TYPE -eq "portable")
{
cpack -G ZIP -B "$env:GITHUB_WORKSPACE\Package"
}
env:
TYPE: ${{matrix.type}}
- name: Package Clean
run: rm -r $env:GITHUB_WORKSPACE\Package\_CPack_Packages
- uses: actions/upload-artifact@v3
with:
name: msvc-${{ matrix.config.arch }}-${{ matrix.type }}
path: .\Package\

55
.github/workflows/cpp_lint.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: cpp_lint
# lint on c/cpp changes or workflow changes
on:
push:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/ci/**'
- '.github/workflows/**.yml'
pull_request:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/ci/**'
- '.github/workflows/**.yml'
jobs:
# clang_format:
# runs-on: ubuntu-20.04
# steps:
# - uses: actions/checkout@v3
# - name: Install clang-format
# run: |
# sudo apt-get update
# sudo apt-get install -y clang-format-9
#
# - name: Run clang-format
# run: |
# source ./util/ci/clang-format.sh
# check_format
# env:
# CLANG_FORMAT: clang-format-9
clang_tidy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-tidy-9
- name: Run clang-tidy
run: |
./util/ci/clang-tidy.sh

72
.github/workflows/lua.yml vendored Normal file
View File

@ -0,0 +1,72 @@
name: lua_lint
# Lint on lua changes on builtin or if workflow changed
on:
push:
paths:
- 'builtin/**.lua'
- 'games/devtest/**.lua'
- '.github/workflows/**.yml'
pull_request:
paths:
- 'builtin/**.lua'
- 'games/devtest/**.lua'
- '.github/workflows/**.yml'
jobs:
# Note that the integration tests are also run build.yml, but only when C++ code is changed.
integration_tests:
name: "Compile and run multiplayer tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-10 gdb libluajit-5.1-dev
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-10
CXX: clang++-10
CMAKE_FLAGS: "-DENABLE_GETTEXT=0 -DBUILD_SERVER=0"
- name: Integration test + devtest
run: |
./util/test_multiplayer.sh
luacheck:
name: "Builtin Luacheck and Unit Tests"
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: leafo/gh-actions-lua@v9
with:
luaVersion: "5.1.5"
- uses: leafo/gh-actions-luarocks@v4
- name: Install LuaJIT
run: |
cd $HOME
git clone https://github.com/LuaJIT/LuaJIT/
cd LuaJIT
make -j$(nproc)
- name: Install luarocks tools
run: |
luarocks install --local luacheck
luarocks install --local busted
- name: Run checks (builtin)
run: |
$HOME/.luarocks/bin/luacheck builtin
$HOME/.luarocks/bin/busted builtin
$HOME/.luarocks/bin/busted builtin --lua=$HOME/LuaJIT/src/luajit
- name: Run checks (devtest)
run: |
$HOME/.luarocks/bin/luacheck --config=games/devtest/.luacheckrc games/devtest

67
.github/workflows/macos.yml vendored Normal file
View File

@ -0,0 +1,67 @@
name: macos
# build on c/cpp changes or workflow changes
on:
push:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- '.github/workflows/macos.yml'
pull_request:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- '.github/workflows/macos.yml'
env:
MINETEST_GAME_REPO: https://github.com/minetest/minetest_game.git
MINETEST_GAME_BRANCH: master
MINETEST_GAME_NAME: minetest_game
jobs:
build:
runs-on: macos-11
steps:
- uses: actions/checkout@v3
- name: Install deps
run: |
source ./util/ci/common.sh
install_macos_deps
- name: Build
run: |
git clone -b $MINETEST_GAME_BRANCH $MINETEST_GAME_REPO games/$MINETEST_GAME_NAME
git clone https://github.com/minetest/irrlicht lib/irrlichtmt --depth 1 -b $(cat misc/irrlichtmt_tag.txt)
mkdir build
cd build
cmake .. \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14 \
-DCMAKE_FIND_FRAMEWORK=LAST \
-DCMAKE_INSTALL_PREFIX=../build/macos/ \
-DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE
make -j2
make install
- name: Test
run: |
./build/macos/minetest.app/Contents/MacOS/minetest --run-unittests
# Zipping the built .app preserves permissions on the contained files,
# which the GitHub artifact pipeline would otherwise strip away.
- name: CPack
run: |
cd build
cpack -G ZIP -B macos
- uses: actions/upload-artifact@v3
with:
name: minetest-macos
path: ./build/macos/*.zip

119
.gitignore vendored Normal file
View File

@ -0,0 +1,119 @@
## Editors and development environments
*~
*.swp
*.bak*
*.orig
.DS_Store
# Vim
*.vim
# Kate
.*.kate-swp
.swp.*
# KDevelop4
.kdev4/
*.kdev4
# Eclipse (CDT and LDT)
.project
.cproject
.settings/
.buildpath
.metadata
# GNU Global
tags
!tags/
gtags.files
.idea
# Codelite
*.project
# Visual Studio Code & plugins
.vscode/
build/.cmake/
# Gradle
.gradle
## Files related to Minetest development cycle
/*.patch
*.diff
# GNU Patch reject file
*.rej
## Non-static Minetest directories or symlinks to these
/bin/
/games/*
!/games/devtest/
/cache
/textures/*
!/textures/base/
/screenshots
/sounds
/mods/*
!/mods/minetest/
/mods/minetest/*
!/mods/minetest/mods_here.txt
/worlds
/world/
/clientmods/*
!/clientmods/preview/
/client/mod_storage/
## Configuration/log files
minetest.conf
debug.txt
debug.txt.1
## Other files generated by Minetest
screenshot_*.png
testbm.txt
## Doxygen files
doc/Doxyfile
doc/html/
doc/doxygen_*
## MkDocs files
public/
doc/mkdocs/docs/*.md
doc/mkdocs/mkdocs.yml
## Build files
build/
CMakeFiles
Makefile
cmake_install.cmake
CMakeCache.txt
CPackConfig.cmake
CPackSourceConfig.cmake
src/test_config.h
src/cmake_config.h
src/cmake_config_githash.h
src/unittest/test_world/world.mt
games/devtest/mods/testnodes/textures/testnodes_generated_*.png
/locale/
.directory
*.cbp
*.layout
*.o
*.a
*.ninja
.ninja*
*.gch
*.iml
test_config.h
cmake-build-debug/
cmake-build-release/
cmake_config.h
cmake_config_githash.h
CMakeDoxy*
compile_commands.json
*.apk
*.zip
# Visual Studio
*.vcxproj*
*.sln
.vs/
# Optional user provided library folder
lib/irrlichtmt
# Generated mod storage database
client/mod_storage.sqlite

289
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,289 @@
---
# Github repository is cloned every day on Gitlab.com
# https://gitlab.com/minetest/minetest
# Pipelines URL: https://gitlab.com/minetest/minetest/pipelines
stages:
- build
- package
- deploy
variables:
MINETEST_GAME_REPO: "https://github.com/minetest/minetest_game.git"
CONTAINER_IMAGE: registry.gitlab.com/$CI_PROJECT_PATH
.build_template:
stage: build
before_script:
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential git cmake libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libleveldb-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev
script:
- git clone https://github.com/minetest/irrlicht lib/irrlichtmt --depth 1 -b $(cat misc/irrlichtmt_tag.txt)
- mkdir build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE ..
- make -j $(($(nproc) + 1))
- make install
artifacts:
when: on_success
expire_in: 1h
paths:
- artifact/*
.debpkg_template:
stage: package
before_script:
- apt-get update
- apt-get install -y git
- mkdir -p build/deb/minetest/DEBIAN/
- cp misc/debpkg-control build/deb/minetest/DEBIAN/control
- 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
- sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/JPEG_PLACEHOLDER/'$JPEG_PKG'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/JSONCPP_PLACEHOLDER/'$JSONCPP_PKG'/g' build/deb/minetest/DEBIAN/control
- cd build/deb/ && dpkg-deb -b minetest/ && mv minetest.deb ../../
artifacts:
expire_in: 90 day
paths:
- ./*.deb
.debpkg_install:
stage: deploy
before_script:
- apt-get update -qy
script:
- apt-get install -y ./*.deb
- minetest --version
##
## Debian
##
# Stretch
build:debian-9:
extends: .build_template
image: debian:9
package:debian-9:
extends: .debpkg_template
image: debian:9
needs:
- build:debian-9
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1v5
JPEG_PKG: libjpeg62-turbo
deploy:debian-9:
extends: .debpkg_install
image: debian:9
needs:
- package:debian-9
# Buster
build:debian-10:
extends: .build_template
image: debian:10
package:debian-10:
extends: .debpkg_template
image: debian:10
needs:
- build:debian-10
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1d
JPEG_PKG: libjpeg62-turbo
deploy:debian-10:
extends: .debpkg_install
image: debian:10
needs:
- package:debian-10
# Bullseye
build:debian-11:
extends: .build_template
image: debian:11
package:debian-11:
extends: .debpkg_template
image: debian:11
needs:
- build:debian-11
variables:
JSONCPP_PKG: libjsoncpp24
LEVELDB_PKG: libleveldb1d
JPEG_PKG: libjpeg62-turbo
deploy:debian-11:
extends: .debpkg_install
image: debian:11
needs:
- package:debian-11
##
## Ubuntu
##
# Bionic
build:ubuntu-18.04:
extends: .build_template
image: ubuntu:bionic
package:ubuntu-18.04:
extends: .debpkg_template
image: ubuntu:bionic
needs:
- build:ubuntu-18.04
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1v5
JPEG_PKG: libjpeg-turbo8
deploy:ubuntu-18.04:
extends: .debpkg_install
image: ubuntu:bionic
needs:
- package:ubuntu-18.04
# Focal
build:ubuntu-20.04:
extends: .build_template
image: ubuntu:focal
package:ubuntu-20.04:
extends: .debpkg_template
image: ubuntu:focal
needs:
- build:ubuntu-20.04
variables:
JSONCPP_PKG: libjsoncpp1
LEVELDB_PKG: libleveldb1d
JPEG_PKG: libjpeg-turbo8
deploy:ubuntu-20.04:
extends: .debpkg_install
image: ubuntu:focal
needs:
- package:ubuntu-20.04
##
## Fedora
##
# Fedora 28 <-> RHEL 8
build:fedora-28:
extends: .build_template
image: fedora:28
before_script:
- dnf -y install make git gcc gcc-c++ kernel-devel cmake libjpeg-devel libpng-devel libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel libzstd-devel
##
## MinGW for Windows
##
.generic_win_template:
image: ubuntu:focal
before_script:
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get install -y wget xz-utils unzip git cmake gettext
- wget -nv http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_11.2.0_ubuntu20.04.tar.xz -O mingw.tar.xz
- tar -xaf mingw.tar.xz -C /usr
.build_win_template:
extends: .generic_win_template
stage: build
artifacts:
expire_in: 90 day
paths:
- minetest-*-win*/*
build:win32:
extends: .build_win_template
script:
- EXISTING_MINETEST_DIR=$PWD ./util/buildbot/buildwin32.sh build
- unzip -q build/build/*.zip
variables:
WIN_ARCH: "i686"
build:win64:
extends: .build_win_template
script:
- EXISTING_MINETEST_DIR=$PWD ./util/buildbot/buildwin64.sh build
- unzip -q build/build/*.zip
variables:
WIN_ARCH: "x86_64"
##
## Docker
##
package:docker:
stage: package
image: docker:stable
services:
- docker:dind
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
script:
- docker build . -t ${CONTAINER_IMAGE}/server:$CI_COMMIT_SHA -t ${CONTAINER_IMAGE}/server:$CI_COMMIT_REF_NAME -t ${CONTAINER_IMAGE}/server:latest
- docker push ${CONTAINER_IMAGE}/server:$CI_COMMIT_SHA
- 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
before_script:
- pip install git+https://github.com/Python-Markdown/markdown.git
- pip install git+https://github.com/mkdocs/mkdocs.git
- pip install pygments
script:
- cd doc/mkdocs && ./build.sh
artifacts:
paths:
- public
only:
- master
##
## AppImage
##
package:appimage-client:
stage: package
image: appimagecrafters/appimage-builder
needs:
- build:ubuntu-18.04
before_script:
- apt-get update -y
- apt-get install -y git
# Collect files
- mkdir AppDir
- cp -a artifact/minetest/usr/ AppDir/usr/
- rm AppDir/usr/bin/minetestserver
- 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
- 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:
expire_in: 90 day
paths:
- ./*.AppImage

82
.luacheckrc Normal file
View File

@ -0,0 +1,82 @@
unused_args = false
allow_defined_top = true
ignore = {
"131", -- Unused global variable
"431", -- Shadowing an upvalue
"432", -- Shadowing an upvalue argument
}
read_globals = {
"ItemStack",
"INIT",
"DIR_DELIM",
"dump", "dump2",
"fgettext", "fgettext_ne",
"vector",
"VoxelArea",
"profiler",
"Settings",
string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn", "indexof", "insert_all"}},
math = {fields = {"hypot", "round"}},
}
globals = {
"core",
"gamedata",
os = { fields = { "tempfolder" } },
"_",
}
files["builtin/client/register.lua"] = {
globals = {
debug = {fields={"getinfo"}},
}
}
files["builtin/common/misc_helpers.lua"] = {
globals = {
"dump", "dump2", "table", "math", "string",
"fgettext", "fgettext_ne", "basic_dump", "game", -- ???
"file_exists", "get_last_folder", "cleanup_path", -- ???
},
}
files["builtin/common/vector.lua"] = {
globals = { "vector" },
}
files["builtin/game/voxelarea.lua"] = {
globals = { "VoxelArea" },
}
files["builtin/game/init.lua"] = {
globals = { "profiler" },
}
files["builtin/common/filterlist.lua"] = {
globals = {
"filterlist",
"compare_worlds", "sort_worlds_alphabetic", "sort_mod_list", -- ???
},
}
files["builtin/mainmenu"] = {
globals = {
"gamedata",
},
read_globals = {
"PLATFORM",
},
}
files["builtin/common/tests"] = {
read_globals = {
"describe",
"it",
"assert",
},
}

69
.mailmap Normal file
View File

@ -0,0 +1,69 @@
# Documentation: https://git-scm.com/docs/git-check-mailmap#_mapping_authors
0gb.us <0gb.us@0gb.us> <us_0gb@laptop-0gb-us.0gb.us>
Calinou <calinou@opmbx.org> <calinou9999@gmail.com>
Calinou <calinou@opmbx.org> <calinou9999spam@gmail.com>
Perttu Ahola <celeron55@gmail.com>
Perttu Ahola <celeron55@gmail.com> celeron55 <celeron55@armada.(none)>
Zeno- <kde.psych@gmail.com>
Zeno- <kde.psych@gmail.com> <crobbins@localhost.localdomain>
Diego Martínez <kaeza@users.sf.net>
Diego Martínez <kaeza@users.sf.net> <lkaezadl3@gmail.com>
Ilya Zhuravlev <zhuravlevilya@ya.ru>
Ilya Zhuravlev <zhuravlevilya@ya.ru> <whatever@xyz.is>
kwolekr <kwolekr@minetest.net> <mirrorisim@gmail.com>
PilzAdam <pilzadam@minetest.net> <adam-k@outlook.com>
PilzAdam <pilzadam@minetest.net> <PilzAdam@gmx.de>
proller <proller@github.com> <proler@github.com>
proller <proller@github.com> <proler@gmail.com>
RealBadAngel <maciej.kasatkin@o2.pl> <mk@realbadangel.pl>
RealBadAngel <maciej.kasatkin@o2.pl> <maciej.kasatkin@yahoo.com>
Selat <LongExampleTestName@gmail.com> <LongExampletestName@gmail.com>
ShadowNinja <shadowninja@minetest.net> ShadowNinja <noreply@gmail.com>
Esteban I. Ruiz Moreno <exio4.com@gmail.com>
Esteban I. Ruiz Moreno <exio4.com@gmail.com> <me@exio4.xyz>
Lord James <neftali_dtctv@hotmail.com>
BlockMen <nmuelll@web.de>
sfan5 <sfan5@live.de>
DannyDark <the_skeleton_of_a_child@yahoo.co.uk>
Ilya Pavlov <TTChangeTheWorld@gmail.com>
sapier <Sapier at GMX dot net> sapier <sapier AT gmx DOT net>
sapier <Sapier at GMX dot net> sapier <sapier at gmx dot net>
SmallJoker <SmallJoker@users.noreply.github.com> <mk939@ymail.com>
Loïc Blot <nerzhul@users.noreply.github.com>
Loïc Blot <nerzhul@users.noreply.github.com> <loic.blot@unix-experience.fr>
numzero <numzer0@yandex.ru> Vitaliy <numzer0@yandex.ru>
numzero <numzer0@yandex.ru> <silverunicorn2011@yandex.ru>
Jean-Patrick Guerrero <kilbith@users.noreply.github.com>
Jean-Patrick Guerrero <kilbith@users.noreply.github.com> <jeanpatrick.guerrero@gmail.com>
HybridDog <3192173+HybridDog@users.noreply.github.com> <ovvv@web.de>
srfqi <muhammadrifqipriyosusanto@gmail.com>
Dániel Juhász <juhdanad@gmail.com>
rubenwardy <rw@rubenwardy.com>
rubenwardy <rw@rubenwardy.com> <rubenwardy@gmail.com>
Paul Ouellette <oue.paul18@gmail.com>
Vanessa Dannenberg <vanessa.e.dannenberg@gmail.com> <vanessaezekowitz@gmail.com>
ClobberXD <ClobberXD@gmail.com>
ClobberXD <ClobberXD@gmail.com> <ClobberXD@protonmail.com>
ClobberXD <ClobberXD@gmail.com> <36130650+ClobberXD@users.noreply.github.com>
Auke Kok <sofar+github@foo-projects.org>
Auke Kok <sofar+github@foo-projects.org> <sofar@foo-projects.org>
Desour <vorunbekannt75@web.de>
Nathanaëlle Courant <Ekdohibs@users.noreply.github.com> <nathanael.courant@laposte.net>
Ezhh <owlecho@live.com>
paramat <paramat@users.noreply.github.com>
paramat <paramat@users.noreply.github.com> <mat.gregory@virginmedia.com>
lhofhansl <lhofhansl@yahoo.com> <larsh@apache.org>
red-001 <red-001@outlook.ie> <red-001@openmailbox.org>
Wuzzy <Wuzzy@disroot.org> <wuzzy2@mail.ru>
Wuzzy <Wuzzy@disroot.org> <Wuzzy2@mail.ru>
Wuzzy <Wuzzy@disroot.org> <almikes@aol.com>
Jordach <jordach.snelling@gmail.com>
MoNTE48 <MoNTE48@mail.ua>
v-rob <robinsonvincent89@gmail.com>
v-rob <robinsonvincent89@gmail.com> <31123645+v-rob@users.noreply.github.com>
EvidenceB <49488517+EvidenceBKidscode@users.noreply.github.com>
gregorycu <gregory.currie@gmail.com>
Rogier <rogier777@gmail.com>
Rogier <rogier777@gmail.com> <Rogier-5@users.noreply.github.com>
x2048 <codeforsmile@gmail.com>

54
AppImageBuilder.yml Normal file
View File

@ -0,0 +1,54 @@
version: 1
AppDir:
path: ./AppDir
app_info:
id: minetest
name: Minetest
icon: minetest
version: !ENV ${VERSION}
exec: usr/bin/minetest
exec_args: $@
runtime:
env:
APPDIR_LIBRARY_PATH: $APPDIR/usr/lib/x86_64-linux-gnu
apt:
arch: amd64
sources:
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic main universe
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3b4fe6acc0b21f32'
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-updates main universe
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-backports main universe
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-security main universe
include:
- libc6
- libcurl3-gnutls
- libfreetype6
- libgl1
- libjpeg-turbo8
- libjsoncpp1
- libleveldb1v5
- libopenal1
- libpng16-16
- libsqlite3-0
- libstdc++6
- libvorbisfile3
- libx11-6
- libxxf86vm1
- zlib1g
files:
exclude:
- usr/share/man
- usr/share/doc/*/README.*
- usr/share/doc/*/changelog.*
- usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.*
AppImage:
update-information: None
sign-key: None
arch: x86_64

402
CMakeLists.txt Normal file
View File

@ -0,0 +1,402 @@
cmake_minimum_required(VERSION 3.5)
# Set policies up to 3.9 since we want to enable the IPO option
if(${CMAKE_VERSION} VERSION_LESS 3.9)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.9)
endif()
# This can be read from ${PROJECT_NAME} after project() is called
project(minetest)
set(PROJECT_NAME_CAPITALIZED "Minetest")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(GCC_MINIMUM_VERSION "5.1")
set(CLANG_MINIMUM_VERSION "3.5")
# Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing
set(VERSION_MAJOR 5)
set(VERSION_MINOR 6)
set(VERSION_PATCH 1)
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Change to false for releases
set(DEVELOPMENT_BUILD FALSE)
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
if(VERSION_EXTRA)
set(VERSION_STRING "${VERSION_STRING}-${VERSION_EXTRA}")
elseif(DEVELOPMENT_BUILD)
set(VERSION_STRING "${VERSION_STRING}-dev")
endif()
if (CMAKE_BUILD_TYPE STREQUAL Debug)
# Append "-debug" to version string
set(VERSION_STRING "${VERSION_STRING}-debug")
endif()
message(STATUS "*** Will build version ${VERSION_STRING} ***")
# Configuration options
set(DEFAULT_RUN_IN_PLACE FALSE)
if(WIN32)
set(DEFAULT_RUN_IN_PLACE TRUE)
endif()
set(RUN_IN_PLACE ${DEFAULT_RUN_IN_PLACE} CACHE BOOL
"Run directly in source directory structure")
set(BUILD_CLIENT TRUE CACHE BOOL "Build client")
set(BUILD_SERVER FALSE CACHE BOOL "Build server")
set(BUILD_UNITTESTS TRUE CACHE BOOL "Build unittests")
set(BUILD_BENCHMARKS FALSE CACHE BOOL "Build benchmarks")
set(WARN_ALL TRUE CACHE BOOL "Enable -Wall for Release build")
if(NOT CMAKE_BUILD_TYPE)
# Default to release
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type: Debug or Release" FORCE)
endif()
set(ENABLE_UPDATE_CHECKER (NOT ${DEVELOPMENT_BUILD}) CACHE BOOL
"Whether to enable update checks by default")
# Included stuff
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
set(IRRLICHTMT_BUILD_DIR "" CACHE PATH "Path to IrrlichtMt build directory.")
if(NOT "${IRRLICHTMT_BUILD_DIR}" STREQUAL "")
find_package(IrrlichtMt QUIET
PATHS "${IRRLICHTMT_BUILD_DIR}"
NO_DEFAULT_PATH
)
if(NOT TARGET IrrlichtMt::IrrlichtMt)
# find_package() searches certain subdirectories. ${PATH}/cmake is not
# the only one, but it is the one where IrrlichtMt is supposed to export
# IrrlichtMtConfig.cmake
message(FATAL_ERROR "Could not find IrrlichtMtConfig.cmake in ${IRRLICHTMT_BUILD_DIR}/cmake.")
endif()
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/lib/irrlichtmt")
message(STATUS "Using user-provided IrrlichtMt at subdirectory 'lib/irrlichtmt'")
if(BUILD_CLIENT)
# tell IrrlichtMt to create a static library
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared library" FORCE)
add_subdirectory(lib/irrlichtmt EXCLUDE_FROM_ALL)
unset(BUILD_SHARED_LIBS CACHE)
if(NOT TARGET IrrlichtMt)
message(FATAL_ERROR "IrrlichtMt project is missing a CMake target?!")
endif()
else()
add_library(IrrlichtMt::IrrlichtMt INTERFACE IMPORTED)
set_target_properties(IrrlichtMt::IrrlichtMt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/irrlichtmt/include")
endif()
else()
find_package(IrrlichtMt QUIET)
if(NOT TARGET IrrlichtMt::IrrlichtMt)
string(CONCAT explanation_msg
"The Minetest team has forked Irrlicht to make their own customizations. "
"It can be found here: https://github.com/minetest/irrlicht\n"
"For example use: git clone --depth=1 https://github.com/minetest/irrlicht lib/irrlichtmt\n")
if(BUILD_CLIENT)
message(FATAL_ERROR "IrrlichtMt is required to build the client, but it was not found.\n${explanation_msg}")
endif()
include(MinetestFindIrrlichtHeaders)
if(NOT IRRLICHT_INCLUDE_DIR)
message(FATAL_ERROR "IrrlichtMt headers are required to build the server, but none found.\n${explanation_msg}")
endif()
message(STATUS "Found IrrlichtMt headers: ${IRRLICHT_INCLUDE_DIR}")
add_library(IrrlichtMt::IrrlichtMt INTERFACE IMPORTED)
# Note that we can't use target_include_directories() since that doesn't work for IMPORTED targets before CMake 3.11
set_target_properties(IrrlichtMt::IrrlichtMt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${IRRLICHT_INCLUDE_DIR}")
endif()
endif()
if(BUILD_CLIENT AND TARGET IrrlichtMt::IrrlichtMt)
# retrieve version somehow
if(NOT IrrlichtMt_VERSION)
get_target_property(IrrlichtMt_VERSION IrrlichtMt VERSION)
endif()
message(STATUS "Found IrrlichtMt ${IrrlichtMt_VERSION}")
set(TARGET_VER_S 1.9.0mt8)
string(REPLACE "mt" "." TARGET_VER ${TARGET_VER_S})
if(IrrlichtMt_VERSION VERSION_LESS ${TARGET_VER})
message(FATAL_ERROR "At least IrrlichtMt ${TARGET_VER_S} is required to build")
elseif(NOT DEVELOPMENT_BUILD AND IrrlichtMt_VERSION VERSION_GREATER ${TARGET_VER})
message(FATAL_ERROR "IrrlichtMt ${TARGET_VER_S} is required to build")
endif()
endif()
# Installation
if(WIN32)
set(SHAREDIR ".")
set(BINDIR "bin")
set(DOCDIR "doc")
set(EXAMPLE_CONF_DIR ".")
set(LOCALEDIR "locale")
elseif(APPLE)
set(BUNDLE_NAME ${PROJECT_NAME}.app)
set(BUNDLE_PATH "${BUNDLE_NAME}")
set(BINDIR ${BUNDLE_NAME}/Contents/MacOS)
set(SHAREDIR ${BUNDLE_NAME}/Contents/Resources)
set(DOCDIR "${SHAREDIR}/${PROJECT_NAME}")
set(EXAMPLE_CONF_DIR ${DOCDIR})
set(LOCALEDIR "${SHAREDIR}/locale")
elseif(UNIX) # Linux, BSD etc
if(RUN_IN_PLACE)
set(SHAREDIR ".")
set(BINDIR "bin")
set(DOCDIR "doc")
set(EXAMPLE_CONF_DIR ".")
set(MANDIR "unix/man")
set(XDG_APPS_DIR "unix/applications")
set(APPDATADIR "unix/metainfo")
set(ICONDIR "unix/icons")
set(LOCALEDIR "locale")
else()
include(GNUInstallDirs)
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}")
set(BINDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
set(DOCDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}")
set(MANDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_MANDIR}")
set(EXAMPLE_CONF_DIR ${DOCDIR})
set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/applications")
set(APPDATADIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/metainfo")
set(ICONDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/icons")
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}")
endif()
endif()
set(CUSTOM_SHAREDIR "" CACHE STRING "Directory to install data files into")
if(NOT CUSTOM_SHAREDIR STREQUAL "")
set(SHAREDIR "${CUSTOM_SHAREDIR}")
message(STATUS "Using SHAREDIR=${SHAREDIR}")
endif()
set(CUSTOM_BINDIR "" CACHE STRING "Directory to install binaries into")
if(NOT CUSTOM_BINDIR STREQUAL "")
set(BINDIR "${CUSTOM_BINDIR}")
message(STATUS "Using BINDIR=${BINDIR}")
endif()
set(CUSTOM_DOCDIR "" CACHE STRING "Directory to install documentation into")
if(NOT CUSTOM_DOCDIR STREQUAL "")
set(DOCDIR "${CUSTOM_DOCDIR}")
if(NOT RUN_IN_PLACE)
set(EXAMPLE_CONF_DIR ${DOCDIR})
endif()
message(STATUS "Using DOCDIR=${DOCDIR}")
endif()
set(CUSTOM_MANDIR "" CACHE STRING "Directory to install manpages into")
if(NOT CUSTOM_MANDIR STREQUAL "")
set(MANDIR "${CUSTOM_MANDIR}")
message(STATUS "Using MANDIR=${MANDIR}")
endif()
set(CUSTOM_EXAMPLE_CONF_DIR "" CACHE STRING "Directory to install example config file into")
if(NOT CUSTOM_EXAMPLE_CONF_DIR STREQUAL "")
set(EXAMPLE_CONF_DIR "${CUSTOM_EXAMPLE_CONF_DIR}")
message(STATUS "Using EXAMPLE_CONF_DIR=${EXAMPLE_CONF_DIR}")
endif()
set(CUSTOM_XDG_APPS_DIR "" CACHE STRING "Directory to install .desktop files into")
if(NOT CUSTOM_XDG_APPS_DIR STREQUAL "")
set(XDG_APPS_DIR "${CUSTOM_XDG_APPS_DIR}")
message(STATUS "Using XDG_APPS_DIR=${XDG_APPS_DIR}")
endif()
set(CUSTOM_ICONDIR "" CACHE STRING "Directory to install icons into")
if(NOT CUSTOM_ICONDIR STREQUAL "")
set(ICONDIR "${CUSTOM_ICONDIR}")
message(STATUS "Using ICONDIR=${ICONDIR}")
endif()
set(CUSTOM_LOCALEDIR "" CACHE STRING "Directory to install l10n files into")
if(NOT CUSTOM_LOCALEDIR STREQUAL "")
set(LOCALEDIR "${CUSTOM_LOCALEDIR}")
message(STATUS "Using LOCALEDIR=${LOCALEDIR}")
endif()
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
if(RUN_IN_PLACE)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/mods/mods_here.txt" DESTINATION "${SHAREDIR}/mods")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/texture_packs_here.txt" DESTINATION "${SHAREDIR}/textures")
endif()
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game" DESTINATION "${SHAREDIR}/games/"
COMPONENT "SUBGAME_MINETEST_GAME" OPTIONAL PATTERN ".git*" EXCLUDE )
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/devtest" DESTINATION "${SHAREDIR}/games/"
COMPONENT "SUBGAME_MINIMAL" OPTIONAL PATTERN ".git*" EXCLUDE )
if(BUILD_CLIENT)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client/shaders" DESTINATION "${SHAREDIR}/client")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base")
if(RUN_IN_PLACE)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/clientmods" DESTINATION "${SHAREDIR}")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client/serverlist" DESTINATION "${SHAREDIR}/client")
endif()
endif()
install(FILES "README.md" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/lua_api.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/client_lua_api.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/menu_lua_api.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/texture_packs.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/world_format.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "minetest.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}")
if(UNIX AND NOT APPLE)
install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6")
install(FILES "misc/net.minetest.minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
install(FILES "misc/net.minetest.minetest.appdata.xml" DESTINATION "${APPDATADIR}")
install(FILES "misc/minetest.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
install(FILES "misc/minetest-xorg-icon-128.png"
DESTINATION "${ICONDIR}/hicolor/128x128/apps"
RENAME "minetest.png")
endif()
if(APPLE)
install(FILES "misc/minetest-icon.icns" DESTINATION "${SHAREDIR}")
install(FILES "misc/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents")
endif()
# Library pack
find_package(GMP REQUIRED)
find_package(Json REQUIRED)
find_package(Lua REQUIRED)
if(NOT USE_LUAJIT)
set(LUA_BIT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/bitop)
set(LUA_BIT_LIBRARY bitop)
add_subdirectory(lib/bitop)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${GCC_MINIMUM_VERSION}")
message(FATAL_ERROR "Insufficient gcc version, found ${CMAKE_CXX_COMPILER_VERSION}. "
"Version ${GCC_MINIMUM_VERSION} or higher is required.")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?Clang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${CLANG_MINIMUM_VERSION}")
message(FATAL_ERROR "Insufficient clang version, found ${CMAKE_CXX_COMPILER_VERSION}. "
"Version ${CLANG_MINIMUM_VERSION} or higher is required.")
endif()
endif()
if(BUILD_BENCHMARKS)
add_subdirectory(lib/catch2)
endif()
# Subdirectories
# Be sure to add all relevant definitions above this
add_subdirectory(src)
# CPack
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A free open-source voxel game engine with easy modding and game creation.")
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
set(CPACK_PACKAGE_VENDOR "celeron55")
set(CPACK_PACKAGE_CONTACT "Perttu Ahola <celeron55@gmail.com>")
include(CPackComponent)
cpack_add_component(Docs
DISPLAY_NAME "Documentation"
DESCRIPTION "Documentation about Minetest and Minetest modding"
)
cpack_add_component(SUBGAME_MINETEST_GAME
DISPLAY_NAME "Minetest Game"
DESCRIPTION "The default game bundled in the Minetest engine. Mainly used as a modding base."
GROUP "Games"
)
cpack_add_component(SUBGAME_MINIMAL
DISPLAY_NAME "Development Test"
DESCRIPTION "A basic testing environment used for engine development and sometimes for testing mods."
DISABLED #DISABLED does not mean it is disabled, and is just not selected by default.
GROUP "Games"
)
cpack_add_component_group(Subgames
DESCRIPTION "Games for the Minetest engine."
)
if(WIN32)
# Include all dynamically linked runtime libaries such as MSVCRxxx.dll
include(InstallRequiredSystemLibraries)
if(RUN_IN_PLACE)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-win64")
else()
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-win32")
endif()
set(CPACK_GENERATOR ZIP)
else()
set(CPACK_GENERATOR WIX)
set(CPACK_PACKAGE_NAME "${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
# http://wixtoolset.org/documentation/manual/v3/wixui/wixui_localization.html
#set(CPACK_WIX_CULTURES "ar-SA,bg-BG,ca-ES,hr-HR,cs-CZ,da-DK,nl-NL,en-US,et-EE,fi-FI,fr-FR,de-DE")
set(CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/misc/CPACK_WIX_UI_BANNER.BMP")
set(CPACK_WIX_UI_DIALOG "${CMAKE_CURRENT_SOURCE_DIR}/misc/CPACK_WIX_UI_DIALOG.BMP")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/doc/lgpl-2.1.txt")
# The correct way would be to include both x32 and x64 into one installer
# and install the appropriate one.
# CMake does not support that, so there are two separate GUID's
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CPACK_WIX_UPGRADE_GUID "745A0FB3-5552-44CA-A587-A91C397CCC56")
else()
set(CPACK_WIX_UPGRADE_GUID "814A2E2D-2779-4BBD-9ACD-FC3BD51FBBA2")
endif()
endif()
elseif(APPLE)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-osx")
set(CPACK_GENERATOR ZIP)
else()
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_STRING}-linux")
set(CPACK_GENERATOR TGZ)
set(CPACK_SOURCE_GENERATOR TGZ)
endif()
include(CPack)
# Add a target to generate API documentation with Doxygen
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/doc/Doxyfile @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doc/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
endif()

71
Dockerfile Normal file
View File

@ -0,0 +1,71 @@
ARG DOCKER_IMAGE=alpine:3.14
FROM $DOCKER_IMAGE AS builder
ENV MINETEST_GAME_VERSION master
ENV IRRLICHT_VERSION master
COPY .git /usr/src/minetest/.git
COPY CMakeLists.txt /usr/src/minetest/CMakeLists.txt
COPY README.md /usr/src/minetest/README.md
COPY minetest.conf.example /usr/src/minetest/minetest.conf.example
COPY builtin /usr/src/minetest/builtin
COPY cmake /usr/src/minetest/cmake
COPY doc /usr/src/minetest/doc
COPY fonts /usr/src/minetest/fonts
COPY lib /usr/src/minetest/lib
COPY misc /usr/src/minetest/misc
COPY po /usr/src/minetest/po
COPY src /usr/src/minetest/src
COPY textures /usr/src/minetest/textures
WORKDIR /usr/src/minetest
RUN apk add --no-cache git build-base cmake sqlite-dev curl-dev zlib-dev zstd-dev \
gmp-dev jsoncpp-dev postgresql-dev ninja luajit-dev ca-certificates && \
git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \
rm -fr ./games/minetest_game/.git
WORKDIR /usr/src/
RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ && \
cd prometheus-cpp && \
cmake -B build \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_BUILD_TYPE=Release \
-DENABLE_TESTING=0 \
-GNinja && \
cmake --build build && \
cmake --install build
RUN git clone --depth=1 https://github.com/minetest/irrlicht/ -b ${IRRLICHT_VERSION} && \
cp -r irrlicht/include /usr/include/irrlichtmt
WORKDIR /usr/src/minetest
RUN cmake -B build \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SERVER=TRUE \
-DENABLE_PROMETHEUS=TRUE \
-DBUILD_UNITTESTS=FALSE \
-DBUILD_CLIENT=FALSE \
-GNinja && \
cmake --build build && \
cmake --install build
ARG DOCKER_IMAGE=alpine:3.14
FROM $DOCKER_IMAGE AS runtime
RUN apk add --no-cache sqlite-libs curl gmp libstdc++ libgcc libpq luajit jsoncpp zstd-libs && \
adduser -D minetest --uid 30000 -h /var/lib/minetest && \
chown -R minetest:minetest /var/lib/minetest
WORKDIR /var/lib/minetest
COPY --from=builder /usr/local/share/minetest /usr/local/share/minetest
COPY --from=builder /usr/local/bin/minetestserver /usr/local/bin/minetestserver
COPY --from=builder /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/minetest.conf
USER minetest:minetest
EXPOSE 30000/udp 30000/tcp
CMD ["/usr/local/bin/minetestserver", "--config", "/etc/minetest/minetest.conf"]

206
LICENSE.txt Normal file
View File

@ -0,0 +1,206 @@
License of Minetest textures and sounds
---------------------------------------
This applies to textures and sounds contained in the main Minetest
distribution.
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
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/
textures/base/pack/server_public.png is under CC-BY 4.0, taken from Twitter's Twemoji set
https://creativecommons.org/licenses/by/4.0/
Authors of media files
-----------------------
Everything not listed in here:
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
ShadowNinja:
textures/base/pack/smoke_puff.png
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
textures/base/pack/end_icon.png
erlehmann:
misc/minetest-icon-24x24.png
misc/minetest-icon.ico
misc/minetest.svg
textures/base/pack/logo.png
JRottm:
textures/base/pack/player_marker.png
srifqi:
textures/base/pack/chat_hide_btn.png
textures/base/pack/chat_show_btn.png
textures/base/pack/joystick_bg.png
textures/base/pack/joystick_center.png
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
appgurueu:
textures/base/pack/server_incompatible.png
erlehmann, Warr1024, rollerozxa:
textures/base/pack/no_screenshot.png
kilbith:
textures/base/pack/server_favorite.png
SmallJoker
textures/base/pack/server_favorite_delete.png (based on server_favorite.png)
License of Minetest source code
-------------------------------
Minetest
Copyright (C) 2010-2018 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
Irrlicht
---------------
This program uses IrrlichtMt, Minetest's fork of
the Irrlicht Engine. http://irrlicht.sourceforge.net/
The Irrlicht Engine License
Copyright © 2002-2005 Nikolaus Gebhardt
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
JThread
---------------
This program uses the JThread library. License for JThread follows:
Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
Lua
---------------
Lua is licensed under the terms of the MIT license reproduced below.
This means that Lua is free software and can be used for both academic
and commercial purposes at absolutely no cost.
For details and rationale, see https://www.lua.org/license.html .
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Fonts
---------------
Bitstream Vera Fonts Copyright:
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.
Arimo - Apache License, version 2.0
Digitized data copyright (c) 2010-2012 Google Corporation.
Cousine - Apache License, version 2.0
Digitized data copyright (c) 2010-2012 Google Corporation.
DroidSansFallBackFull:
Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

480
README.md Normal file
View File

@ -0,0 +1,480 @@
Minetest
========
![Build Status](https://github.com/minetest/minetest/workflows/build/badge.svg)
[![Translation status](https://hosted.weblate.org/widgets/minetest/-/svg-badge.svg)](https://hosted.weblate.org/engage/minetest/?utm_source=widget)
[![License](https://img.shields.io/badge/license-LGPLv2.1%2B-blue.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
Minetest is a free open-source voxel game engine with easy modding and game creation.
Copyright (C) 2010-2022 Perttu Ahola <celeron55@gmail.com>
and contributors (see source file comments and the version control log)
In case you downloaded the source code
--------------------------------------
If you downloaded the Minetest Engine source code in which this file is
contained, you probably want to download the [Minetest Game](https://github.com/minetest/minetest_game/)
project too. See its README.txt for more information.
Table of Contents
------------------
1. [Further Documentation](#further-documentation)
2. [Default Controls](#default-controls)
3. [Paths](#paths)
4. [Configuration File](#configuration-file)
5. [Command-line Options](#command-line-options)
6. [Compiling](#compiling)
7. [Docker](#docker)
8. [Version Scheme](#version-scheme)
Further documentation
----------------------
- Website: https://minetest.net/
- Wiki: https://wiki.minetest.net/
- Developer wiki: https://dev.minetest.net/
- Forum: https://forum.minetest.net/
- GitHub: https://github.com/minetest/minetest/
- [doc/](doc/) directory of source distribution
Default controls
----------------
All controls are re-bindable using settings.
Some can be changed in the key config dialog in the settings tab.
| Button | Action |
|-------------------------------|----------------------------------------------------------------|
| Move mouse | Look around |
| W, A, S, D | Move |
| Space | Jump/move up |
| Shift | Sneak/move down |
| Q | Drop itemstack |
| Shift + Q | Drop single item |
| Left mouse button | Dig/punch/take item |
| Right mouse button | Place/use |
| Shift + right mouse button | Build (without using) |
| I | Inventory menu |
| Mouse wheel | Select item |
| 0-9 | Select item |
| Z | Zoom (needs zoom privilege) |
| T | Chat |
| / | Command |
| Esc | Pause menu/abort/exit (pauses only singleplayer game) |
| R | Enable/disable full range view |
| + | Increase view range |
| - | Decrease view range |
| K | Enable/disable fly mode (needs fly privilege) |
| P | Enable/disable pitch move mode |
| J | Enable/disable fast mode (needs fast privilege) |
| H | Enable/disable noclip mode (needs noclip privilege) |
| E | Aux1 (Move fast in fast mode. Games may add special features) |
| C | Cycle through camera modes |
| V | Cycle through minimap modes |
| Shift + V | Change minimap orientation |
| F1 | Hide/show HUD |
| F2 | Hide/show chat |
| F3 | Disable/enable fog |
| F4 | Disable/enable camera update (Mapblocks are not updated anymore when disabled, disabled in release builds) |
| F5 | Cycle through debug information screens |
| F6 | Cycle through profiler info screens |
| F10 | Show/hide console |
| F12 | Take screenshot |
Paths
-----
Locations:
* `bin` - Compiled binaries
* `share` - Distributed read-only data
* `user` - User-created modifiable data
Where each location is on each platform:
* Windows .zip / RUN_IN_PLACE source:
* `bin` = `bin`
* `share` = `.`
* `user` = `.`
* Windows installed:
* `bin` = `C:\Program Files\Minetest\bin (Depends on the install location)`
* `share` = `C:\Program Files\Minetest (Depends on the install location)`
* `user` = `%APPDATA%\Minetest`
* Linux installed:
* `bin` = `/usr/bin`
* `share` = `/usr/share/minetest`
* `user` = `~/.minetest`
* macOS:
* `bin` = `Contents/MacOS`
* `share` = `Contents/Resources`
* `user` = `Contents/User OR ~/Library/Application Support/minetest`
Worlds can be found as separate folders in: `user/worlds/`
Configuration file
------------------
- Default location:
`user/minetest.conf`
- This file is created by closing Minetest for the first time.
- A specific file can be specified on the command line:
`--config <path-to-file>`
- A run-in-place build will look for the configuration file in
`location_of_exe/../minetest.conf` and also `location_of_exe/../../minetest.conf`
Command-line options
--------------------
- Use `--help`
Compiling
---------
### Compiling on GNU/Linux
#### Dependencies
| Dependency | Version | Commentary |
|------------|---------|------------|
| GCC | 5.1+ | or Clang 3.5+ |
| CMake | 3.5+ | |
| IrrlichtMt | - | Custom version of Irrlicht, see https://github.com/minetest/irrlicht |
| Freetype | 2.0+ | |
| SQLite3 | 3+ | |
| Zstd | 1.0+ | |
| LuaJIT | 2.0+ | Bundled Lua 5.1 is used if not present |
| GMP | 5.0.0+ | Bundled mini-GMP is used if not present |
| JsonCPP | 1.0.0+ | Bundled JsonCPP is used if not present |
For Debian/Ubuntu users:
sudo apt install g++ make libc6-dev cmake libpng-dev libjpeg-dev libxi-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev libzstd-dev libluajit-5.1-dev
For Fedora users:
sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXi-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel spatialindex-devel libzstd-devel
For Arch users:
sudo pacman -S base-devel libcurl-gnutls cmake libxi libpng sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses zstd
For Alpine users:
sudo apk add build-base cmake libpng-dev jpeg-dev libxi-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev zstd-dev
#### Download
You can install Git for easily keeping your copy up to date.
If you dont want Git, read below on how to get the source without Git.
This is an example for installing Git on Debian/Ubuntu:
sudo apt install git
For Fedora users:
sudo dnf install git
Download source (this is the URL to the latest of source repository, which might not work at all times) using Git:
git clone --depth 1 https://github.com/minetest/minetest.git
cd minetest
Download minetest_game (otherwise only the "Development Test" game is available) using Git:
git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game
Download IrrlichtMt to `lib/irrlichtmt`, it will be used to satisfy the IrrlichtMt dependency that way:
git clone --depth 1 https://github.com/minetest/irrlicht.git lib/irrlichtmt
Download source, without using Git:
wget https://github.com/minetest/minetest/archive/master.tar.gz
tar xf master.tar.gz
cd minetest-master
Download minetest_game, without using Git:
cd games/
wget https://github.com/minetest/minetest_game/archive/master.tar.gz
tar xf master.tar.gz
mv minetest_game-master minetest_game
cd ..
Download IrrlichtMt, without using Git:
cd lib/
wget https://github.com/minetest/irrlicht/archive/master.tar.gz
tar xf master.tar.gz
mv irrlicht-master irrlichtmt
cd ..
#### Build
Build a version that runs directly from the source directory:
cmake . -DRUN_IN_PLACE=TRUE
make -j$(nproc)
Run it:
./bin/minetest
- Use `cmake . -LH` to see all CMake options and their current state.
- If you want to install it system-wide (or are making a distribution package),
you will want to use `-DRUN_IN_PLACE=FALSE`.
- You can build a bare server by specifying `-DBUILD_SERVER=TRUE`.
- You can disable the client build by specifying `-DBUILD_CLIENT=FALSE`.
- You can select between Release and Debug build by `-DCMAKE_BUILD_TYPE=<Debug or Release>`.
- Debug build is slower, but gives much more useful output in a debugger.
- If you build a bare server you don't need to compile IrrlichtMt, just the headers suffice.
- In that case use `-DIRRLICHT_INCLUDE_DIR=/some/where/irrlichtmt/include`.
- Minetest will use the IrrlichtMt package that is found first, given by the following order:
1. Specified `IRRLICHTMT_BUILD_DIR` CMake variable
2. `${PROJECT_SOURCE_DIR}/lib/irrlichtmt` (if existent)
3. Installation of IrrlichtMt in the system-specific library paths
4. For server builds with disabled `BUILD_CLIENT` variable, the headers from `IRRLICHT_INCLUDE_DIR` will be used.
- NOTE: Changing the IrrlichtMt build directory (includes system installs) requires regenerating the CMake cache (`rm CMakeCache.txt`)
### CMake options
General options and their default values:
BUILD_CLIENT=TRUE - Build Minetest client
BUILD_SERVER=FALSE - Build Minetest server
BUILD_UNITTESTS=TRUE - Build unittest sources
BUILD_BENCHMARKS=FALSE - Build benchmark sources
CMAKE_BUILD_TYPE=Release - Type of build (Release vs. Debug)
Release - Release build
Debug - Debug build
SemiDebug - Partially optimized debug build
RelWithDebInfo - Release build with debug information
MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible
ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http
ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal)
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations
ENABLE_GLES=OFF - Enable extra support code for OpenGL ES (requires support by IrrlichtMt)
ENABLE_LEVELDB=ON - Build with LevelDB; Enables use of LevelDB map backend
ENABLE_POSTGRESQL=ON - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended)
ENABLE_REDIS=ON - Build with libhiredis; Enables use of Redis map backend
ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores
ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds
ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua)
ENABLE_PROMETHEUS=OFF - Build with Prometheus metrics exporter (listens on tcp/30000 by default)
ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp)
ENABLE_SYSTEM_JSONCPP=ON - Use JsonCPP from system
RUN_IN_PLACE=FALSE - Create a portable install (worlds, settings etc. in current directory)
ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
USE_GPROF=FALSE - Enable profiling using GProf
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
ENABLE_TOUCH=FALSE - Enable Touchscreen support (requires support by IrrlichtMt)
Library specific options:
CURL_DLL - Only if building with cURL on Windows; path to libcurl.dll
CURL_INCLUDE_DIR - Only if building with cURL; directory where curl.h is located
CURL_LIBRARY - Only if building with cURL; path to libcurl.a/libcurl.so/libcurl.lib
EGL_INCLUDE_DIR - Only if building with GLES; directory that contains egl.h
EGL_LIBRARY - Only if building with GLES; path to libEGL.a/libEGL.so
EXTRA_DLL - Only on Windows; optional paths to additional DLLs that should be packaged
FREETYPE_INCLUDE_DIR_freetype2 - Directory that contains files such as ftimage.h
FREETYPE_INCLUDE_DIR_ft2build - Directory that contains ft2build.h
FREETYPE_LIBRARY - Path to libfreetype.a/libfreetype.so/freetype.lib
FREETYPE_DLL - Only on Windows; path to libfreetype-6.dll
GETTEXT_DLL - Only when building with gettext on Windows; paths to libintl + libiconv DLLs
GETTEXT_INCLUDE_DIR - Only when building with gettext; directory that contains iconv.h
GETTEXT_LIBRARY - Only when building with gettext on Windows; path to libintl.dll.a
GETTEXT_MSGFMT - Only when building with gettext; path to msgfmt/msgfmt.exe
IRRLICHT_DLL - Only on Windows; path to IrrlichtMt.dll
IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h (usable for server build only)
LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h
LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a
LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll
PostgreSQL_INCLUDE_DIR - Only when building with PostgreSQL; directory that contains libpq-fe.h
PostgreSQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so/libpq.lib
REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h
REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so
SPATIAL_INCLUDE_DIR - Only when building with LibSpatial; directory that contains spatialindex/SpatialIndex.h
SPATIAL_LIBRARY - Only when building with LibSpatial; path to libspatialindex_c.so/spatialindex-32.lib
LUA_INCLUDE_DIR - Only if you want to use LuaJIT; directory where luajit.h is located
LUA_LIBRARY - Only if you want to use LuaJIT; path to libluajit.a/libluajit.so
OGG_DLL - Only if building with sound on Windows; path to libogg.dll
OGG_INCLUDE_DIR - Only if building with sound; directory that contains an ogg directory which contains ogg.h
OGG_LIBRARY - Only if building with sound; path to libogg.a/libogg.so/libogg.dll.a
OPENAL_DLL - Only if building with sound on Windows; path to OpenAL32.dll
OPENAL_INCLUDE_DIR - Only if building with sound; directory where al.h is located
OPENAL_LIBRARY - Only if building with sound; path to libopenal.a/libopenal.so/OpenAL32.lib
SQLITE3_INCLUDE_DIR - Directory that contains sqlite3.h
SQLITE3_LIBRARY - Path to libsqlite3.a/libsqlite3.so/sqlite3.lib
VORBISFILE_LIBRARY - Only if building with sound; path to libvorbisfile.a/libvorbisfile.so/libvorbisfile.dll.a
VORBIS_DLL - Only if building with sound on Windows; paths to vorbis DLLs
VORBIS_INCLUDE_DIR - Only if building with sound; directory that contains a directory vorbis with vorbisenc.h inside
VORBIS_LIBRARY - Only if building with sound; path to libvorbis.a/libvorbis.so/libvorbis.dll.a
ZLIB_DLL - Only on Windows; path to zlib1.dll
ZLIB_INCLUDE_DIR - Directory that contains zlib.h
ZLIB_LIBRARY - Path to libz.a/libz.so/zlib.lib
ZSTD_DLL - Only on Windows; path to libzstd.dll
ZSTD_INCLUDE_DIR - Directory that contains zstd.h
ZSTD_LIBRARY - Path to libzstd.a/libzstd.so/ztd.lib
### Compiling on Windows using MSVC
### Requirements
- [Visual Studio 2015 or newer](https://visualstudio.microsoft.com)
- [CMake](https://cmake.org/download/)
- [vcpkg](https://github.com/Microsoft/vcpkg)
- [Git](https://git-scm.com/downloads)
### Compiling and installing the dependencies
It is highly recommended to use vcpkg as package manager.
After you successfully built vcpkg you can easily install the required libraries:
```powershell
vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp opengl-registry --triplet x64-windows
```
- **Don't forget about IrrlichtMt.** The easiest way is to clone it to `lib/irrlichtmt` as described in the Linux section.
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
- `gmp` and `jsoncpp` are optional, otherwise the bundled versions will be compiled
There are other optional libraries, but they are not tested if they can build and link correctly.
Use `--triplet` to specify the target triplet, e.g. `x64-windows` or `x86-windows`.
### Compile Minetest
#### a) Using the vcpkg toolchain and CMake GUI
1. Start up the CMake GUI
2. Select **Browse Source...** and select DIR/minetest
3. Select **Browse Build...** and select DIR/minetest-build
4. Select **Configure**
5. Choose the right visual Studio version and target platform. It has to match the version of the installed dependencies
6. Choose **Specify toolchain file for cross-compiling**
7. Click **Next**
8. Select the vcpkg toolchain file e.g. `D:/vcpkg/scripts/buildsystems/vcpkg.cmake`
9. Click Finish
10. Wait until cmake have generated the cash file
11. If there are any errors, solve them and hit **Configure**
12. Click **Generate**
13. Click **Open Project**
14. Compile Minetest inside Visual studio.
#### b) Using the vcpkg toolchain and the commandline
Run the following script in PowerShell:
```powershell
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=OFF -DENABLE_CURSES=OFF
cmake --build . --config Release
```
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.
### Windows Installer using WiX Toolset
Requirements:
* [Visual Studio 2017](https://visualstudio.microsoft.com/)
* [WiX Toolset](https://wixtoolset.org/)
In the Visual Studio 2017 Installer select **Optional Features -> WiX Toolset**.
Build the binaries as described above, but make sure you unselect `RUN_IN_PLACE`.
Open the generated project file with Visual Studio. Right-click **Package** and choose **Generate**.
It may take some minutes to generate the installer.
### Compiling on MacOS
#### Requirements
- [Homebrew](https://brew.sh/)
- [Git](https://git-scm.com/downloads)
Install dependencies with homebrew:
```
brew install cmake freetype gettext gmp hiredis jpeg jsoncpp leveldb libogg libpng libvorbis luajit zstd
```
#### Download
Download source (this is the URL to the latest of source repository, which might not work at all times) using Git:
```bash
git clone --depth 1 https://github.com/minetest/minetest.git
cd minetest
```
Download minetest_game (otherwise only the "Development Test" game is available) using Git:
```
git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game
```
Download Minetest's fork of Irrlicht:
```
git clone --depth 1 https://github.com/minetest/irrlicht.git lib/irrlichtmt
```
#### Build
```bash
mkdir build
cd build
cmake .. \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14 \
-DCMAKE_FIND_FRAMEWORK=LAST \
-DCMAKE_INSTALL_PREFIX=../build/macos/ \
-DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE
make -j$(sysctl -n hw.logicalcpu)
make install
```
#### Run
```
open ./build/macos/minetest.app
```
Docker
------
We provide Minetest server Docker images using the GitLab mirror registry.
Images are built on each commit and available using the following tag scheme:
* `registry.gitlab.com/minetest/minetest/server:latest` (latest build)
* `registry.gitlab.com/minetest/minetest/server:<branch/tag>` (current branch or current tag)
* `registry.gitlab.com/minetest/minetest/server:<commit-id>` (current commit id)
If you want to test it on a Docker server you can easily run:
sudo docker run registry.gitlab.com/minetest/minetest/server:<docker tag>
If you want to use it in a production environment you should use volumes bound to the Docker host
to persist data and modify the configuration:
sudo docker create -v /home/minetest/data/:/var/lib/minetest/ -v /home/minetest/conf/:/etc/minetest/ registry.gitlab.com/minetest/minetest/server:master
Data will be written to `/home/minetest/data` on the host, and configuration will be read from `/home/minetest/conf/minetest.conf`.
**Note:** If you don't understand the previous commands please read the official Docker documentation before use.
You can also host your Minetest server inside a Kubernetes cluster. See our example implementation in [`misc/kubernetes.yml`](misc/kubernetes.yml).
Version scheme
--------------
We use `major.minor.patch` since 5.0.0-dev. Prior to that we used `0.major.minor`.
- Major is incremented when the release contains breaking changes, all other
numbers are set to 0.
- Minor is incremented when the release contains new non-breaking features,
patch is set to 0.
- Patch is incremented when the release only contains bugfixes and very
minor/trivial features considered necessary.
Since 5.0.0-dev and 0.4.17-dev, the dev notation refers to the next release,
i.e.: 5.0.0-dev is the development version leading to 5.0.0.
Prior to that we used `previous_version-dev`.

11
android/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
*.iml
.externalNativeBuild
.gradle
app/build
app/release
app/src/main/assets
build
local.properties
native/.*
native/build
native/deps

116
android/app/build.gradle Normal file
View File

@ -0,0 +1,116 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion '30.0.3'
ndkVersion "$ndk_version"
defaultConfig {
applicationId 'net.minetest.minetest'
minSdkVersion 16
targetSdkVersion 30
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
versionCode project.versionCode
}
// load properties
Properties props = new Properties()
def propfile = file('../local.properties')
if (propfile.exists())
props.load(new FileInputStream(propfile))
if (props.getProperty('keystore') != null) {
signingConfigs {
release {
storeFile file(props['keystore'])
storePassword props['keystore.password']
keyAlias props['key']
keyPassword props['key.password']
}
}
buildTypes {
release {
minifyEnabled true
signingConfig signingConfigs.release
}
}
}
// for multiple APKs
splits {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
task prepareAssets() {
def assetsFolder = "build/assets"
def projRoot = "../.."
def gameToCopy = "minetest_game"
copy {
from "${projRoot}/minetest.conf.example", "${projRoot}/README.md" into assetsFolder
}
copy {
from "${projRoot}/doc/lgpl-2.1.txt" into "${assetsFolder}"
}
copy {
from "${projRoot}/builtin" into "${assetsFolder}/builtin"
}
copy {
from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders"
}
copy {
from "../native/deps/armeabi-v7a/Irrlicht/Shaders" into "${assetsFolder}/client/shaders/Irrlicht"
}
copy {
from "${projRoot}/fonts" include "*.ttf" into "${assetsFolder}/fonts"
}
copy {
from "${projRoot}/games/${gameToCopy}" into "${assetsFolder}/games/${gameToCopy}"
}
fileTree("${projRoot}/po").include("**/*.po").forEach { poFile ->
def moPath = "${assetsFolder}/locale/${poFile.parentFile.name}/LC_MESSAGES/"
file(moPath).mkdirs()
exec {
commandLine 'msgfmt', '-o', "${moPath}/minetest.mo", poFile
}
}
copy {
from "${projRoot}/textures" into "${assetsFolder}/textures"
}
file("${assetsFolder}/.nomedia").text = "";
task zipAssets(type: Zip) {
archiveName "Minetest.zip"
from "${assetsFolder}"
destinationDir file("src/main/assets")
}
}
preBuild.dependsOn zipAssets
// Map for the version code that gives each ABI a value.
import com.android.build.OutputFile
def abiCodes = ['armeabi-v7a': 0, 'arm64-v8a': 1]
android.applicationVariants.all { variant ->
variant.outputs.each {
output ->
def abiName = output.getFilter(OutputFile.ABI)
output.versionCodeOverride = abiCodes.get(abiName, 0) + variant.versionCode
}
}
dependencies {
implementation project(':native')
implementation 'androidx.appcompat:appcompat:1.3.1'
}

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="net.minetest.minetest"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--
`android:requestLegacyExternalStorage="true"` is workaround for using `/sdcard`
instead of the `getFilesDir()` patch for assets. Check link below for more information:
https://developer.android.com/training/data-storage/compatibility
-->
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/label"
android:requestLegacyExternalStorage="true"
android:resizeableActivity="false"
tools:ignore="UnusedAttribute">
<meta-data
android:name="android.max_aspect"
android:value="3.0" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
android:maxAspectRatio="3.0"
android:screenOrientation="sensorLandscape"
android:theme="@style/AppTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".GameActivity"
android:configChanges="orientation|keyboard|keyboardHidden|navigation|screenSize|smallestScreenSize"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:maxAspectRatio="3.0"
android:screenOrientation="sensorLandscape"
android:theme="@style/AppTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="Minetest" />
</activity>
<service
android:name=".UnzipService"
android:enabled="true"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="net.minetest.minetest.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
</manifest>

View File

@ -0,0 +1,45 @@
/*
Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
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.
*/
package net.minetest.minetest;
import android.content.Context;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import androidx.appcompat.widget.AppCompatEditText;
import java.util.Objects;
public class CustomEditText extends AppCompatEditText {
public CustomEditText(Context context) {
super(context);
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
InputMethodManager mgr = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
Objects.requireNonNull(mgr).hideSoftInputFromWindow(this.getWindowToken(), 0);
}
return false;
}
}

View File

@ -0,0 +1,207 @@
/*
Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
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.
*/
package net.minetest.minetest;
import android.app.NativeActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.annotation.Keep;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import java.io.File;
import java.util.Objects;
// Native code finds these methods by name (see porting_android.cpp).
// This annotation prevents the minifier/Proguard from mangling them.
@Keep
public class GameActivity extends NativeActivity {
static {
System.loadLibrary("c++_shared");
System.loadLibrary("Minetest");
}
private int messageReturnCode = -1;
private String messageReturnValue = "";
public static native void putMessageBoxResult(String text);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void makeFullScreen() {
if (Build.VERSION.SDK_INT >= 19)
this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
makeFullScreen();
}
@Override
protected void onResume() {
super.onResume();
makeFullScreen();
}
@Override
public void onBackPressed() {
// Ignore the back press so Minetest can handle it
}
public void showDialog(String acceptButton, String hint, String current, int editType) {
runOnUiThread(() -> showDialogUI(hint, current, editType));
}
private void showDialogUI(String hint, String current, int editType) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
LinearLayout container = new LinearLayout(this);
container.setOrientation(LinearLayout.VERTICAL);
builder.setView(container);
AlertDialog alertDialog = builder.create();
EditText editText;
// For multi-line, do not close the dialog after pressing back button
if (editType == 1) {
editText = new EditText(this);
} else {
editText = new CustomEditText(this);
}
container.addView(editText);
editText.setMaxLines(8);
editText.requestFocus();
editText.setHint(hint);
editText.setText(current);
final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
Objects.requireNonNull(imm).toggleSoftInput(InputMethodManager.SHOW_FORCED,
InputMethodManager.HIDE_IMPLICIT_ONLY);
if (editType == 1)
editText.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_MULTI_LINE);
else if (editType == 3)
editText.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_PASSWORD);
else
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setSelection(editText.getText().length());
editText.setOnKeyListener((view, keyCode, event) -> {
// For multi-line, do not submit the text after pressing Enter key
if (keyCode == KeyEvent.KEYCODE_ENTER && editType != 1) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
messageReturnCode = 0;
messageReturnValue = editText.getText().toString();
alertDialog.dismiss();
return true;
}
return false;
});
// For multi-line, add Done button since Enter key does not submit text
if (editType == 1) {
Button doneButton = new Button(this);
container.addView(doneButton);
doneButton.setText(R.string.ime_dialog_done);
doneButton.setOnClickListener((view -> {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
messageReturnCode = 0;
messageReturnValue = editText.getText().toString();
alertDialog.dismiss();
}));
}
alertDialog.show();
alertDialog.setOnCancelListener(dialog -> {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
messageReturnValue = current;
messageReturnCode = -1;
});
}
public int getDialogState() {
return messageReturnCode;
}
public String getDialogValue() {
messageReturnCode = -1;
return messageReturnValue;
}
public float getDensity() {
return getResources().getDisplayMetrics().density;
}
public int getDisplayHeight() {
return getResources().getDisplayMetrics().heightPixels;
}
public int getDisplayWidth() {
return getResources().getDisplayMetrics().widthPixels;
}
public void openURI(String uri) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(browserIntent);
}
public String getUserDataPath() {
return Utils.getUserDataDirectory(this).getAbsolutePath();
}
public String getCachePath() {
return Utils.getCacheDirectory(this).getAbsolutePath();
}
public void shareFile(String path) {
File file = new File(path);
if (!file.exists()) {
Log.e("GameActivity", "File " + file.getAbsolutePath() + " doesn't exist");
return;
}
Uri fileUri = FileProvider.getUriForFile(this, "net.minetest.minetest.fileprovider", file);
Intent intent = new Intent(Intent.ACTION_SEND, fileUri);
intent.setDataAndType(fileUri, getContentResolver().getType(fileUri));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
Intent shareIntent = Intent.createChooser(intent, null);
startActivity(shareIntent);
}
}

View File

@ -0,0 +1,185 @@
/*
Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
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.
*/
package net.minetest.minetest;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static net.minetest.minetest.UnzipService.*;
public class MainActivity extends AppCompatActivity {
private final static int versionCode = BuildConfig.VERSION_CODE;
private final static int PERMISSIONS = 1;
private static final String[] REQUIRED_SDK_PERMISSIONS =
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static final String SETTINGS = "MinetestSettings";
private static final String TAG_VERSION_CODE = "versionCode";
private ProgressBar mProgressBar;
private TextView mTextView;
private SharedPreferences sharedPreferences;
private final BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int progress = 0;
@StringRes int message = 0;
if (intent != null) {
progress = intent.getIntExtra(ACTION_PROGRESS, 0);
message = intent.getIntExtra(ACTION_PROGRESS_MESSAGE, 0);
}
if (progress == FAILURE) {
Toast.makeText(MainActivity.this, intent.getStringExtra(ACTION_FAILURE), Toast.LENGTH_LONG).show();
finish();
} else if (progress == SUCCESS) {
startNative();
} else {
if (mProgressBar != null) {
mProgressBar.setVisibility(View.VISIBLE);
if (progress == INDETERMINATE) {
mProgressBar.setIndeterminate(true);
} else {
mProgressBar.setIndeterminate(false);
mProgressBar.setProgress(progress);
}
}
mTextView.setVisibility(View.VISIBLE);
if (message != 0)
mTextView.setText(message);
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter(ACTION_UPDATE);
registerReceiver(myReceiver, filter);
mProgressBar = findViewById(R.id.progressBar);
mTextView = findViewById(R.id.textView);
sharedPreferences = getSharedPreferences(SETTINGS, Context.MODE_PRIVATE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
checkPermission();
else
checkAppVersion();
}
private void checkPermission() {
final List<String> missingPermissions = new ArrayList<>();
for (final String permission : REQUIRED_SDK_PERMISSIONS) {
final int result = ContextCompat.checkSelfPermission(this, permission);
if (result != PackageManager.PERMISSION_GRANTED)
missingPermissions.add(permission);
}
if (!missingPermissions.isEmpty()) {
final String[] permissions = missingPermissions
.toArray(new String[0]);
ActivityCompat.requestPermissions(this, permissions, PERMISSIONS);
} else {
final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length];
Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
onRequestPermissionsResult(PERMISSIONS, REQUIRED_SDK_PERMISSIONS, grantResults);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSIONS) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, R.string.not_granted, Toast.LENGTH_LONG).show();
finish();
return;
}
}
checkAppVersion();
}
}
private void checkAppVersion() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(this, R.string.no_external_storage, Toast.LENGTH_LONG).show();
finish();
return;
}
if (UnzipService.getIsRunning()) {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setIndeterminate(true);
mTextView.setVisibility(View.VISIBLE);
} else if (sharedPreferences.getInt(TAG_VERSION_CODE, 0) == versionCode &&
Utils.isInstallValid(this)) {
startNative();
} else {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setIndeterminate(true);
mTextView.setVisibility(View.VISIBLE);
Intent intent = new Intent(this, UnzipService.class);
startService(intent);
}
}
private void startNative() {
sharedPreferences.edit().putInt(TAG_VERSION_CODE, versionCode).apply();
Intent intent = new Intent(this, GameActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
@Override
public void onBackPressed() {
// Prevent abrupt interruption when copy game files from assets
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myReceiver);
}
}

View File

@ -0,0 +1,259 @@
/*
Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
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.
*/
package net.minetest.minetest;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Environment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class UnzipService extends IntentService {
public static final String ACTION_UPDATE = "net.minetest.minetest.UPDATE";
public static final String ACTION_PROGRESS = "net.minetest.minetest.PROGRESS";
public static final String ACTION_PROGRESS_MESSAGE = "net.minetest.minetest.PROGRESS_MESSAGE";
public static final String ACTION_FAILURE = "net.minetest.minetest.FAILURE";
public static final int SUCCESS = -1;
public static final int FAILURE = -2;
public static final int INDETERMINATE = -3;
private final int id = 1;
private NotificationManager mNotifyManager;
private boolean isSuccess = true;
private String failureMessage;
private static boolean isRunning = false;
public static synchronized boolean getIsRunning() {
return isRunning;
}
private static synchronized void setIsRunning(boolean v) {
isRunning = v;
}
public UnzipService() {
super("net.minetest.minetest.UnzipService");
}
@Override
protected void onHandleIntent(Intent intent) {
Notification.Builder notificationBuilder = createNotification();
final File zipFile = new File(getCacheDir(), "Minetest.zip");
try {
setIsRunning(true);
File userDataDirectory = Utils.getUserDataDirectory(this);
if (userDataDirectory == null) {
throw new IOException("Unable to find user data directory");
}
try (InputStream in = this.getAssets().open(zipFile.getName())) {
try (OutputStream out = new FileOutputStream(zipFile)) {
int readLen;
byte[] readBuffer = new byte[16384];
while ((readLen = in.read(readBuffer)) != -1) {
out.write(readBuffer, 0, readLen);
}
}
}
migrate(notificationBuilder, userDataDirectory);
unzip(notificationBuilder, zipFile, userDataDirectory);
} catch (IOException e) {
isSuccess = false;
failureMessage = e.getLocalizedMessage();
} finally {
setIsRunning(false);
zipFile.delete();
}
}
private Notification.Builder createNotification() {
String name = "net.minetest.minetest";
String channelId = "Minetest channel";
String description = "notifications from Minetest";
Notification.Builder builder;
if (mNotifyManager == null)
mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = null;
if (mNotifyManager != null)
mChannel = mNotifyManager.getNotificationChannel(channelId);
if (mChannel == null) {
mChannel = new NotificationChannel(channelId, name, importance);
mChannel.setDescription(description);
// Configure the notification channel, NO SOUND
mChannel.setSound(null, null);
mChannel.enableLights(false);
mChannel.enableVibration(false);
mNotifyManager.createNotificationChannel(mChannel);
}
builder = new Notification.Builder(this, channelId);
} else {
builder = new Notification.Builder(this);
}
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
builder.setContentTitle(getString(R.string.notification_title))
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(getString(R.string.notification_description))
.setContentIntent(intent)
.setOngoing(true)
.setProgress(0, 0, true);
mNotifyManager.notify(id, builder.build());
return builder;
}
private void unzip(Notification.Builder notificationBuilder, File zipFile, File userDataDirectory) throws IOException {
int per = 0;
int size;
try (ZipFile zipSize = new ZipFile(zipFile)) {
size = zipSize.size();
}
int readLen;
byte[] readBuffer = new byte[16384];
try (FileInputStream fileInputStream = new FileInputStream(zipFile);
ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) {
ZipEntry ze;
while ((ze = zipInputStream.getNextEntry()) != null) {
if (ze.isDirectory()) {
++per;
Utils.createDirs(userDataDirectory, ze.getName());
continue;
}
publishProgress(notificationBuilder, R.string.loading, 100 * ++per / size);
try (OutputStream outputStream = new FileOutputStream(
new File(userDataDirectory, ze.getName()))) {
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
outputStream.write(readBuffer, 0, readLen);
}
}
}
}
}
void moveFileOrDir(@NonNull File src, @NonNull File dst) throws IOException {
try {
Process p = new ProcessBuilder("/system/bin/mv",
src.getAbsolutePath(), dst.getAbsolutePath()).start();
int exitcode = p.waitFor();
if (exitcode != 0)
throw new IOException("Move failed with exit code " + exitcode);
} catch (InterruptedException e) {
throw new IOException("Move operation interrupted");
}
}
boolean recursivelyDeleteDirectory(@NonNull File loc) {
try {
Process p = new ProcessBuilder("/system/bin/rm", "-rf",
loc.getAbsolutePath()).start();
return p.waitFor() == 0;
} catch (IOException | InterruptedException e) {
return false;
}
}
/**
* Migrates user data from deprecated external storage to app scoped storage
*/
private void migrate(Notification.Builder notificationBuilder, File newLocation) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return;
}
File oldLocation = new File(Environment.getExternalStorageDirectory(), "Minetest");
if (!oldLocation.isDirectory())
return;
publishProgress(notificationBuilder, R.string.migrating, 0);
newLocation.mkdir();
String[] dirs = new String[] { "worlds", "games", "mods", "textures", "client" };
for (int i = 0; i < dirs.length; i++) {
publishProgress(notificationBuilder, R.string.migrating, 100 * i / dirs.length);
File dir = new File(oldLocation, dirs[i]), dir2 = new File(newLocation, dirs[i]);
if (dir.isDirectory() && !dir2.isDirectory()) {
moveFileOrDir(dir, dir2);
}
}
for (String filename : new String[] { "minetest.conf" }) {
File file = new File(oldLocation, filename), file2 = new File(newLocation, filename);
if (file.isFile() && !file2.isFile()) {
moveFileOrDir(file, file2);
}
}
recursivelyDeleteDirectory(oldLocation);
}
private void publishProgress(@Nullable Notification.Builder notificationBuilder, @StringRes int message, int progress) {
Intent intentUpdate = new Intent(ACTION_UPDATE);
intentUpdate.putExtra(ACTION_PROGRESS, progress);
intentUpdate.putExtra(ACTION_PROGRESS_MESSAGE, message);
if (!isSuccess)
intentUpdate.putExtra(ACTION_FAILURE, failureMessage);
sendBroadcast(intentUpdate);
if (notificationBuilder != null) {
notificationBuilder.setContentText(getString(message));
if (progress == INDETERMINATE) {
notificationBuilder.setProgress(100, 50, true);
} else {
notificationBuilder.setProgress(100, progress, false);
}
mNotifyManager.notify(id, notificationBuilder.build());
}
}
@Override
public void onDestroy() {
super.onDestroy();
mNotifyManager.cancel(id);
publishProgress(null, R.string.loading, isSuccess ? SUCCESS : FAILURE);
}
}

View File

@ -0,0 +1,39 @@
package net.minetest.minetest;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.File;
public class Utils {
public static @NonNull File createDirs(File root, String dir) {
File f = new File(root, dir);
if (!f.isDirectory())
f.mkdirs();
return f;
}
public static @Nullable File getUserDataDirectory(Context context) {
File extDir = context.getExternalFilesDir(null);
if (extDir == null) {
return null;
}
return createDirs(extDir, "Minetest");
}
public static @Nullable File getCacheDirectory(Context context) {
return context.getCacheDir();
}
public static boolean isInstallValid(Context context) {
File userDataDirectory = getUserDataDirectory(context);
return userDataDirectory != null && userDataDirectory.isDirectory() &&
new File(userDataDirectory, "games").isDirectory() &&
new File(userDataDirectory, "builtin").isDirectory() &&
new File(userDataDirectory, "client").isDirectory() &&
new File(userDataDirectory, "textures").isDirectory();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 B

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/background"
android:tileMode="repeat" />

View File

@ -0,0 +1,33 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg">
<ProgressBar
android:id="@+id/progressBar"
style="@style/CustomProgressBar"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:layout_marginLeft="90dp"
android:layout_marginRight="90dp"
android:indeterminate="false"
android:max="100"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progressBar"
android:layout_centerInParent="true"
android:background="@android:color/transparent"
android:text="@string/loading"
android:textColor="#FEFEFE"
android:visibility="gone"
tools:visibility="visible" />
</RelativeLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="label">Minetest</string>
<string name="loading">Loading&#8230;</string>
<string name="migrating">Migrating save data from old install&#8230; (this may take a while)</string>
<string name="not_granted">Required permission wasn\'t granted, Minetest can\'t run without it</string>
<string name="notification_title">Loading Minetest</string>
<string name="notification_description">Less than 1 minute&#8230;</string>
<string name="ime_dialog_done">Done</string>
<string name="no_external_storage">External storage isn\'t available. If you use an SDCard, please reinsert it. Otherwise, try restarting your phone or contacting the Minetest developers</string>
</resources>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@drawable/bg</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
</style>
<style name="CustomProgressBar" parent="Widget.AppCompat.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item>
</style>
</resources>

View File

@ -0,0 +1,3 @@
<paths>
<external-files-path path="Minetest/" name="minetest" />
</paths>

37
android/build.gradle Normal file
View File

@ -0,0 +1,37 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
project.ext.set("versionMajor", 5) // Version Major
project.ext.set("versionMinor", 6) // Version Minor
project.ext.set("versionPatch", 0) // Version Patch
project.ext.set("versionExtra", "") // Version Extra
project.ext.set("versionCode", 42) // Android Version Code
project.ext.set("developmentBuild", 0) // Whether it is a development build, or a release
// NOTE: +2 after each release!
// +1 for ARM and +1 for ARM64 APK's, because
// each APK must have a larger `versionCode` than the previous
buildscript {
ext.ndk_version = '23.2.8568313'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath 'de.undercouch:gradle-download-task:4.1.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
delete 'native/deps'
}

11
android/gradle.properties Normal file
View File

@ -0,0 +1,11 @@
<#if isLowMemory>
org.gradle.jvmargs=-Xmx4G -XX:MaxPermSize=2G -XX:+HeapDumpOnOutOfMemoryError
<#else>
org.gradle.jvmargs=-Xmx16G -XX:MaxPermSize=8G -XX:+HeapDumpOnOutOfMemoryError
</#if>
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.parallel.threads=8
org.gradle.configureondemand=true
android.enableJetifier=true
android.useAndroidX=true

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip

188
android/gradlew vendored Normal file
View File

@ -0,0 +1,188 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
command -v java >/dev/null || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

100
android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,100 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

143
android/icons/aux1_btn.svg Normal file
View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="24.000002"
inkscape:export-xdpi="24.000002"
inkscape:export-filename="/home/stu/Desktop/icons/png/aux_btn.png"
sodipodi:docname="aux_btn.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
id="svg8"
version="1.1"
viewBox="0 0 135.46666 135.46667"
height="512"
width="512">
<defs
id="defs2" />
<sodipodi:namedview
inkscape:document-rotation="0"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-others="true"
inkscape:snap-object-midpoints="false"
inkscape:snap-to-guides="true"
inkscape:snap-bbox="true"
showguides="true"
inkscape:snap-page="true"
inkscape:snap-grids="false"
inkscape:pagecheckerboard="false"
inkscape:window-maximized="1"
inkscape:window-y="31"
inkscape:window-x="0"
inkscape:window-height="1024"
inkscape:window-width="1920"
units="px"
showgrid="true"
inkscape:current-layer="layer2"
inkscape:document-units="mm"
inkscape:cy="212.91276"
inkscape:cx="201.43176"
inkscape:zoom="1.4633894"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#404040"
id="base">
<inkscape:grid
empopacity="0.25098039"
empcolor="#40ff40"
opacity="0.1254902"
color="#40ff40"
empspacing="4"
spacingy="0.26458333"
spacingx="0.26458333"
id="grid16"
type="xygrid" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
style="display:inline"
inkscape:label="Layer 2"
id="layer2"
inkscape:groupmode="layer">
<path
inkscape:connector-curvature="0"
id="path7055"
d=""
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7035"
d=""
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7005"
d=""
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5127"
d=""
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
transform="scale(1.0078883,0.99217343)"
id="text4716"
y="85.59491"
x="67.78315"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:48.4785px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#d9d9d9;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
xml:space="preserve"><tspan
style="fill:#d9d9d9;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="85.59491"
x="67.78315"
id="tspan4714"
sodipodi:role="line">Aux1</tspan></text>
<flowRoot
transform="scale(0.26458333)"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
id="flowRoot4718"
xml:space="preserve"><flowRegion
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
id="flowRegion4720"><rect
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
y="124.10143"
x="264.65997"
height="136.37059"
width="157.5838"
id="rect4722" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="camera_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/camera_btn.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.56808712"
inkscape:cx="108.02318"
inkscape:cy="100.37635"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.52916666"
spacingy="0.52916666"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.70848799;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 67.733332,254.66665 c 0,0 -8.668881,0 -18.300771,-3.15268 -9.631892,-3.1527 -18.2943,-9.47798 -24.078829,-22.06889 5.706713,-9.81112 13.792733,-18.56809 24.089264,-22.0987 9.587884,-3.28767 18.290339,-3.12291 18.290339,-3.12291 0,0 7.735344,-0.0794 18.31234,3.12292 9.690806,2.93407 18.313585,9.42827 24.067265,22.09869 -5.76759,12.59091 -14.445437,18.91619 -24.0777,22.06889 -9.63227,3.15268 -18.301908,3.15268 -18.301908,3.15268 z"
id="path58-3-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscscscsc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.73025268;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 64.488929,217.53903 c -0.857939,0.17659 0.965211,0.45252 1.127737,0.80919 3.74151,2.22182 4.135021,8.10158 0.722172,10.79555 -2.788479,2.49816 -7.570549,1.85517 -9.647324,-1.24231 -0.478813,6.23671 4.305402,12.62817 10.72756,13.07655 5.379142,0.53291 10.304075,-3.82096 11.146917,-9.02134 1.316631,-6.22759 -2.756791,-13.29903 -9.184051,-14.59275 -1.613453,-0.33844 -3.308229,-0.28143 -4.893011,0.17511 z"
id="path4487"
inkscape:connector-curvature="0" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4489"
cx="68.000587"
cy="229.40236"
rx="24.328558"
ry="24.538925" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="chat_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/chat_btn.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-49.76592"
inkscape:cy="230.35684"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="16"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 38.099995,186.93332 H 97.36666 l 12.70001,13.36842 v 44.56141 l -12.095255,13.02565 -13.304754,13.71119 5e-6,-16.93334 H 38.1 l -12.7,-12.7 -5e-6,-41.66491 z"
id="path4573"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="chat_hide_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/chat_hide_btn.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="122.83767"
inkscape:cy="254.28074"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="8"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)"
style="display:inline">
<path
style="fill:none;stroke:#ffffff;stroke-width:22.67716599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 352,96.000006 144,96 96,146.52539 V 304 l 24,24.00001 m 88,24 L 320,352 v 64 L 370.28516,364.17773 416,314.94727 V 146.52539"
transform="matrix(0.26458333,0,0,0.26458333,0,161.53332)"
id="path4573"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 38.1,199.63332 h 38.099999 v 8.46667 H 38.1 v -8.46667"
id="path4737"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:22.67716599;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 144,272 v 32 l 16,10e-6 32,-32 z m 128,0 -32,32 h 48 v -32 z"
transform="matrix(0.26458333,0,0,0.26458333,0,161.53332)"
id="path4737-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:22.67716599;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 256,208.00001 224,208 v 32 m 112,-32 -32,32 h 64 v -32 z"
transform="matrix(0.26458333,0,0,0.26458333,0,161.53332)"
id="path4737-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:22.67716599;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 304,144 v 16.00001 l 16,-16 z"
transform="matrix(0.26458333,0,0,0.26458333,0,161.53332)"
id="path4737-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 38.1,216.56665 h 16.933333 v 8.46667 H 38.1 v -8.46667"
id="path4737-2-9"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 80.433332,233.49999 h 16.933333 v 8.46667 H 80.433332 v -8.46667"
id="path4737-2-1"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 23.283335,267.36666 4.23333,4.23333 88.900005,-88.9 -4.23333,-4.23333 z"
id="path4499"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="chat_show_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/chat_show_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="-52.637496"
inkscape:cy="236.47723"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="16"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<path
style="fill:none;stroke:#ffffff;stroke-width:6.15586996;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 38.099995,186.93332 H 97.36666 l 12.70001,13.36842 v 44.56141 l -12.095255,13.02565 -13.304754,13.71119 5e-6,-16.93334 H 38.1 l -12.7,-12.7 -5e-6,-41.66491 z"
id="path4573"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 38.1,199.63332 h 38.099999 v 8.46667 H 38.1 v -8.46667"
id="path4737"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.30048177;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 38.1,233.49998 h 38.099999 v 8.46667 H 38.1 v -8.46667"
id="path4737-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.30048177;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 59.266666,216.56665 h 38.099999 v 8.46667 H 59.266666 v -8.46667"
id="path4737-6"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.20032115;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 80.433331,199.63332 h 16.933334 v 8.46667 H 80.433331 v -8.46667"
id="path4737-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.20032115;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 38.1,216.56665 h 16.933333 v 8.46667 H 38.1 v -8.46667"
id="path4737-2-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.20032115;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 80.433332,233.49999 h 16.933333 v 8.46667 H 80.433332 v -8.46667"
id="path4737-2-1"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1.8897638;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 332.249,369.02277 c -0.0402,-18.48612 -0.4849,-21.66096 -3.48875,-24.9094 -3.91749,-4.23646 1.11742,-4.01917 -93.12942,-4.01917 h -86.6347 l -20.5311,-20.54025 -20.53109,-20.54025 0.0344,-73.92404 0.0344,-73.92403 20.50131,-21.579 20.50132,-21.57899 106.90272,-0.0281 106.90273,-0.0281 20.77585,21.85532 20.77584,21.85531 v 79.11261 79.1126 l -24.59489,26.35352 c -13.5272,14.49442 -29.74434,31.65707 -36.0381,38.13922 l -11.44321,11.78571 -0.0373,-17.14286 z m -43.95792,-81.07142 v -16.07143 l -72.32143,-0.18197 -72.32143,-0.18198 v 16.43538 16.43537 l 72.32143,-0.18197 72.32143,-0.18198 z m 80,0 v -16.07143 l -32.32143,-0.18585 -32.32143,-0.18585 v 16.44313 16.44312 l 32.32143,-0.18585 32.32143,-0.18585 z M 208.64822,224.02277 v -16.07142 h -32.5 -32.5 v 16.07142 16.07143 h 32.5 32.5 z m 160,0 v -16.07142 h -72.5 -72.5 v 16.07142 16.07143 h 72.5 72.5 z M 288.29108,160.0942 v -16.07143 l -72.32143,-0.18197 -72.32143,-0.18197 v 16.43537 16.43537 l 72.32143,-0.18197 72.32143,-0.18197 z m 80,0 v -16.07143 l -32.32143,-0.18585 -32.32143,-0.18585 v 16.44313 16.44313 l 32.32143,-0.18585 32.32143,-0.18585 z"
id="path5484"
inkscape:connector-curvature="0"
transform="matrix(0.26458333,0,0,0.26458333,0,161.53332)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="checkbox_tick.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="-28.833943"
inkscape:cy="228.57143"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="16"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.1254902" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<path
style="fill:#1a1a1a;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 42.333333,284.29999 4.2333333,246.19999 21.166666,229.26665 42.333333,250.43332 114.3,178.46665 131.23333,195.39999 Z"
id="path14"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

344
android/icons/debug_btn.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

542
android/icons/down.svg Normal file
View File

@ -0,0 +1,542 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="down.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/down.png"
inkscape:export-xdpi="48.000004"
inkscape:export-ydpi="48.000004">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5225" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5418">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5404" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5406" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5408" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5410" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5412" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5414" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5416" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="-237.64887"
inkscape:cy="241.15373"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="false"
inkscape:snap-page="true"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <path
style="display:inline;fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 17.018648,43.065371 V 56.520637 L 67.733324,92.401356 118.44801,56.520637 V 43.065371 Z"
id="path5426"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

173
android/icons/drop_btn.svg Normal file
View File

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="drop_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/drop_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="-435.15132"
inkscape:cy="209.28829"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:0.50196078;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 21.166666,29.761616 21.166667,-7.055555 21.166666,7.055555 -21.166666,8.338385 z"
id="path4693"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#ffffff;fill-opacity:0.25098039;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 21.166666,30.40303 v 26.939394 l 21.166667,7.69697 V 38.099999 Z"
id="path4699"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:0.0627451;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 42.333333,38.099999 v 26.939395 l 21.166666,-7.69697 V 30.40303 Z"
id="path4701"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 110.06667,110.06667 H 67.733332"
id="path4727"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 88.899999,97.366665 0,-16.933331 C 89.263773,55.921256 75.773505,47.130445 55.033333,46.566666"
id="path4729"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 101.6,84.666667 -12.700001,12.699998 -12.7,-12.699998"
id="path4737"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

190
android/icons/fast_btn.svg Normal file
View File

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="fast_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/fast_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="-123.33594"
inkscape:cy="234.93088"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:none;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 52.349702,78.770237 c 8.223364,2.478851 17.933206,1.627099 22.678571,-5.85863 L 86.367558,52.311904"
id="path4630"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 99.195826,95.244627 C 95.407287,83.585464 90.120793,78.524425 79.752975,74.045534 L 90.856024,53.96555"
id="path4632"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 64.539433,56.942114 c 4.52339,-7.945233 16.596076,-10.248496 24.001489,-4.535715 6.443481,4.79704 18.068938,2.827548 22.314838,-3.012345"
id="path4495"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.947;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4496"
cx="95.061012"
cy="40.783634"
rx="6.9582553"
ry="7.1472435" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.22683655px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 47.624999,35.454168 1.058334,-1.5875 h 29.633333 l -0.921774,1.663097 z"
id="path4509"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.22683655px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 21.030106,52.841071 1.058334,-1.5875 h 29.633333 l -0.921774,1.663097 z"
id="path4509-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.22683655px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 29.496773,69.774404 1.058334,-1.5875 H 60.18844 l -0.921774,1.663097 z"
id="path4509-56"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.22683655px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 18.91344,88.824411 1.058334,-1.5875 h 29.633333 l -0.921774,1.66309 z"
id="path4509-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

168
android/icons/fly_btn.svg Normal file
View File

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="fly_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/fly_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="53.55965"
inkscape:cy="198.9488"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="false"
inkscape:snap-page="true"
showguides="false"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-to-guides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 25.670229,38.593108 109.83886,56.716287 83.057927,68.798408 75.262818,96.914386 71.580388,74.83947 44.799461,86.921586 25.670229,38.593108"
id="path4666"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 25.670229,38.593106 71.580388,74.839464"
id="path4668"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 25.670229,38.593106 83.057927,68.798404"
id="path4670"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 75.262817,96.914386 60.102847,80.880526"
id="path4672"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

194
android/icons/gear_icon.svg Normal file
View File

@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="gear_icon.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/gear_icon.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<defs
id="defs2">
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path4687"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path4690"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path4692"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path4694"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX-3">
<path
id="path4756"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch-6"
height="8">
<path
id="path4759"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path4761"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path4763"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="-308.644"
inkscape:cy="171.10144"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-page="true"
inkscape:snap-grids="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-object-midpoints="true"
inkscape:snap-to-guides="false"
inkscape:showpageshadow="false"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="2.1166666"
spacingy="2.1166666"
empspacing="2"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<g
id="g4792"
transform="matrix(0.68725287,0,0,0.65623884,67.477909,-509.24679)"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.74041259;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<g
id="g4772"
inkscape:label="OpenJsCad"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.74041259;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 256,80.943359 -8.28125,0.72461 -3.63477,5.410156 -5.61328,12.685547 -2.28906,9.259768 -0.35156,5.1875 0.0937,0.86133 0.70703,2.44726 0.60547,9.80664 -2.66602,5.47461 -21.5957,5.78711 -5.04492,-3.40625 -4.37696,-8.79687 -0.61132,-2.47071 -0.35157,-0.79297 -2.89648,-4.31836 -6.60938,-6.87304 -11.20507,-8.17969 -5.84961,-2.86719 -7.53516,3.51367 -6.80859,4.76954 -0.44336,6.50195 1.48047,13.79297 2.64453,9.16406 2.28906,4.66992 0.51172,0.69922 1.83398,1.76563 5.42774,8.18945 0.42773,6.07422 -15.81054,15.81445 -6.07032,-0.42773 -8.18945,-5.42969 -1.76367,-1.83399 -0.69922,-0.51171 -4.66992,-2.28907 -9.15821,-2.64843 -13.79297,-1.47852 -6.5,0.44141 -4.76757,6.8125 -3.51367,7.53515 2.86914,5.85157 8.17382,11.20703 6.87305,6.61132 4.31641,2.90039 0.79297,0.34961 2.4707,0.61133 8.79492,4.37696 3.4043,5.04687 -5.78516,21.60156 -5.47265,2.66602 -9.80469,-0.60547 -2.44727,-0.70703 -0.85937,-0.0918 -5.1875,0.35156 -9.257816,2.28907 -12.68164,5.61523 -5.408203,3.63281 -0.72461,8.28516 0.72461,8.28516 5.408203,3.63281 12.68164,5.61523 9.257816,2.28907 5.1875,0.35156 0.85937,-0.0918 2.44727,-0.70703 9.80469,-0.60547 5.47265,2.66602 5.78516,21.60156 -3.4043,5.04687 -8.79492,4.37696 -2.4707,0.61133 -0.79297,0.34961 -4.31641,2.90039 -6.87305,6.61132 -8.17382,11.20703 -2.86914,5.85157 3.51367,7.53515 4.76757,6.8125 6.5,0.44141 13.79297,-1.47852 9.15821,-2.64843 4.66992,-2.28907 0.69922,-0.50976 1.76367,-1.83594 8.18945,-5.42969 6.07032,-0.42773 15.81054,15.81445 -0.42773,6.07422 -5.42774,8.18945 -1.83398,1.76563 -0.51172,0.69922 -2.28906,4.66992 -2.64453,9.16406 -1.48047,13.79297 0.44336,6.50195 6.80859,4.76758 7.53516,3.51758 5.84961,-2.86914 11.20507,-8.17969 6.60938,-6.87304 2.89648,-4.31836 0.35157,-0.79297 0.61132,-2.47071 4.37696,-8.79687 5.04492,-3.40625 21.5957,5.78711 2.66602,5.47461 -0.60547,9.80664 -0.70703,2.44726 -0.0937,0.85938 0.35156,5.18945 2.28906,9.25977 5.61328,12.68555 3.63477,5.41015 8.28125,0.72461 8.28125,-0.72461 3.63477,-5.41015 5.61328,-12.68555 2.28906,-9.25977 0.35156,-5.18945 -0.0937,-0.85938 -0.70703,-2.44726 -0.60547,-9.80664 2.66602,-5.47461 21.5957,-5.78711 5.04492,3.40625 4.37696,8.79687 0.61132,2.47071 0.35157,0.79297 2.89648,4.31836 6.60938,6.87304 11.20507,8.17969 5.84961,2.86914 7.53516,-3.51758 6.80859,-4.76758 0.44336,-6.50195 -1.48047,-13.79297 -2.64453,-9.16406 -2.28906,-4.66992 -0.51172,-0.69922 -1.83398,-1.76563 -5.42774,-8.18945 -0.42773,-6.07422 15.81054,-15.81445 6.07032,0.42773 8.18945,5.42969 1.76367,1.83594 0.69922,0.50976 4.66992,2.28907 9.15821,2.64843 13.79297,1.47852 6.5,-0.44141 v -0.002 l 4.76757,-6.81055 3.51367,-7.53711 -2.86914,-5.85156 -8.17382,-11.20508 -6.87305,-6.61328 -4.31641,-2.89843 -0.79297,-0.34961 -2.4707,-0.61133 -8.79492,-4.37891 -3.4043,-5.04492 5.78516,-21.60352 5.47265,-2.66797 9.80469,0.60938 2.44727,0.70703 0.85937,0.0918 5.1875,-0.35156 9.25782,-2.28907 12.68164,-5.61718 5.4082,-3.63282 0.72461,-8.28515 -0.72461,-8.28321 -5.4082,-3.63476 -12.68164,-5.61524 -9.25782,-2.28711 -5.1875,-0.35351 -0.85937,0.0937 -2.44727,0.70508 -9.80469,0.60937 -5.47265,-2.66797 -5.78516,-21.59961 3.4043,-5.04882 8.79492,-4.37696 2.4707,-0.61133 0.79297,-0.35156 4.31641,-2.89844 6.87305,-6.61132 8.17382,-11.20703 2.86914,-5.85157 -3.51367,-7.53711 -4.76757,-6.81054 -6.5,-0.44336 -13.79297,1.48047 -9.15821,2.64648 -4.66992,2.28906 -0.69922,0.51172 -1.76367,1.83594 -8.18945,5.42773 -6.07032,0.42774 -15.81054,-15.81446 0.42773,-6.07226 5.42774,-8.18945 1.83398,-1.76563 0.51172,-0.69922 2.28906,-4.67187 2.64453,-9.16016 1.48047,-13.79492 -0.44336,-6.50195 -6.80859,-4.76954 -7.53516,-3.51562 -5.84961,2.87109 -11.20507,8.17578 -6.60938,6.875 -2.89648,4.31836 -0.35157,0.79102 -0.61132,2.47266 -4.37696,8.79687 -5.04492,3.4082 -21.5957,-5.79101 -2.66602,-5.47266 0.60547,-9.80664 0.70703,-2.44726 0.0937,-0.85938 -0.35156,-5.19141 -2.28906,-9.259761 -5.61328,-12.683594 -3.63477,-5.412109 z m 0,97.111331 A 77.946197,77.946197 0 0 1 333.94531,256 77.946197,77.946197 0 0 1 256,333.94531 77.946197,77.946197 0 0 1 178.05469,256 77.946197,77.946197 0 0 1 256,178.05469 Z"
transform="matrix(0.38495268,0,0,0.40318156,-98.176247,1022.1341)"
id="path4768"
inkscape:connector-curvature="0" />
</g>
<g
id="g4774"
inkscape:label="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.74041259;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,509 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="inventory_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/inventory_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="51.254762"
inkscape:cy="221.96083"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 3"
style="display:inline" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028"
width="21.166668"
height="21.166664"
x="27.516666"
y="27.516668" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-6"
width="21.166668"
height="21.166664"
x="57.149998"
y="27.516668" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-2"
width="21.166668"
height="21.166664"
x="86.783333"
y="27.516668" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-1"
width="21.166668"
height="21.166664"
x="27.516665"
y="57.150002" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-6-7"
width="21.166668"
height="21.166664"
x="57.149998"
y="57.150002" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-2-8"
width="21.166668"
height="21.166664"
x="86.783333"
y="57.150002" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-5"
width="21.166668"
height="21.166664"
x="27.516666"
y="86.783333" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-6-74"
width="21.166668"
height="21.166664"
x="57.149998"
y="86.783333" />
<rect
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5028-2-1"
width="21.166668"
height="21.166664"
x="86.783333"
y="86.783333" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,876 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="joystick_bg.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/joystick_bg.png"
inkscape:export-xdpi="144.00002"
inkscape:export-ydpi="144.00002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5225" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5418">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5404" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5406" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5408" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5410" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5412" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5414" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5416" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5914">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5900" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5902" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5904" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5906" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5908" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5910" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5912" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5916" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5918"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5920"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5922"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5924"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5926"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5928"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5930"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5932" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5934"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5936"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5938"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5940"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5942"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5944"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5946"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5948" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5950"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5952"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5954"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5956"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5958"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5960"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5962"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5964" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5966"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5968"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5970"
flood-opacity="1"
flood-color="rgb(159,28,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5972"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5974"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5976"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5978"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5980" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5982"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5984"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5986"
flood-opacity="1"
flood-color="rgb(159,28,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5988"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5990"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5992"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5994"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5996" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5998"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix6000"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood6002"
flood-opacity="1"
flood-color="rgb(159,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend6004"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend6006"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix6008"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite6010"
in="colormatrix2"
operator="in"
k2="1"
result="composite2" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="142.53646"
inkscape:cy="181.89104"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="false"
inkscape:snap-page="true"
showguides="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <circle
style="fill:#ffffff;fill-opacity:0.1254902;stroke:#ffffff;stroke-width:1.99994016;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196078"
id="path5898"
cx="67.733498"
cy="67.73317"
r="66.733528" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,877 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="joystick_center.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/joystick_center.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5225" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5418">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5404" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5406" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5408" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5410" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5412" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5414" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5416" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5914">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5900" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5902" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5904" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5906" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5908" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5910" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5912" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5916" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5918"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5920"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5922"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5924"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5926"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5928"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5930"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5932" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5934"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5936"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5938"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5940"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5942"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5944"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5946"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5948" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5950"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5952"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5954"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5956"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5958"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5960"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5962"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5964" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5966"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5968"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5970"
flood-opacity="1"
flood-color="rgb(159,28,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5972"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5974"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5976"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5978"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5980" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5982"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5984"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5986"
flood-opacity="1"
flood-color="rgb(159,28,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5988"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5990"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5992"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5994"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5996" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5998"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix6000"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood6002"
flood-opacity="1"
flood-color="rgb(159,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend6004"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend6006"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix6008"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite6010"
in="colormatrix2"
operator="in"
k2="1"
result="composite2" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="170.02349"
inkscape:cy="266.32864"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <ellipse
style="display:inline;fill:#ffffff;fill-opacity:0.31372549;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.62745098"
id="path5898-8"
cx="67.733505"
cy="67.73317"
rx="64.816437"
ry="64.816429" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,882 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="joystick_off.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/joystick_off.png"
inkscape:export-xdpi="96.000008"
inkscape:export-ydpi="96.000008">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5225" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5418">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5404" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5406" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5408" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5410" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5412" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5414" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5416" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5914">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5900" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5902" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5904" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5906" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5908" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5910" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5912" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5916" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5918"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5920"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5922"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5924"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5926"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5928"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5930"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5932" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5934"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5936"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5938"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5940"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5942"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5944"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5946"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5948" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5950"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5952"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5954"
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5956"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5958"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5960"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5962"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5964" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5966"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5968"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5970"
flood-opacity="1"
flood-color="rgb(159,28,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5972"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5974"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5976"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5978"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5980" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5982"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5984"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5986"
flood-opacity="1"
flood-color="rgb(159,28,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5988"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5990"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5992"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5994"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5996" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5998"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix6000"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood6002"
flood-opacity="1"
flood-color="rgb(159,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend6004"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend6006"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix6008"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite6010"
in="colormatrix2"
operator="in"
k2="1"
result="composite2" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.1361742"
inkscape:cx="47.851245"
inkscape:cy="254.8605"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <circle
style="fill:none;fill-opacity:0.1254902;stroke:#ffffff;stroke-width:1.99994016;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196078"
id="path5898"
cx="67.731476"
cy="67.735199"
r="66.733528" />
<circle
style="display:inline;fill:#ffffff;fill-opacity:0.1254902;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196078"
id="path5898-8"
cx="68.06868"
cy="67.452492"
r="22.219723" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

547
android/icons/jump_btn.svg Normal file
View File

@ -0,0 +1,547 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="jump_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/jump_btn.png"
inkscape:export-xdpi="48.000004"
inkscape:export-ydpi="48.000004">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5225" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5418">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5404" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5406" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5408" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5410" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5412" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5414" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5416" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="128.02635"
inkscape:cy="237.11312"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="false"
inkscape:snap-page="true"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 3"
style="display:inline" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <path
style="display:inline;fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 17.018648,92.401289 V 78.946023 L 67.733324,43.065304 118.44801,78.946023 v 13.455266 z"
id="path5426"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="minimap_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/minimap_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.56808711"
inkscape:cx="140.1995"
inkscape:cy="242.801"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 25.4,25.400001 52.859457,36.945456 V 110.06667 L 25.4,98.521213 Z"
id="path4857"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="display:inline;fill:none;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 82.607193,25.496213 110.06667,37.041668 V 110.16289 L 82.607192,98.617425 Z"
id="path4857-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="display:inline;fill:#ffffff;fill-opacity:0.1254902;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 52.859457,36.900035 82.607203,25.400001 V 98.233546 L 52.859457,109.73359 Z"
id="path4857-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="noclip_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/noclip_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="166.57784"
inkscape:cy="222.80905"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:none;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 20.760344,79.838021 c 8.223364,2.478851 17.933206,1.627099 22.678571,-5.85863 L 54.7782,53.379688"
id="path4630"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 67.606468,96.312411 C 63.817929,84.653248 58.531435,79.592209 48.163617,75.113318 L 59.266666,55.033334"
id="path4632"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 32.950075,58.009898 c 4.52339,-7.945233 16.596076,-10.248496 24.001489,-4.535715 6.443481,4.79704 18.068938,2.827548 22.314838,-3.012345"
id="path4495"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.94658476;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4496"
cx="63.471653"
cy="41.851418"
rx="6.9582553"
ry="7.1472435" />
<rect
style="fill:#ffffff;fill-opacity:0.25098041;stroke:#ffffff;stroke-width:1.668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4645"
width="71.966667"
height="76.199997"
x="41.166401"
y="29.295174" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,456 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="rangeview_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/rangeview_btn.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="166.63539"
inkscape:cy="248.08632"
inkscape:document-units="mm"
inkscape:current-layer="svg8"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="false"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;stroke-width:1;stroke:#ffffff;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;stroke-width:1;stroke:#ffffff;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;stroke-width:1;stroke:#ffffff;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;stroke-width:1;stroke:#ffffff;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:3.77952761;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 150.08631,391.94585 C 127.2399,389.49917 105.94293,375.91818 94.0332,356.20102 86.417382,343.59265 83.080086,330.51463 83.588961,315.27269 c 0.288383,-8.63772 1.22906,-14.19631 3.585813,-21.18907 0.744516,-2.20907 10.578738,-22.66466 21.853826,-45.45687 11.27509,-22.79221 22.70752,-45.91291 25.4054,-51.37934 5.65921,-11.46666 7.92364,-14.85355 13.47663,-20.15687 9.3888,-8.96668 21.0224,-13.60185 34.10046,-13.58663 15.57027,0.0181 29.17184,6.54335 38.91458,18.66892 4.42466,5.50682 7.71172,12.24131 9.40778,19.27457 l 1.32267,5.48487 1.89404,7.6e-4 c 1.80502,7.5e-4 1.89404,-0.0773 1.89404,-1.66087 0,-2.38449 1.37433,-7.32366 2.62141,-9.42102 4.34092,-7.30059 13.17739,-11.60831 20.98951,-10.23223 8.90426,1.56845 16.14022,8.89813 17.09233,17.31369 l 0.3384,2.99108 h 1.90437 1.90437 l 0.82037,-3.6618 c 1.97195,-8.80199 6.717,-17.42698 13.15423,-23.91027 6.44087,-6.48695 14.23724,-11.09036 22.74482,-13.4298 3.44476,-0.94724 5.34406,-1.11181 12.87945,-1.11592 8.2237,-0.004 9.15393,0.0921 13.36642,1.38764 11.19974,3.4445 21.27498,10.65667 27.47414,19.66684 2.43995,3.54634 51.82554,103.72263 53.56888,108.66187 4.86293,13.77773 5.3328,30.48234 1.25486,44.6126 -7.75149,26.85937 -29.41571,46.87461 -57.03616,52.69485 -7.41065,1.56158 -20.20927,1.68497 -27.769,0.2677 -10.44443,-1.95808 -21.29618,-6.51537 -29.79851,-12.51414 -5.61285,-3.96011 -13.68691,-11.97138 -17.55818,-17.42164 -5.93008,-8.3488 -10.31705,-18.5166 -12.57558,-29.14677 -0.9513,-4.47749 -1.12676,-7.36003 -1.388,-22.80306 l -0.29904,-17.67767 -1.72317,-3.17794 c -1.98763,-3.66567 -6.54416,-8.1288 -10.17974,-9.97108 -3.00155,-1.521 -7.96438,-2.74331 -11.17947,-2.75342 -9.0329,-0.0284 -18.18038,5.63658 -22.00735,13.62902 l -1.57171,3.28243 -0.0408,14.1427 c -0.0539,18.69996 -0.78106,24.89804 -4.07384,34.72632 -2.2638,6.75698 -4.66197,11.60267 -8.86796,17.91843 -11.87929,17.83801 -31.39221,29.77252 -52.98796,32.40855 -4.28534,0.52308 -12.49549,0.62647 -16.41498,0.20673 z m 17.51181,-12.02116 c 24.5782,-3.98628 44.48858,-21.86418 50.90845,-45.71164 7.03076,-26.11666 -3.52165,-54.08171 -26.00322,-68.91142 -18.6353,-12.29256 -42.96948,-13.7508 -62.79635,-3.7631 -6.56442,3.3068 -10.82228,6.4025 -16.2475,11.81283 -12.18826,12.1548 -18.426507,27.20212 -18.426507,44.44671 0,16.25308 5.718027,30.90801 16.717117,42.84489 8.79197,9.54157 22.47266,17.01469 34.80066,19.00997 2.08344,0.33719 4.129,0.67988 4.54569,0.76152 2.33806,0.45809 12.52096,0.15587 16.50166,-0.48976 z m 199.67098,-0.46635 c 21.74737,-4.70543 39.22231,-19.90775 46.64822,-40.58158 4.67986,-13.02877 4.67986,-29.12861 0,-42.15737 -9.00601,-25.07287 -32.72555,-41.79925 -59.27512,-41.79925 -29.97234,0 -55.28352,20.70748 -61.73156,50.50356 -0.78837,3.64299 -1.03837,6.62229 -1.03837,12.37437 0,8.49596 0.94045,14.06163 3.61188,21.37559 7.82601,21.42637 26.67144,37.08767 49.05652,40.76791 5.46425,0.89835 17.52859,0.64186 22.72843,-0.48323 z M 237.11052,255.93654 c 2.061,-5.80288 9.76676,-11.6013 16.44795,-12.37673 8.46341,-0.98229 17.00015,3.70335 20.60499,11.30963 1.35941,2.86835 1.5302,3.0277 3.27087,3.05174 l 1.83657,0.0254 0.37277,-13.91749 c 0.20502,-7.65462 0.25259,-14.81346 0.10571,-15.90854 -0.81263,-6.05855 -6.90622,-13.74979 -13.24302,-16.71514 -12.19154,-5.70511 -26.74913,-0.60024 -32.61887,11.43837 -1.71657,3.52062 -1.72459,3.57069 -1.90176,11.8693 -0.0979,4.58356 -0.0177,11.79984 0.17822,16.03617 l 0.35614,7.70241 h 1.84858 c 1.76097,0 1.89091,-0.11919 2.74185,-2.51507 z"
id="path7617"
inkscape:connector-curvature="0"
transform="scale(0.26458333)" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:3.77952761;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 226.35138,166.86581 c -8.68374,-8.45091 -19.24579,-14.06812 -31.56582,-16.78764 -1.94455,-0.42924 -6.62953,-0.91183 -10.41107,-1.07243 l -6.87554,-0.29199 3.79476,-8.23483 c 4.15041,-9.00661 6.33398,-12.02822 10.83115,-14.98806 5.73143,-3.77218 12.11755,-5.07486 18.37716,-3.74869 6.79635,1.43989 12.12205,4.97666 15.80992,10.49928 3.65897,5.47936 4.06888,7.72634 4.43093,24.289 0.17485,7.99863 0.22458,14.53663 0.11051,14.52888 -0.11408,-0.008 -2.13997,-1.89483 -4.502,-4.19352 z"
id="path7619"
inkscape:connector-curvature="0"
transform="scale(0.26458333)" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:3.77952761;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 281.04946,156.67874 c 0.29695,-15.67547 0.53041,-17.35662 3.11733,-22.44879 1.64145,-3.23106 6.08971,-7.81924 9.49653,-9.79523 1.32451,-0.76823 4.2792,-1.87338 6.56599,-2.45589 3.62852,-0.92429 4.68255,-0.99503 8.28005,-0.55573 6.90922,0.84371 13.7575,4.77525 17.28082,9.92078 1.38217,2.01854 8.14389,16.19869 8.14389,17.07872 0,0.2351 -2.10238,0.42837 -4.67196,0.42949 -8.99282,0.004 -18.25222,2.12274 -26.55807,6.0773 -7.17709,3.41713 -11.63607,6.48677 -17.19557,11.83773 l -4.73649,4.55883 z"
id="path7621"
inkscape:connector-curvature="0"
transform="scale(0.26458333)" />
</g>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 3"
style="display:inline" />
<g
id="g7475"
inkscape:label="0"
transform="matrix(0.14221997,0,0,0.14221997,-31.981034,55.479631)"
style="stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round">
<path
id="path7425"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 394.42769,131.14785 a 142.37722,142.37722 0 1 0 266.38087,69.95976"
inkscape:connector-curvature="0" />
<path
id="path7433"
style="fill:none;stroke:#ffffff;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:round"
d="M 658.56907,-59.664378 A 115.98533,115.98533 0 0 0 548.79351,-108.70519 m 108.73351,-11.03878 1.04205,60.079592 m -1.04205,-60.079592 a 49.685709,49.685709 0 0 0 -92.6985,-23.81259 m 0,0 -16.03501,34.85137" />
<path
id="path7435"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 660.1707,35.074784 0.45347,54.803856"
inkscape:connector-curvature="0" />
<path
id="path7437"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 474.48909,-30.517229 387.62757,144.87909"
inkscape:connector-curvature="0" />
<path
id="path7439"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 659.19164,-5.530313 A 96.39108,96.39108 0 0 0 474.48909,-30.517229"
inkscape:connector-curvature="0" />
<path
id="path7441"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 740.97478,202.17383 A 142.37722,142.37722 0 1 0 1007.3517,131.14785"
inkscape:connector-curvature="0" />
<path
id="path7449"
style="fill:none;stroke:#ffffff;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:round"
d="m 852.98584,-108.70519 a 115.98533,115.98533 0 0 0 -109.77556,49.040812 m 1.04205,-60.079592 -1.04205,60.079592 m 93.74055,-83.892182 a 49.685709,49.685709 0 0 0 -92.6985,23.81259 m 92.6985,-23.81259 16.03501,34.85137" />
<path
id="path7451"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 741.61776,33.973249 -0.4549,54.976979"
inkscape:connector-curvature="0" />
<path
id="path7453"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 927.29026,-30.517229 1014.1518,144.87909"
inkscape:connector-curvature="0" />
<path
id="path7455"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 927.29026,-30.517229 A 96.39108,96.39108 0 0 0 742.8897,-7.745832"
inkscape:connector-curvature="0" />
<path
id="path7457"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 741.16286,88.950228 A 41.867624,41.867624 0 0 0 660.62417,89.87864"
inkscape:connector-curvature="0" />
<path
id="path7459"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 740.61905,154.67245 a 41.867624,41.867624 0 0 0 -79.45215,0.79683"
inkscape:connector-curvature="0" />
<path
id="path7461"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 742.8897,-7.745832 a 41.867624,41.867624 0 1 0 -83.69806,2.215519"
inkscape:connector-curvature="0" />
<path
id="path7463"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="M 741.61776,33.973249 A 41.867624,41.867624 0 0 0 660.1707,35.074784"
inkscape:connector-curvature="0" />
<path
id="path7465"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 660.80856,201.10761 0.35834,-45.63833"
inkscape:connector-curvature="0" />
<path
id="path7467"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 740.97478,202.17383 -0.35573,-47.50138"
inkscape:connector-curvature="0" />
<path
id="path7471"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 631.81717,201.10761 a 113.38583,113.38583 0 1 0 -226.77166,0 113.38583,113.38583 0 1 0 226.77166,0 z"
inkscape:connector-curvature="0" />
<path
id="path7473"
style="fill:none;stroke:#ffffff;stroke-width:7.03136135;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
d="m 997.9874,201.10761 a 113.38583,113.38583 0 1 0 -226.77166,0 113.38583,113.38583 0 1 0 226.77166,0 z"
inkscape:connector-curvature="0" />
</g>
<path
id="path7469"
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
d="m 70.34536,79.242709 a 2.6876219,2.6876219 0 1 0 -5.375243,0 2.6876219,2.6876219 0 1 0 5.375243,0 z"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,521 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256"
height="512"
viewBox="0 0 67.73333 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="rare_controls.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/rare_controls.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614"
k3="0"
k4="0" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095"
k3="0"
k4="0" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic"
k3="0"
k4="0" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0"
refX="0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000;stroke-width:0.5"
d="M 3,-3 -3,3 M 0,-5 V 5"
inkscape:connector-curvature="0" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869"
k3="0"
k4="0" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045"
k3="0"
k4="0" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213"
k3="0"
k4="0" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
result="composite2"
id="feComposite5225" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="-59.862018"
inkscape:cy="260.34663"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 3"
style="display:inline" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9"
width="25.4"
height="25.400003"
x="21.166666"
y="101.6" />
<rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9-7"
width="25.4"
height="25.400003"
x="21.166666"
y="55.033333" />
<rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9-5"
width="25.4"
height="25.400003"
x="21.166664"
y="8.4666681" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

599
android/icons/zoom.svg Normal file
View File

@ -0,0 +1,599 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="zoom.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/zoom.png"
inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002">
<defs
id="defs2">
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4628">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4614" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4616" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1"
id="feFlood4618" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4620" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4622" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4624" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4626" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Sharpen More"
id="filter5109"
inkscape:menu="Image Effects"
inkscape:menu-tooltip="Sharpen edges and boundaries within the object, force=0.3">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5095" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5097" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,67,0)"
result="flood1"
id="feFlood5099" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5101" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5103" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5105" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="fbSourceGraphic"
id="feComposite5107" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix5111" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5113"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
in="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix5115"
in="composite1"
values="1"
type="saturate"
result="colormatrix1" />
<feFlood
id="feFlood5117"
flood-opacity="1"
flood-color="rgb(158,0,0)"
result="flood1" />
<feBlend
in2="colormatrix1"
id="feBlend5119"
in="flood1"
mode="multiply"
result="blend1" />
<feBlend
in2="blend1"
id="feBlend5121"
mode="screen"
result="blend2" />
<feColorMatrix
id="feColorMatrix5123"
in="blend2"
values="1"
type="saturate"
result="colormatrix2" />
<feComposite
in2="fbSourceGraphic"
id="feComposite5125"
in="colormatrix2"
operator="in"
k2="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7007" />
<feConvolveMatrix
id="feConvolveMatrix7009"
order="3 3"
kernelMatrix="0 -0.15 0 -0.15 1.6 -0.15 0 -0.15 0"
divisor="1"
in="fbSourceGraphic"
targetX="1"
targetY="1"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix7011" />
<feConvolveMatrix
id="feConvolveMatrix7013"
targetY="1"
targetX="1"
in="fbSourceGraphic"
divisor="1"
kernelMatrix="0 -0.3 0 -0.3 2.2 -0.3 0 -0.3 0"
order="3 3"
result="result1" />
<feBlend
in2="fbSourceGraphic"
id="feBlend7015"
mode="normal"
result="result2" />
</filter>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path7410"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path7413"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path7415"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path7417"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<symbol
id="*Model_Space" />
<symbol
id="*Paper_Space" />
<symbol
id="*Paper_Space0" />
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4883">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4869" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4871" />
<feFlood
flood-opacity="1"
flood-color="rgb(158,21,0)"
result="flood1"
id="feFlood4873" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4875" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4877" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4879" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4881" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5059">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5045" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5047" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,14,0)"
result="flood1"
id="feFlood5049" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5051" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5053" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5055" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5057" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5227">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5213" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5215" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5217" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5219" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5221" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5223" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5225" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter5418">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite5404" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix5406" />
<feFlood
flood-opacity="1"
flood-color="rgb(159,21,0)"
result="flood1"
id="feFlood5408" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend5410" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend5412" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix5414" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite5416" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Colorize"
id="filter4664">
<feComposite
in2="SourceGraphic"
operator="arithmetic"
k1="0"
k2="1"
result="composite1"
id="feComposite4650" />
<feColorMatrix
in="composite1"
values="1"
type="saturate"
result="colormatrix1"
id="feColorMatrix4652" />
<feFlood
flood-opacity="1"
flood-color="rgb(255,0,0)"
result="flood1"
id="feFlood4654" />
<feBlend
in="flood1"
in2="colormatrix1"
mode="multiply"
result="blend1"
id="feBlend4656" />
<feBlend
in2="blend1"
mode="screen"
result="blend2"
id="feBlend4658" />
<feColorMatrix
in="blend2"
values="1"
type="saturate"
result="colormatrix2"
id="feColorMatrix4660" />
<feComposite
in="colormatrix2"
in2="SourceGraphic"
operator="in"
k2="1"
result="composite2"
id="feComposite4662" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="142.16849"
inkscape:cy="213.87961"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-grids="true"
inkscape:snap-page="true"
showguides="true">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="0.26458333"
spacingy="0.26458333"
empspacing="4"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 3"
style="display:inline" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7055"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7035"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path7005"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d=""
id="path5127"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
transform="scale(0.26458333)"><flowRegion
id="flowRegion4720"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"><rect
id="rect4722"
width="157.5838"
height="136.37059"
x="264.65997"
y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <ellipse
style="display:inline;fill:none;fill-opacity:0.31372549;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4672"
cx="56.858261"
cy="57.228764"
rx="27.848776"
ry="27.594934" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 71.702072,80.367223 80.697906,71.427111 110.06667,101.6 l -8.73126,8.9401 z"
id="path4689"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

View File

@ -0,0 +1,69 @@
apply plugin: 'com.android.library'
apply plugin: 'de.undercouch.download'
android {
compileSdkVersion 30
buildToolsVersion '30.0.3'
ndkVersion "$ndk_version"
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
externalNativeBuild {
ndkBuild {
arguments '-j' + Runtime.getRuntime().availableProcessors(),
"versionMajor=${versionMajor}",
"versionMinor=${versionMinor}",
"versionPatch=${versionPatch}",
"versionExtra=${versionExtra}",
"developmentBuild=${developmentBuild}"
}
}
}
externalNativeBuild {
ndkBuild {
path file('jni/Android.mk')
}
}
// supported architectures
splits {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
buildTypes {
release {
externalNativeBuild {
ndkBuild {
arguments 'NDEBUG=1'
}
}
ndk {
debugSymbolLevel 'SYMBOL_TABLE'
}
}
}
}
// get precompiled deps
task downloadDeps(type: Download) {
src 'https://github.com/minetest/minetest_android_deps/releases/download/latest/deps.zip'
dest new File(buildDir, 'deps.zip')
overwrite false
}
task getDeps(dependsOn: downloadDeps, type: Copy) {
def deps = new File(buildDir.parent, 'deps')
if (!deps.exists()) {
deps.mkdir()
from zipTree(downloadDeps.dest)
into deps
}
}
preBuild.dependsOn getDeps

View File

@ -0,0 +1,301 @@
LOCAL_PATH := $(call my-dir)/..
#LOCAL_ADDRESS_SANITIZER:=true
#USE_BUILTIN_LUA:=true
include $(CLEAR_VARS)
LOCAL_MODULE := Curl
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libcurl.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmbedcrypto
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libmbedcrypto.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmbedtls
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libmbedtls.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmbedx509
LOCAL_SRC_FILES := deps/$(APP_ABI)/Curl/libmbedx509.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Freetype
LOCAL_SRC_FILES := deps/$(APP_ABI)/Freetype/libfreetype.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Iconv
LOCAL_SRC_FILES := deps/$(APP_ABI)/Iconv/libiconv.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcharset
LOCAL_SRC_FILES := deps/$(APP_ABI)/Iconv/libcharset.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Irrlicht
LOCAL_SRC_FILES := deps/$(APP_ABI)/Irrlicht/libIrrlichtMt.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Irrlicht-libpng
LOCAL_SRC_FILES := deps/$(APP_ABI)/Irrlicht/libpng.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Irrlicht-libjpeg
LOCAL_SRC_FILES := deps/$(APP_ABI)/Irrlicht/libjpeg.a
include $(PREBUILT_STATIC_LIBRARY)
ifndef USE_BUILTIN_LUA
include $(CLEAR_VARS)
LOCAL_MODULE := LuaJIT
LOCAL_SRC_FILES := deps/$(APP_ABI)/LuaJIT/libluajit.a
include $(PREBUILT_STATIC_LIBRARY)
endif
include $(CLEAR_VARS)
LOCAL_MODULE := OpenAL
LOCAL_SRC_FILES := deps/$(APP_ABI)/OpenAL-Soft/libopenal.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Gettext
LOCAL_SRC_FILES := deps/$(APP_ABI)/Gettext/libintl.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := SQLite3
LOCAL_SRC_FILES := deps/$(APP_ABI)/SQLite/libsqlite3.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Vorbis
LOCAL_SRC_FILES := deps/$(APP_ABI)/Vorbis/libvorbis.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libvorbisfile
LOCAL_SRC_FILES := deps/$(APP_ABI)/Vorbis/libvorbisfile.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libogg
LOCAL_SRC_FILES := deps/$(APP_ABI)/Vorbis/libogg.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Zstd
LOCAL_SRC_FILES := deps/$(APP_ABI)/Zstd/libzstd.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Minetest
LOCAL_CFLAGS += \
-DJSONCPP_NO_LOCALE_SUPPORT \
-DHAVE_TOUCHSCREENGUI \
-DENABLE_GLES=1 \
-DUSE_CURL=1 \
-DUSE_SOUND=1 \
-DUSE_LEVELDB=0 \
-DUSE_GETTEXT=1 \
-DVERSION_MAJOR=${versionMajor} \
-DVERSION_MINOR=${versionMinor} \
-DVERSION_PATCH=${versionPatch} \
-DVERSION_EXTRA=${versionExtra} \
-DDEVELOPMENT_BUILD=${developmentBuild} \
$(GPROF_DEF)
ifdef USE_BUILTIN_LUA
LOCAL_CFLAGS += -DUSE_LUAJIT=0
else
LOCAL_CFLAGS += -DUSE_LUAJIT=1
endif
ifdef NDEBUG
LOCAL_CFLAGS += -DNDEBUG=1
endif
ifdef GPROF
GPROF_DEF := -DGPROF
PROFILER_LIBS := android-ndk-profiler
LOCAL_CFLAGS += -pg
endif
LOCAL_C_INCLUDES := \
../../src \
../../src/script \
../../lib/gmp \
../../lib/jsoncpp \
deps/$(APP_ABI)/Curl/include \
deps/$(APP_ABI)/Freetype/include/freetype2 \
deps/$(APP_ABI)/Irrlicht/include \
deps/$(APP_ABI)/Gettext/include \
deps/$(APP_ABI)/Iconv/include \
deps/$(APP_ABI)/OpenAL-Soft/include \
deps/$(APP_ABI)/SQLite/include \
deps/$(APP_ABI)/Vorbis/include \
deps/$(APP_ABI)/Zstd/include
ifdef USE_BUILTIN_LUA
LOCAL_C_INCLUDES += \
../../lib/lua/src \
../../lib/bitop
else
LOCAL_C_INCLUDES += deps/$(APP_ABI)/LuaJIT/include
endif
LOCAL_SRC_FILES := \
$(wildcard ../../src/client/*.cpp) \
$(wildcard ../../src/client/*/*.cpp) \
$(wildcard ../../src/content/*.cpp) \
../../src/database/database.cpp \
../../src/database/database-dummy.cpp \
../../src/database/database-files.cpp \
../../src/database/database-sqlite3.cpp \
$(wildcard ../../src/gui/*.cpp) \
$(wildcard ../../src/irrlicht_changes/*.cpp) \
$(wildcard ../../src/mapgen/*.cpp) \
$(wildcard ../../src/network/*.cpp) \
$(wildcard ../../src/script/*.cpp) \
$(wildcard ../../src/script/*/*.cpp) \
$(wildcard ../../src/server/*.cpp) \
$(wildcard ../../src/threading/*.cpp) \
$(wildcard ../../src/util/*.c) \
$(wildcard ../../src/util/*.cpp) \
../../src/ban.cpp \
../../src/chat.cpp \
../../src/clientiface.cpp \
../../src/collision.cpp \
../../src/content_mapnode.cpp \
../../src/content_nodemeta.cpp \
../../src/convert_json.cpp \
../../src/craftdef.cpp \
../../src/debug.cpp \
../../src/defaultsettings.cpp \
../../src/emerge.cpp \
../../src/environment.cpp \
../../src/face_position_cache.cpp \
../../src/filesys.cpp \
../../src/gettext.cpp \
../../src/httpfetch.cpp \
../../src/hud.cpp \
../../src/inventory.cpp \
../../src/inventorymanager.cpp \
../../src/itemdef.cpp \
../../src/itemstackmetadata.cpp \
../../src/light.cpp \
../../src/log.cpp \
../../src/main.cpp \
../../src/map.cpp \
../../src/map_settings_manager.cpp \
../../src/mapblock.cpp \
../../src/mapnode.cpp \
../../src/mapsector.cpp \
../../src/metadata.cpp \
../../src/modchannels.cpp \
../../src/nameidmapping.cpp \
../../src/nodedef.cpp \
../../src/nodemetadata.cpp \
../../src/nodetimer.cpp \
../../src/noise.cpp \
../../src/objdef.cpp \
../../src/object_properties.cpp \
../../src/particles.cpp \
../../src/pathfinder.cpp \
../../src/player.cpp \
../../src/porting.cpp \
../../src/porting_android.cpp \
../../src/profiler.cpp \
../../src/raycast.cpp \
../../src/reflowscan.cpp \
../../src/remoteplayer.cpp \
../../src/rollback.cpp \
../../src/rollback_interface.cpp \
../../src/serialization.cpp \
../../src/server.cpp \
../../src/serverenvironment.cpp \
../../src/serverlist.cpp \
../../src/settings.cpp \
../../src/staticobject.cpp \
../../src/texture_override.cpp \
../../src/tileanimation.cpp \
../../src/tool.cpp \
../../src/translation.cpp \
../../src/version.cpp \
../../src/voxel.cpp \
../../src/voxelalgorithms.cpp
# Built-in Lua
ifdef USE_BUILTIN_LUA
LOCAL_SRC_FILES += \
../../lib/lua/src/lapi.c \
../../lib/lua/src/lauxlib.c \
../../lib/lua/src/lbaselib.c \
../../lib/lua/src/lcode.c \
../../lib/lua/src/ldblib.c \
../../lib/lua/src/ldebug.c \
../../lib/lua/src/ldo.c \
../../lib/lua/src/ldump.c \
../../lib/lua/src/lfunc.c \
../../lib/lua/src/lgc.c \
../../lib/lua/src/linit.c \
../../lib/lua/src/liolib.c \
../../lib/lua/src/llex.c \
../../lib/lua/src/lmathlib.c \
../../lib/lua/src/lmem.c \
../../lib/lua/src/loadlib.c \
../../lib/lua/src/lobject.c \
../../lib/lua/src/lopcodes.c \
../../lib/lua/src/loslib.c \
../../lib/lua/src/lparser.c \
../../lib/lua/src/lstate.c \
../../lib/lua/src/lstring.c \
../../lib/lua/src/lstrlib.c \
../../lib/lua/src/ltable.c \
../../lib/lua/src/ltablib.c \
../../lib/lua/src/ltm.c \
../../lib/lua/src/lundump.c \
../../lib/lua/src/lvm.c \
../../lib/lua/src/lzio.c \
../../lib/bitop/bit.c
endif
# GMP
LOCAL_SRC_FILES += ../../lib/gmp/mini-gmp.c
# JSONCPP
LOCAL_SRC_FILES += ../../lib/jsoncpp/jsoncpp.cpp
LOCAL_STATIC_LIBRARIES += \
Curl libmbedcrypto libmbedtls libmbedx509 \
Freetype \
Iconv libcharset \
Irrlicht Irrlicht-libpng Irrlicht-libjpeg \
OpenAL \
Gettext \
SQLite3 \
Vorbis libvorbisfile libogg \
Zstd
ifndef USE_BUILTIN_LUA
LOCAL_STATIC_LIBRARIES += LuaJIT
endif
LOCAL_STATIC_LIBRARIES += android_native_app_glue $(PROFILER_LIBS)
LOCAL_LDLIBS := -lEGL -lGLESv1_CM -lGLESv2 -landroid -lOpenSLES -lz
include $(BUILD_SHARED_LIBRARY)
ifdef GPROF
$(call import-module,android-ndk-profiler)
endif
$(call import-module,android/native_app_glue)

View File

@ -0,0 +1,32 @@
APP_PLATFORM := ${APP_PLATFORM}
APP_ABI := ${TARGET_ABI}
APP_STL := c++_shared
NDK_TOOLCHAIN_VERSION := clang
APP_SHORT_COMMANDS := true
APP_MODULES := Minetest
APP_CPPFLAGS := -O2 -fvisibility=hidden
ifeq ($(APP_ABI),armeabi-v7a)
APP_CPPFLAGS += -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb
endif
ifeq ($(APP_ABI),x86)
APP_CPPFLAGS += -mssse3 -mfpmath=sse -funroll-loops
endif
ifndef NDEBUG
APP_CPPFLAGS := -g -Og -fno-omit-frame-pointer
endif
APP_CFLAGS := $(APP_CPPFLAGS) -Wno-inconsistent-missing-override -Wno-parentheses-equality
APP_CXXFLAGS := $(APP_CPPFLAGS) -fexceptions -frtti -std=gnu++14
APP_LDFLAGS := -Wl,--no-warn-mismatch,--gc-sections,--icf=safe
ifeq ($(APP_ABI),arm64-v8a)
APP_LDFLAGS := -Wl,--no-warn-mismatch,--gc-sections
endif
ifndef NDEBUG
APP_LDFLAGS :=
endif

View File

@ -0,0 +1 @@
<manifest package="net.minetest" />

2
android/settings.gradle Normal file
View File

@ -0,0 +1,2 @@
rootProject.name = "Minetest"
include ':app', ':native'

59
builtin/async/game.lua Normal file
View File

@ -0,0 +1,59 @@
core.log("info", "Initializing asynchronous environment (game)")
local function pack2(...)
return {n=select('#', ...), ...}
end
-- Entrypoint to run async jobs, called by C++
function core.job_processor(func, params)
local retval = pack2(func(unpack(params, 1, params.n)))
return retval
end
-- Import a bunch of individual files from builtin/game/
local gamepath = core.get_builtin_path() .. "game" .. DIR_DELIM
dofile(gamepath .. "constants.lua")
dofile(gamepath .. "item_s.lua")
dofile(gamepath .. "misc_s.lua")
dofile(gamepath .. "features.lua")
dofile(gamepath .. "voxelarea.lua")
-- Transfer of globals
do
local all = assert(core.transferred_globals)
core.transferred_globals = nil
all.registered_nodes = {}
all.registered_craftitems = {}
all.registered_tools = {}
for k, v in pairs(all.registered_items) do
-- Disable further modification
setmetatable(v, {__newindex = {}})
-- Reassemble the other tables
if v.type == "node" then
all.registered_nodes[k] = v
elseif v.type == "craftitem" then
all.registered_craftitems[k] = v
elseif v.type == "tool" then
all.registered_tools[k] = v
end
end
for k, v in pairs(all) do
core[k] = v
end
end
-- For tables that are indexed by item name:
-- If table[X] does not exist, default to table[core.registered_aliases[X]]
local alias_metatable = {
__index = function(t, name)
return rawget(t, core.registered_aliases[name])
end
}
setmetatable(core.registered_items, alias_metatable)
setmetatable(core.registered_nodes, alias_metatable)
setmetatable(core.registered_craftitems, alias_metatable)
setmetatable(core.registered_tools, alias_metatable)

View File

@ -0,0 +1,9 @@
core.log("info", "Initializing asynchronous environment")
function core.job_processor(func, serialized_param)
local param = core.deserialize(serialized_param)
local retval = core.serialize(func(param))
return retval or core.serialize(nil)
end

View File

@ -0,0 +1,74 @@
-- Minetest: builtin/client/chatcommands.lua
core.register_on_sending_chat_message(function(message)
if message:sub(1,2) == ".." then
return false
end
local first_char = message:sub(1,1)
if first_char == "/" or first_char == "." then
core.display_chat_message(core.gettext("Issued command: ") .. message)
end
if first_char ~= "." then
return false
end
local cmd, param = string.match(message, "^%.([^ ]+) *(.*)")
param = param or ""
if not cmd then
core.display_chat_message("-!- " .. core.gettext("Empty command."))
return true
end
-- Run core.registered_on_chatcommand callbacks.
if core.run_callbacks(core.registered_on_chatcommand, 5, cmd, param) then
return true
end
local cmd_def = core.registered_chatcommands[cmd]
if cmd_def then
core.set_last_run_mod(cmd_def.mod_origin)
local _, result = cmd_def.func(param)
if result then
core.display_chat_message(result)
end
else
core.display_chat_message("-!- " .. core.gettext("Invalid command: ") .. cmd)
end
return true
end)
core.register_chatcommand("list_players", {
description = core.gettext("List online players"),
func = function(param)
local player_names = core.get_player_names()
if not player_names then
return false, core.gettext("This command is disabled by server.")
end
local players = table.concat(player_names, ", ")
return true, core.gettext("Online players: ") .. players
end
})
core.register_chatcommand("disconnect", {
description = core.gettext("Exit to main menu"),
func = function(param)
core.disconnect()
end,
})
core.register_chatcommand("clear_chat_queue", {
description = core.gettext("Clear the out chat queue"),
func = function(param)
core.clear_out_chat_queue()
return true, core.gettext("The out chat queue is now empty.")
end,
})
function core.run_server_chatcommand(cmd, param)
core.send_chat_message("/" .. cmd .. " " .. param)
end

View File

@ -0,0 +1,15 @@
-- CSM death formspec. Only used when clientside modding is enabled, otherwise
-- handled by the engine.
core.register_on_death(function()
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
"label[4.85,1.35;" .. fgettext("You died") ..
"]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]"
core.show_formspec("bultin:death", formspec)
end)
core.register_on_formspec_input(function(formname, fields)
if formname == "bultin:death" then
core.send_respawn()
end
end)

12
builtin/client/init.lua Normal file
View File

@ -0,0 +1,12 @@
-- Minetest: builtin/client/init.lua
local scriptpath = core.get_builtin_path()
local clientpath = scriptpath.."client"..DIR_DELIM
local commonpath = scriptpath.."common"..DIR_DELIM
dofile(clientpath .. "register.lua")
dofile(commonpath .. "after.lua")
dofile(commonpath .. "mod_storage.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(clientpath .. "chatcommands.lua")
dofile(clientpath .. "death_formspec.lua")
dofile(clientpath .. "misc.lua")

7
builtin/client/misc.lua Normal file
View File

@ -0,0 +1,7 @@
function core.setting_get_pos(name)
local value = core.settings:get(name)
if not value then
return nil
end
return core.string_to_pos(value)
end

View File

@ -0,0 +1,83 @@
core.callback_origins = {}
local getinfo = debug.getinfo
debug.getinfo = nil
--- Runs given callbacks.
--
-- Note: this function is also called from C++
-- @tparam table callbacks a table with registered callbacks, like `core.registered_on_*`
-- @tparam number mode a RunCallbacksMode, as defined in src/script/common/c_internal.h
-- @param ... arguments for the callback
-- @return depends on mode
function core.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table")
local cb_len = #callbacks
if cb_len == 0 then
if mode == 2 or mode == 3 then
return true
elseif mode == 4 or mode == 5 then
return false
end
end
local ret
for i = 1, cb_len do
local cb_ret = callbacks[i](...)
if mode == 0 and i == 1 or mode == 1 and i == cb_len then
ret = cb_ret
elseif mode == 2 then
if not cb_ret or i == 1 then
ret = cb_ret
end
elseif mode == 3 then
if cb_ret then
return cb_ret
end
ret = cb_ret
elseif mode == 4 then
if (cb_ret and not ret) or i == 1 then
ret = cb_ret
end
elseif mode == 5 and cb_ret then
return cb_ret
end
end
return ret
end
--
-- Callback registration
--
local function make_registration()
local t = {}
local registerfunc = function(func)
t[#t + 1] = func
core.callback_origins[func] = {
mod = core.get_current_modname() or "??",
name = getinfo(1, "n").name or "??"
}
--local origin = core.callback_origins[func]
--print(origin.name .. ": " .. origin.mod .. " registering cbk " .. tostring(func))
end
return t, registerfunc
end
core.registered_globalsteps, core.register_globalstep = make_registration()
core.registered_on_mods_loaded, core.register_on_mods_loaded = make_registration()
core.registered_on_shutdown, core.register_on_shutdown = make_registration()
core.registered_on_receiving_chat_message, core.register_on_receiving_chat_message = make_registration()
core.registered_on_sending_chat_message, core.register_on_sending_chat_message = make_registration()
core.registered_on_chatcommand, core.register_on_chatcommand = make_registration()
core.registered_on_death, core.register_on_death = make_registration()
core.registered_on_hp_modification, core.register_on_hp_modification = make_registration()
core.registered_on_damage_taken, core.register_on_damage_taken = make_registration()
core.registered_on_formspec_input, core.register_on_formspec_input = make_registration()
core.registered_on_dignode, core.register_on_dignode = make_registration()
core.registered_on_punchnode, core.register_on_punchnode = make_registration()
core.registered_on_placenode, core.register_on_placenode = make_registration()
core.registered_on_item_use, core.register_on_item_use = make_registration()
core.registered_on_modchannel_message, core.register_on_modchannel_message = make_registration()
core.registered_on_modchannel_signal, core.register_on_modchannel_signal = make_registration()
core.registered_on_inventory_open, core.register_on_inventory_open = make_registration()

50
builtin/common/after.lua Normal file
View File

@ -0,0 +1,50 @@
local jobs = {}
local time = 0.0
local time_next = math.huge
core.register_globalstep(function(dtime)
time = time + dtime
if time < time_next then
return
end
time_next = math.huge
-- Iterate backwards so that we miss any new timers added by
-- a timer callback.
for i = #jobs, 1, -1 do
local job = jobs[i]
if time >= job.expire then
core.set_last_run_mod(job.mod_origin)
job.func(unpack(job.arg))
local jobs_l = #jobs
jobs[i] = jobs[jobs_l]
jobs[jobs_l] = nil
elseif job.expire < time_next then
time_next = job.expire
end
end
end)
function core.after(after, func, ...)
assert(tonumber(after) and type(func) == "function",
"Invalid minetest.after invocation")
local expire = time + after
local new_job = {
func = func,
expire = expire,
arg = {...},
mod_origin = core.get_last_run_mod(),
}
jobs[#jobs + 1] = new_job
time_next = math.min(time_next, expire)
return {
cancel = function()
new_job.func = function() end
new_job.args = {}
end
}
end

View File

@ -0,0 +1,178 @@
-- Minetest: builtin/common/chatcommands.lua
-- For server-side translations (if INIT == "game")
-- Otherwise, use core.gettext
local S = core.get_translator("__builtin")
core.registered_chatcommands = {}
-- Interpret the parameters of a command, separating options and arguments.
-- Input: command, param
-- command: name of command
-- param: parameters of command
-- Returns: opts, args
-- opts is a string of option letters, or false on error
-- args is an array with the non-option arguments in order, or an error message
-- Example: for this command line:
-- /command a b -cd e f -g
-- the function would receive:
-- a b -cd e f -g
-- and it would return:
-- "cdg", {"a", "b", "e", "f"}
-- Negative numbers are taken as arguments. Long options (--option) are
-- currently rejected as reserved.
local function getopts(command, param)
local opts = ""
local args = {}
for match in param:gmatch("%S+") do
if match:byte(1) == 45 then -- 45 = '-'
local second = match:byte(2)
if second == 45 then
return false, S("Invalid parameters (see /help @1).", command)
elseif second and (second < 48 or second > 57) then -- 48 = '0', 57 = '9'
opts = opts .. match:sub(2)
else
-- numeric, add it to args
args[#args + 1] = match
end
else
args[#args + 1] = match
end
end
return opts, args
end
function core.register_chatcommand(cmd, def)
def = def or {}
def.params = def.params or ""
def.description = def.description or ""
def.privs = def.privs or {}
def.mod_origin = core.get_current_modname() or "??"
core.registered_chatcommands[cmd] = def
end
function core.unregister_chatcommand(name)
if core.registered_chatcommands[name] then
core.registered_chatcommands[name] = nil
else
core.log("warning", "Not unregistering chatcommand " ..name..
" because it doesn't exist.")
end
end
function core.override_chatcommand(name, redefinition)
local chatcommand = core.registered_chatcommands[name]
assert(chatcommand, "Attempt to override non-existent chatcommand "..name)
for k, v in pairs(redefinition) do
rawset(chatcommand, k, v)
end
core.registered_chatcommands[name] = chatcommand
end
local function format_help_line(cmd, def)
local cmd_marker = INIT == "client" and "." or "/"
local msg = core.colorize("#00ffff", cmd_marker .. cmd)
if def.params and def.params ~= "" then
msg = msg .. " " .. def.params
end
if def.description and def.description ~= "" then
msg = msg .. ": " .. def.description
end
return msg
end
local function do_help_cmd(name, param)
local opts, args = getopts("help", param)
if not opts then
return false, args
end
if #args > 1 then
return false, S("Too many arguments, try using just /help <command>")
end
local use_gui = INIT ~= "client" and core.get_player_by_name(name)
use_gui = use_gui and not opts:find("t")
if #args == 0 and not use_gui then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = cmd
end
end
table.sort(cmds)
local msg
if INIT == "game" then
msg = S("Available commands: @1",
table.concat(cmds, " ")) .. "\n"
.. S("Use '/help <cmd>' to get more "
.. "information, or '/help all' to list "
.. "everything.")
else
msg = core.gettext("Available commands: ")
.. table.concat(cmds, " ") .. "\n"
.. core.gettext("Use '.help <cmd>' to get more "
.. "information, or '.help all' to list "
.. "everything.")
end
return true, msg
elseif #args == 0 or (args[1] == "all" and use_gui) then
core.show_general_help_formspec(name)
return true
elseif args[1] == "all" then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = format_help_line(cmd, def)
end
end
table.sort(cmds)
local msg
if INIT == "game" then
msg = S("Available commands:")
else
msg = core.gettext("Available commands:")
end
return true, msg.."\n"..table.concat(cmds, "\n")
elseif INIT == "game" and args[1] == "privs" then
if use_gui then
core.show_privs_help_formspec(name)
return true
end
local privs = {}
for priv, def in pairs(core.registered_privileges) do
privs[#privs + 1] = priv .. ": " .. def.description
end
table.sort(privs)
return true, S("Available privileges:").."\n"..table.concat(privs, "\n")
else
local cmd = args[1]
local def = core.registered_chatcommands[cmd]
if not def then
local msg
if INIT == "game" then
msg = S("Command not available: @1", cmd)
else
msg = core.gettext("Command not available: ") .. cmd
end
return false, msg
else
return true, format_help_line(cmd, def)
end
end
end
if INIT == "client" then
core.register_chatcommand("help", {
params = core.gettext("[all | <cmd>]"),
description = core.gettext("Get help for commands"),
func = function(param)
return do_help_cmd(nil, param)
end,
})
else
core.register_chatcommand("help", {
params = S("[all | privs | <cmd>] [-t]"),
description = S("Get help for commands or list privileges (-t: output in chat)"),
func = do_help_cmd,
})
end

View File

@ -0,0 +1,319 @@
--Minetest
--Copyright (C) 2013 sapier
--
--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.
--------------------------------------------------------------------------------
-- TODO improve doc --
-- TODO code cleanup --
-- Generic implementation of a filter/sortable list --
-- Usage: --
-- Filterlist needs to be initialized on creation. To achieve this you need to --
-- pass following functions: --
-- raw_fct() (mandatory): --
-- function returning a table containing the elements to be filtered --
-- compare_fct(element1,element2) (mandatory): --
-- function returning true/false if element1 is same element as element2 --
-- uid_match_fct(element1,uid) (optional) --
-- function telling if uid is attached to element1 --
-- filter_fct(element,filtercriteria) (optional) --
-- function returning true/false if filtercriteria met to element --
-- fetch_param (optional) --
-- parameter passed to raw_fct to aquire correct raw data --
-- --
--------------------------------------------------------------------------------
filterlist = {}
--------------------------------------------------------------------------------
function filterlist.refresh(self)
self.m_raw_list = self.m_raw_list_fct(self.m_fetch_param)
filterlist.process(self)
end
--------------------------------------------------------------------------------
function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
local self = {}
self.m_raw_list_fct = raw_fct
self.m_compare_fct = compare_fct
self.m_filter_fct = filter_fct
self.m_uid_match_fct = uid_match_fct
self.m_filtercriteria = nil
self.m_fetch_param = fetch_param
self.m_sortmode = "none"
self.m_sort_list = {}
self.m_processed_list = nil
self.m_raw_list = self.m_raw_list_fct(self.m_fetch_param)
self.add_sort_mechanism = filterlist.add_sort_mechanism
self.set_filtercriteria = filterlist.set_filtercriteria
self.get_filtercriteria = filterlist.get_filtercriteria
self.set_sortmode = filterlist.set_sortmode
self.get_list = filterlist.get_list
self.get_raw_list = filterlist.get_raw_list
self.get_raw_element = filterlist.get_raw_element
self.get_raw_index = filterlist.get_raw_index
self.get_current_index = filterlist.get_current_index
self.size = filterlist.size
self.uid_exists_raw = filterlist.uid_exists_raw
self.raw_index_by_uid = filterlist.raw_index_by_uid
self.refresh = filterlist.refresh
filterlist.process(self)
return self
end
--------------------------------------------------------------------------------
function filterlist.add_sort_mechanism(self,name,fct)
self.m_sort_list[name] = fct
end
--------------------------------------------------------------------------------
function filterlist.set_filtercriteria(self,criteria)
if criteria == self.m_filtercriteria and
type(criteria) ~= "table" then
return
end
self.m_filtercriteria = criteria
filterlist.process(self)
end
--------------------------------------------------------------------------------
function filterlist.get_filtercriteria(self)
return self.m_filtercriteria
end
--------------------------------------------------------------------------------
--supported sort mode "alphabetic|none"
function filterlist.set_sortmode(self,mode)
if (mode == self.m_sortmode) then
return
end
self.m_sortmode = mode
filterlist.process(self)
end
--------------------------------------------------------------------------------
function filterlist.get_list(self)
return self.m_processed_list
end
--------------------------------------------------------------------------------
function filterlist.get_raw_list(self)
return self.m_raw_list
end
--------------------------------------------------------------------------------
function filterlist.get_raw_element(self,idx)
if type(idx) ~= "number" then
idx = tonumber(idx)
end
if idx ~= nil and idx > 0 and idx <= #self.m_raw_list then
return self.m_raw_list[idx]
end
return nil
end
--------------------------------------------------------------------------------
function filterlist.get_raw_index(self,listindex)
assert(self.m_processed_list ~= nil)
if listindex ~= nil and listindex > 0 and
listindex <= #self.m_processed_list then
local entry = self.m_processed_list[listindex]
for i,v in ipairs(self.m_raw_list) do
if self.m_compare_fct(v,entry) then
return i
end
end
end
return 0
end
--------------------------------------------------------------------------------
function filterlist.get_current_index(self,listindex)
assert(self.m_processed_list ~= nil)
if listindex ~= nil and listindex > 0 and
listindex <= #self.m_raw_list then
local entry = self.m_raw_list[listindex]
for i,v in ipairs(self.m_processed_list) do
if self.m_compare_fct(v,entry) then
return i
end
end
end
return 0
end
--------------------------------------------------------------------------------
function filterlist.process(self)
assert(self.m_raw_list ~= nil)
if self.m_sortmode == "none" and
self.m_filtercriteria == nil then
self.m_processed_list = self.m_raw_list
return
end
self.m_processed_list = {}
for k,v in pairs(self.m_raw_list) do
if self.m_filtercriteria == nil or
self.m_filter_fct(v,self.m_filtercriteria) then
self.m_processed_list[#self.m_processed_list + 1] = v
end
end
if self.m_sortmode == "none" then
return
end
if self.m_sort_list[self.m_sortmode] ~= nil and
type(self.m_sort_list[self.m_sortmode]) == "function" then
self.m_sort_list[self.m_sortmode](self)
end
end
--------------------------------------------------------------------------------
function filterlist.size(self)
if self.m_processed_list == nil then
return 0
end
return #self.m_processed_list
end
--------------------------------------------------------------------------------
function filterlist.uid_exists_raw(self,uid)
for i,v in ipairs(self.m_raw_list) do
if self.m_uid_match_fct(v,uid) then
return true
end
end
return false
end
--------------------------------------------------------------------------------
function filterlist.raw_index_by_uid(self, uid)
local elementcount = 0
local elementidx = 0
for i,v in ipairs(self.m_raw_list) do
if self.m_uid_match_fct(v,uid) then
elementcount = elementcount +1
elementidx = i
end
end
-- If there are more elements than one with same name uid can't decide which
-- one is meant. self shouldn't be possible but just for sure.
if elementcount > 1 then
elementidx=0
end
return elementidx
end
--------------------------------------------------------------------------------
-- COMMON helper functions --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function compare_worlds(world1,world2)
if world1.path ~= world2.path then
return false
end
if world1.name ~= world2.name then
return false
end
if world1.gameid ~= world2.gameid then
return false
end
return true
end
--------------------------------------------------------------------------------
function sort_worlds_alphabetic(self)
table.sort(self.m_processed_list, function(a, b)
--fixes issue #857 (crash due to sorting nil in worldlist)
if a == nil or b == nil then
if a == nil and b ~= nil then return false end
if b == nil and a ~= nil then return true end
return false
end
if a.name:lower() == b.name:lower() then
return a.name < b.name
end
return a.name:lower() < b.name:lower()
end)
end
--------------------------------------------------------------------------------
function sort_mod_list(self)
table.sort(self.m_processed_list, function(a, b)
-- Show game mods at bottom
if a.type ~= b.type or a.loc ~= b.loc then
if b.type == "game" then
return a.loc ~= "game"
end
return b.loc == "game"
end
-- If in same or no modpack, sort by name
if a.modpack == b.modpack then
if a.name:lower() == b.name:lower() then
return a.name < b.name
end
return a.name:lower() < b.name:lower()
-- Else compare name to modpack name
else
-- Always show modpack pseudo-mod on top of modpack mod list
if a.name == b.modpack then
return true
elseif b.name == a.modpack then
return false
end
local name_a = a.modpack or a.name
local name_b = b.modpack or b.name
if name_a:lower() == name_b:lower() then
return name_a < name_b
end
return name_a:lower() < name_b:lower()
end
end)
end

View File

@ -0,0 +1,136 @@
local COLOR_BLUE = "#7AF"
local COLOR_GREEN = "#7F7"
local COLOR_GRAY = "#BBB"
local LIST_FORMSPEC = [[
size[13,6.5]
label[0,-0.1;%s]
tablecolumns[color;tree;text;text]
table[0,0.5;12.8,5.5;list;%s;0]
button_exit[5,6;3,1;quit;%s]
]]
local LIST_FORMSPEC_DESCRIPTION = [[
size[13,7.5]
label[0,-0.1;%s]
tablecolumns[color;tree;text;text]
table[0,0.5;12.8,4.8;list;%s;%i]
box[0,5.5;12.8,1.5;#000]
textarea[0.3,5.5;13.05,1.9;;;%s]
button_exit[5,7;3,1;quit;%s]
]]
local F = core.formspec_escape
local S = core.get_translator("__builtin")
-- CHAT COMMANDS FORMSPEC
local mod_cmds = {}
local function load_mod_command_tree()
mod_cmds = {}
for name, def in pairs(core.registered_chatcommands) do
mod_cmds[def.mod_origin] = mod_cmds[def.mod_origin] or {}
local cmds = mod_cmds[def.mod_origin]
-- Could be simplified, but avoid the priv checks whenever possible
cmds[#cmds + 1] = { name, def }
end
local sorted_mod_cmds = {}
for modname, cmds in pairs(mod_cmds) do
table.sort(cmds, function(a, b) return a[1] < b[1] end)
sorted_mod_cmds[#sorted_mod_cmds + 1] = { modname, cmds }
end
table.sort(sorted_mod_cmds, function(a, b) return a[1] < b[1] end)
mod_cmds = sorted_mod_cmds
end
core.after(0, load_mod_command_tree)
local function build_chatcommands_formspec(name, sel, copy)
local rows = {}
rows[1] = "#FFF,0,"..F(S("Command"))..","..F(S("Parameters"))
local description = S("For more information, click on "
.. "any entry in the list.").. "\n" ..
S("Double-click to copy the entry to the chat history.")
local privs = core.get_player_privs(name)
for i, data in ipairs(mod_cmds) do
rows[#rows + 1] = COLOR_BLUE .. ",0," .. F(data[1]) .. ","
for j, cmds in ipairs(data[2]) do
local has_priv = privs[cmds[2].privs]
rows[#rows + 1] = ("%s,1,%s,%s"):format(
has_priv and COLOR_GREEN or COLOR_GRAY,
cmds[1], F(cmds[2].params))
if sel == #rows then
description = cmds[2].description
if copy then
core.chat_send_player(name, S("Command: @1 @2",
core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params))
end
end
end
end
return LIST_FORMSPEC_DESCRIPTION:format(
F(S("Available commands: (see also: /help <cmd>)")),
table.concat(rows, ","), sel or 0,
F(description), F(S("Close"))
)
end
-- PRIVILEGES FORMSPEC
local function build_privs_formspec(name)
local privs = {}
for priv_name, def in pairs(core.registered_privileges) do
privs[#privs + 1] = { priv_name, def }
end
table.sort(privs, function(a, b) return a[1] < b[1] end)
local rows = {}
rows[1] = "#FFF,0,"..F(S("Privilege"))..","..F(S("Description"))
local player_privs = core.get_player_privs(name)
for i, data in ipairs(privs) do
rows[#rows + 1] = ("%s,0,%s,%s"):format(
player_privs[data[1]] and COLOR_GREEN or COLOR_GRAY,
data[1], F(data[2].description))
end
return LIST_FORMSPEC:format(
F(S("Available privileges:")),
table.concat(rows, ","),
F(S("Close"))
)
end
-- DETAILED CHAT COMMAND INFORMATION
core.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "__builtin:help_cmds" or fields.quit then
return
end
local event = core.explode_table_event(fields.list)
if event.type ~= "INV" then
local name = player:get_player_name()
core.show_formspec(name, "__builtin:help_cmds",
build_chatcommands_formspec(name, event.row, event.type == "DCL"))
end
end)
function core.show_general_help_formspec(name)
core.show_formspec(name, "__builtin:help_cmds",
build_chatcommands_formspec(name))
end
function core.show_privs_help_formspec(name)
core.show_formspec(name, "__builtin:help_privs",
build_privs_formspec(name))
end

View File

@ -0,0 +1,770 @@
-- Minetest: builtin/misc_helpers.lua
--------------------------------------------------------------------------------
-- Localize functions to avoid table lookups (better performance).
local string_sub, string_find = string.sub, string.find
--------------------------------------------------------------------------------
local function basic_dump(o)
local tp = type(o)
if tp == "number" then
return tostring(o)
elseif tp == "string" then
return string.format("%q", o)
elseif tp == "boolean" then
return tostring(o)
elseif tp == "nil" then
return "nil"
-- Uncomment for full function dumping support.
-- Not currently enabled because bytecode isn't very human-readable and
-- dump's output is intended for humans.
--elseif tp == "function" then
-- return string.format("loadstring(%q)", string.dump(o))
elseif tp == "userdata" then
return tostring(o)
else
return string.format("<%s>", tp)
end
end
local keywords = {
["and"] = true,
["break"] = true,
["do"] = true,
["else"] = true,
["elseif"] = true,
["end"] = true,
["false"] = true,
["for"] = true,
["function"] = true,
["goto"] = true, -- Lua 5.2
["if"] = true,
["in"] = true,
["local"] = true,
["nil"] = true,
["not"] = true,
["or"] = true,
["repeat"] = true,
["return"] = true,
["then"] = true,
["true"] = true,
["until"] = true,
["while"] = true,
}
local function is_valid_identifier(str)
if not str:find("^[a-zA-Z_][a-zA-Z0-9_]*$") or keywords[str] then
return false
end
return true
end
--------------------------------------------------------------------------------
-- Dumps values in a line-per-value format.
-- For example, {test = {"Testing..."}} becomes:
-- _["test"] = {}
-- _["test"][1] = "Testing..."
-- This handles tables as keys and circular references properly.
-- It also handles multiple references well, writing the table only once.
-- The dumped argument is internal-only.
function dump2(o, name, dumped)
name = name or "_"
-- "dumped" is used to keep track of serialized tables to handle
-- multiple references and circular tables properly.
-- It only contains tables as keys. The value is the name that
-- the table has in the dump, eg:
-- {x = {"y"}} -> dumped[{"y"}] = '_["x"]'
dumped = dumped or {}
if type(o) ~= "table" then
return string.format("%s = %s\n", name, basic_dump(o))
end
if dumped[o] then
return string.format("%s = %s\n", name, dumped[o])
end
dumped[o] = name
-- This contains a list of strings to be concatenated later (because
-- Lua is slow at individual concatenation).
local t = {}
for k, v in pairs(o) do
local keyStr
if type(k) == "table" then
if dumped[k] then
keyStr = dumped[k]
else
-- Key tables don't have a name, so use one of
-- the form _G["table: 0xFFFFFFF"]
keyStr = string.format("_G[%q]", tostring(k))
-- Dump key table
t[#t + 1] = dump2(k, keyStr, dumped)
end
else
keyStr = basic_dump(k)
end
local vname = string.format("%s[%s]", name, keyStr)
t[#t + 1] = dump2(v, vname, dumped)
end
return string.format("%s = {}\n%s", name, table.concat(t))
end
--------------------------------------------------------------------------------
-- This dumps values in a one-statement format.
-- For example, {test = {"Testing..."}} becomes:
-- [[{
-- test = {
-- "Testing..."
-- }
-- }]]
-- This supports tables as keys, but not circular references.
-- It performs poorly with multiple references as it writes out the full
-- table each time.
-- The indent field specifies a indentation string, it defaults to a tab.
-- Use the empty string to disable indentation.
-- The dumped and level arguments are internal-only.
function dump(o, indent, nested, level)
local t = type(o)
if not level and t == "userdata" then
-- when userdata (e.g. player) is passed directly, print its metatable:
return "userdata metatable: " .. dump(getmetatable(o))
end
if t ~= "table" then
return basic_dump(o)
end
-- Contains table -> true/nil of currently nested tables
nested = nested or {}
if nested[o] then
return "<circular reference>"
end
nested[o] = true
indent = indent or "\t"
level = level or 1
local ret = {}
local dumped_indexes = {}
for i, v in ipairs(o) do
ret[#ret + 1] = dump(v, indent, nested, level + 1)
dumped_indexes[i] = true
end
for k, v in pairs(o) do
if not dumped_indexes[k] then
if type(k) ~= "string" or not is_valid_identifier(k) then
k = "["..dump(k, indent, nested, level + 1).."]"
end
v = dump(v, indent, nested, level + 1)
ret[#ret + 1] = k.." = "..v
end
end
nested[o] = nil
if indent ~= "" then
local indent_str = "\n"..string.rep(indent, level)
local end_indent_str = "\n"..string.rep(indent, level - 1)
return string.format("{%s%s%s}",
indent_str,
table.concat(ret, ","..indent_str),
end_indent_str)
end
return "{"..table.concat(ret, ", ").."}"
end
--------------------------------------------------------------------------------
function string.split(str, delim, include_empty, max_splits, sep_is_pattern)
delim = delim or ","
max_splits = max_splits or -2
local items = {}
local pos, len = 1, #str
local plain = not sep_is_pattern
max_splits = max_splits + 1
repeat
local np, npe = string_find(str, delim, pos, plain)
np, npe = (np or (len+1)), (npe or (len+1))
if (not np) or (max_splits == 1) then
np = len + 1
npe = np
end
local s = string_sub(str, pos, np - 1)
if include_empty or (s ~= "") then
max_splits = max_splits - 1
items[#items + 1] = s
end
pos = npe + 1
until (max_splits == 0) or (pos > (len + 1))
return items
end
--------------------------------------------------------------------------------
function table.indexof(list, val)
for i, v in ipairs(list) do
if v == val then
return i
end
end
return -1
end
--------------------------------------------------------------------------------
function string:trim()
return self:match("^%s*(.-)%s*$")
end
--------------------------------------------------------------------------------
function math.hypot(x, y)
return math.sqrt(x * x + y * y)
end
--------------------------------------------------------------------------------
function math.sign(x, tolerance)
tolerance = tolerance or 0
if x > tolerance then
return 1
elseif x < -tolerance then
return -1
end
return 0
end
--------------------------------------------------------------------------------
function math.factorial(x)
assert(x % 1 == 0 and x >= 0, "factorial expects a non-negative integer")
if x >= 171 then
-- 171! is greater than the biggest double, no need to calculate
return math.huge
end
local v = 1
for k = 2, x do
v = v * k
end
return v
end
function math.round(x)
if x >= 0 then
return math.floor(x + 0.5)
end
return math.ceil(x - 0.5)
end
local formspec_escapes = {
["\\"] = "\\\\",
["["] = "\\[",
["]"] = "\\]",
[";"] = "\\;",
[","] = "\\,"
}
function core.formspec_escape(text)
-- Use explicit character set instead of dot here because it doubles the performance
return text and string.gsub(text, "[\\%[%];,]", formspec_escapes)
end
function core.wrap_text(text, max_length, as_table)
local result = {}
local line = {}
if #text <= max_length then
return as_table and {text} or text
end
local line_length = 0
for word in text:gmatch("%S+") do
if line_length > 0 and line_length + #word + 1 >= max_length then
-- word wouldn't fit on current line, move to next line
table.insert(result, table.concat(line, " "))
line = {word}
line_length = #word
else
table.insert(line, word)
line_length = line_length + 1 + #word
end
end
table.insert(result, table.concat(line, " "))
return as_table and result or table.concat(result, "\n")
end
--------------------------------------------------------------------------------
if INIT == "game" then
local dirs1 = {9, 18, 7, 12}
local dirs2 = {20, 23, 22, 21}
function core.rotate_and_place(itemstack, placer, pointed_thing,
infinitestacks, orient_flags, prevent_after_place)
orient_flags = orient_flags or {}
local unode = core.get_node_or_nil(pointed_thing.under)
if not unode then
return
end
local undef = core.registered_nodes[unode.name]
local sneaking = placer and placer:get_player_control().sneak
if undef and undef.on_rightclick and not sneaking then
return undef.on_rightclick(pointed_thing.under, unode, placer,
itemstack, pointed_thing)
end
local fdir = placer and core.dir_to_facedir(placer:get_look_dir()) or 0
local above = pointed_thing.above
local under = pointed_thing.under
local iswall = (above.y == under.y)
local isceiling = not iswall and (above.y < under.y)
if undef and undef.buildable_to then
iswall = false
end
if orient_flags.force_floor then
iswall = false
isceiling = false
elseif orient_flags.force_ceiling then
iswall = false
isceiling = true
elseif orient_flags.force_wall then
iswall = true
isceiling = false
elseif orient_flags.invert_wall then
iswall = not iswall
end
local param2 = fdir
if iswall then
param2 = dirs1[fdir + 1]
elseif isceiling then
if orient_flags.force_facedir then
param2 = 20
else
param2 = dirs2[fdir + 1]
end
else -- place right side up
if orient_flags.force_facedir then
param2 = 0
end
end
local old_itemstack = ItemStack(itemstack)
local new_itemstack = core.item_place_node(itemstack, placer,
pointed_thing, param2, prevent_after_place)
return infinitestacks and old_itemstack or new_itemstack
end
--------------------------------------------------------------------------------
--Wrapper for rotate_and_place() to check for sneak and assume Creative mode
--implies infinite stacks when performing a 6d rotation.
--------------------------------------------------------------------------------
core.rotate_node = function(itemstack, placer, pointed_thing)
local name = placer and placer:get_player_name() or ""
local invert_wall = placer and placer:get_player_control().sneak or false
return core.rotate_and_place(itemstack, placer, pointed_thing,
core.is_creative_enabled(name),
{invert_wall = invert_wall}, true)
end
end
--------------------------------------------------------------------------------
function core.explode_table_event(evt)
if evt ~= nil then
local parts = evt:split(":")
if #parts == 3 then
local t = parts[1]:trim()
local r = tonumber(parts[2]:trim())
local c = tonumber(parts[3]:trim())
if type(r) == "number" and type(c) == "number"
and t ~= "INV" then
return {type=t, row=r, column=c}
end
end
end
return {type="INV", row=0, column=0}
end
--------------------------------------------------------------------------------
function core.explode_textlist_event(evt)
if evt ~= nil then
local parts = evt:split(":")
if #parts == 2 then
local t = parts[1]:trim()
local r = tonumber(parts[2]:trim())
if type(r) == "number" and t ~= "INV" then
return {type=t, index=r}
end
end
end
return {type="INV", index=0}
end
--------------------------------------------------------------------------------
function core.explode_scrollbar_event(evt)
local retval = core.explode_textlist_event(evt)
retval.value = retval.index
retval.index = nil
return retval
end
--------------------------------------------------------------------------------
function core.rgba(r, g, b, a)
return a and string.format("#%02X%02X%02X%02X", r, g, b, a) or
string.format("#%02X%02X%02X", r, g, b)
end
--------------------------------------------------------------------------------
function core.pos_to_string(pos, decimal_places)
local x = pos.x
local y = pos.y
local z = pos.z
if decimal_places ~= nil then
x = string.format("%." .. decimal_places .. "f", x)
y = string.format("%." .. decimal_places .. "f", y)
z = string.format("%." .. decimal_places .. "f", z)
end
return "(" .. x .. "," .. y .. "," .. z .. ")"
end
--------------------------------------------------------------------------------
function core.string_to_pos(value)
if value == nil then
return nil
end
value = value:match("^%((.-)%)$") or value -- strip parentheses
local x, y, z = value:trim():match("^([%d.-]+)[,%s]%s*([%d.-]+)[,%s]%s*([%d.-]+)$")
if x and y and z then
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
return vector.new(x, y, z)
end
return nil
end
--------------------------------------------------------------------------------
do
local rel_num_cap = "(~?-?%d*%.?%d*)" -- may be overly permissive as this will be tonumber'ed anyways
local num_delim = "[,%s]%s*"
local pattern = "^" .. table.concat({rel_num_cap, rel_num_cap, rel_num_cap}, num_delim) .. "$"
local function parse_area_string(pos, relative_to)
local pp = {}
pp.x, pp.y, pp.z = pos:trim():match(pattern)
return core.parse_coordinates(pp.x, pp.y, pp.z, relative_to)
end
function core.string_to_area(value, relative_to)
local p1, p2 = value:match("^%((.-)%)%s*%((.-)%)$")
if not p1 then
return
end
p1 = parse_area_string(p1, relative_to)
p2 = parse_area_string(p2, relative_to)
if p1 == nil or p2 == nil then
return
end
return p1, p2
end
end
--------------------------------------------------------------------------------
function table.copy(t, seen)
local n = {}
seen = seen or {}
seen[t] = n
for k, v in pairs(t) do
n[(type(k) == "table" and (seen[k] or table.copy(k, seen))) or k] =
(type(v) == "table" and (seen[v] or table.copy(v, seen))) or v
end
return n
end
function table.insert_all(t, other)
for i=1, #other do
t[#t + 1] = other[i]
end
return t
end
function table.key_value_swap(t)
local ti = {}
for k,v in pairs(t) do
ti[v] = k
end
return ti
end
function table.shuffle(t, from, to, random)
from = from or 1
to = to or #t
random = random or math.random
local n = to - from + 1
while n > 1 do
local r = from + n-1
local l = from + random(0, n-1)
t[l], t[r] = t[r], t[l]
n = n-1
end
end
--------------------------------------------------------------------------------
-- mainmenu only functions
--------------------------------------------------------------------------------
if INIT == "mainmenu" then
function core.get_game(index)
local games = core.get_games()
if index > 0 and index <= #games then
return games[index]
end
return nil
end
end
if core.gettext then -- for client and mainmenu
function fgettext_ne(text, ...)
text = core.gettext(text)
local arg = {n=select('#', ...), ...}
if arg.n >= 1 then
-- Insert positional parameters ($1, $2, ...)
local result = ''
local pos = 1
while pos <= text:len() do
local newpos = text:find('[$]', pos)
if newpos == nil then
result = result .. text:sub(pos)
pos = text:len() + 1
else
local paramindex =
tonumber(text:sub(newpos+1, newpos+1))
result = result .. text:sub(pos, newpos-1)
.. tostring(arg[paramindex])
pos = newpos + 2
end
end
text = result
end
return text
end
function fgettext(text, ...)
return core.formspec_escape(fgettext_ne(text, ...))
end
end
local ESCAPE_CHAR = string.char(0x1b)
function core.get_color_escape_sequence(color)
return ESCAPE_CHAR .. "(c@" .. color .. ")"
end
function core.get_background_escape_sequence(color)
return ESCAPE_CHAR .. "(b@" .. color .. ")"
end
function core.colorize(color, message)
local lines = tostring(message):split("\n", true)
local color_code = core.get_color_escape_sequence(color)
for i, line in ipairs(lines) do
lines[i] = color_code .. line
end
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
end
function core.strip_foreground_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", ""))
end
function core.strip_background_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%(b@[^)]+%)", ""))
end
function core.strip_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%([bc]@[^)]+%)", ""))
end
function core.translate(textdomain, str, ...)
local start_seq
if textdomain == "" then
start_seq = ESCAPE_CHAR .. "T"
else
start_seq = ESCAPE_CHAR .. "(T@" .. textdomain .. ")"
end
local arg = {n=select('#', ...), ...}
local end_seq = ESCAPE_CHAR .. "E"
local arg_index = 1
local translated = str:gsub("@(.)", function(matched)
local c = string.byte(matched)
if string.byte("1") <= c and c <= string.byte("9") then
local a = c - string.byte("0")
if a ~= arg_index then
error("Escape sequences in string given to core.translate " ..
"are not in the correct order: got @" .. matched ..
"but expected @" .. tostring(arg_index))
end
if a > arg.n then
error("Not enough arguments provided to core.translate")
end
arg_index = arg_index + 1
return ESCAPE_CHAR .. "F" .. arg[a] .. ESCAPE_CHAR .. "E"
elseif matched == "n" then
return "\n"
else
return matched
end
end)
if arg_index < arg.n + 1 then
error("Too many arguments provided to core.translate")
end
return start_seq .. translated .. end_seq
end
function core.get_translator(textdomain)
return function(str, ...) return core.translate(textdomain or "", str, ...) end
end
--------------------------------------------------------------------------------
-- Returns the exact coordinate of a pointed surface
--------------------------------------------------------------------------------
function core.pointed_thing_to_face_pos(placer, pointed_thing)
-- Avoid crash in some situations when player is inside a node, causing
-- 'above' to equal 'under'.
if vector.equals(pointed_thing.above, pointed_thing.under) then
return pointed_thing.under
end
local eye_height = placer:get_properties().eye_height
local eye_offset_first = placer:get_eye_offset()
local node_pos = pointed_thing.under
local camera_pos = placer:get_pos()
local pos_off = vector.multiply(
vector.subtract(pointed_thing.above, node_pos), 0.5)
local look_dir = placer:get_look_dir()
local offset, nc
local oc = {}
for c, v in pairs(pos_off) do
if nc or v == 0 then
oc[#oc + 1] = c
else
offset = v
nc = c
end
end
local fine_pos = {[nc] = node_pos[nc] + offset}
camera_pos.y = camera_pos.y + eye_height + eye_offset_first.y / 10
local f = (node_pos[nc] + offset - camera_pos[nc]) / look_dir[nc]
for i = 1, #oc do
fine_pos[oc[i]] = camera_pos[oc[i]] + look_dir[oc[i]] * f
end
return fine_pos
end
function core.string_to_privs(str, delim)
assert(type(str) == "string")
delim = delim or ','
local privs = {}
for _, priv in pairs(string.split(str, delim)) do
privs[priv:trim()] = true
end
return privs
end
function core.privs_to_string(privs, delim)
assert(type(privs) == "table")
delim = delim or ','
local list = {}
for priv, bool in pairs(privs) do
if bool then
list[#list + 1] = priv
end
end
return table.concat(list, delim)
end
function core.is_nan(number)
return number ~= number
end
--[[ Helper function for parsing an optionally relative number
of a chat command parameter, using the chat command tilde notation.
Parameters:
* arg: String snippet containing the number; possible values:
* "<number>": return as number
* "~<number>": return relative_to + <number>
* "~": return relative_to
* Anything else will return `nil`
* relative_to: Number to which the `arg` number might be relative to
Returns:
A number or `nil`, depending on `arg.
Examples:
* `core.parse_relative_number("5", 10)` returns 5
* `core.parse_relative_number("~5", 10)` returns 15
* `core.parse_relative_number("~", 10)` returns 10
]]
function core.parse_relative_number(arg, relative_to)
if not arg then
return nil
elseif arg == "~" then
return relative_to
elseif string.sub(arg, 1, 1) == "~" then
local number = tonumber(string.sub(arg, 2))
if not number then
return nil
end
if core.is_nan(number) or number == math.huge or number == -math.huge then
return nil
end
return relative_to + number
else
local number = tonumber(arg)
if core.is_nan(number) or number == math.huge or number == -math.huge then
return nil
end
return number
end
end
--[[ Helper function to parse coordinates that might be relative
to another position; supports chat command tilde notation.
Intended to be used in chat command parameter parsing.
Parameters:
* x, y, z: Parsed x, y, and z coordinates as strings
* relative_to: Position to which to compare the position
Syntax of x, y and z:
* "<number>": return as number
* "~<number>": return <number> + player position on this axis
* "~": return player position on this axis
Returns: a vector or nil for invalid input or if player does not exist
]]
function core.parse_coordinates(x, y, z, relative_to)
if not relative_to then
x, y, z = tonumber(x), tonumber(y), tonumber(z)
return x and y and z and { x = x, y = y, z = z }
end
local rx = core.parse_relative_number(x, relative_to.x)
local ry = core.parse_relative_number(y, relative_to.y)
local rz = core.parse_relative_number(z, relative_to.z)
return rx and ry and rz and { x = rx, y = ry, z = rz }
end

View File

@ -0,0 +1,19 @@
-- Modify core.get_mod_storage to return the storage for the current mod.
local get_current_modname = core.get_current_modname
local old_get_mod_storage = core.get_mod_storage
local storages = setmetatable({}, {
__mode = "v", -- values are weak references (can be garbage-collected)
__index = function(self, modname)
local storage = old_get_mod_storage(modname)
self[modname] = storage
return storage
end,
})
function core.get_mod_storage()
local modname = get_current_modname()
return modname and storages[modname]
end

View File

@ -0,0 +1,238 @@
--- Lua module to serialize values as Lua code.
-- From: https://github.com/appgurueu/modlib/blob/master/luon.lua
-- License: MIT
local next, rawget, pairs, pcall, error, type, setfenv, loadstring
= next, rawget, pairs, pcall, error, type, setfenv, loadstring
local table_concat, string_dump, string_format, string_match, math_huge
= table.concat, string.dump, string.format, string.match, math.huge
-- Recursively counts occurences of objects (non-primitives including strings) in a table.
local function count_objects(value)
local counts = {}
if value == nil then
-- Early return for nil; tables can't contain nil
return counts
end
local function count_values(val)
local type_ = type(val)
if type_ == "boolean" or type_ == "number" then
return
end
local count = counts[val]
counts[val] = (count or 0) + 1
if type_ == "table" then
if not count then
for k, v in pairs(val) do
count_values(k)
count_values(v)
end
end
elseif type_ ~= "string" and type_ ~= "function" then
error("unsupported type: " .. type_)
end
end
count_values(value)
return counts
end
-- Build a "set" of Lua keywords. These can't be used as short key names.
-- See https://www.lua.org/manual/5.1/manual.html#2.1
local keywords = {}
for _, keyword in pairs({
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or",
"repeat", "return", "then", "true", "until", "while",
"goto" -- LuaJIT, Lua 5.2+
}) do
keywords[keyword] = true
end
local function quote(string)
return string_format("%q", string)
end
local function dump_func(func)
return string_format("loadstring(%q)", string_dump(func))
end
-- Serializes Lua nil, booleans, numbers, strings, tables and even functions
-- Tables are referenced by reference, strings are referenced by value. Supports circular tables.
local function serialize(value, write)
local reference, refnum = "1", 1
-- [object] = reference
local references = {}
-- Circular tables that must be filled using `table[key] = value` statements
local to_fill = {}
for object, count in pairs(count_objects(value)) do
local type_ = type(object)
-- Object must appear more than once. If it is a string, the reference has to be shorter than the string.
if count >= 2 and (type_ ~= "string" or #reference + 5 < #object) then
if refnum == 1 then
write"local _={};" -- initialize reference table
end
write"_["
write(reference)
write("]=")
if type_ == "table" then
write("{}")
elseif type_ == "function" then
write(dump_func(object))
elseif type_ == "string" then
write(quote(object))
end
write(";")
references[object] = reference
if type_ == "table" then
to_fill[object] = reference
end
refnum = refnum + 1
reference = ("%d"):format(refnum)
end
end
-- Used to decide whether we should do "key=..."
local function use_short_key(key)
return not references[key] and type(key) == "string" and (not keywords[key]) and string_match(key, "^[%a_][%a%d_]*$")
end
local function dump(value)
-- Primitive types
if value == nil then
return write("nil")
end
if value == true then
return write("true")
end
if value == false then
return write("false")
end
local type_ = type(value)
if type_ == "number" then
if value ~= value then -- nan
return write"0/0"
elseif value == math_huge then
return write"1/0"
elseif value == -math_huge then
return write"-1/0"
else
return write(string_format("%.17g", value))
end
end
-- Reference types: table, function and string
local ref = references[value]
if ref then
write"_["
write(ref)
return write"]"
end
if type_ == "string" then
return write(quote(value))
end
if type_ == "function" then
return write(dump_func(value))
end
if type_ == "table" then
write("{")
-- First write list keys:
-- Don't use the table length #value here as it may horribly fail
-- for tables which use large integers as keys in the hash part;
-- stop at the first "hole" (nil value) instead
local len = 0
local first = true -- whether this is the first entry, which may not have a leading comma
while true do
local v = rawget(value, len + 1) -- use rawget to avoid metatables like the vector metatable
if v == nil then break end
if first then first = false else write(",") end
dump(v)
len = len + 1
end
-- Now write map keys ([key] = value)
for k, v in next, value do
-- We have written all non-float keys in [1, len] already
if type(k) ~= "number" or k % 1 ~= 0 or k < 1 or k > len then
if first then first = false else write(",") end
if use_short_key(k) then
write(k)
else
write("[")
dump(k)
write("]")
end
write("=")
dump(v)
end
end
write("}")
return
end
end
-- Write the statements to fill circular tables
for table, ref in pairs(to_fill) do
for k, v in pairs(table) do
write("_[")
write(ref)
write("]")
if use_short_key(k) then
write(".")
write(k)
else
write("[")
dump(k)
write("]")
end
write("=")
dump(v)
write(";")
end
end
write("return ")
dump(value)
end
function core.serialize(value)
local rope = {}
serialize(value, function(text)
-- Faster than table.insert(rope, text) on PUC Lua 5.1
rope[#rope + 1] = text
end)
return table_concat(rope)
end
local function dummy_func() end
function core.deserialize(str, safe)
-- Backwards compatibility
if str == nil then
core.log("deprecated", "minetest.deserialize called with nil (expected string).")
return nil, "Invalid type: Expected a string, got nil"
end
local t = type(str)
if t ~= "string" then
error(("minetest.deserialize called with %s (expected string)."):format(t))
end
local func, err = loadstring(str)
if not func then return nil, err end
-- math.huge was serialized to inf and NaNs to nan by Lua in Minetest 5.6, so we have to support this here
local env = {inf = math_huge, nan = 0/0}
if safe then
env.loadstring = dummy_func
else
env.loadstring = function(str, ...)
local func, err = loadstring(str, ...)
if func then
setfenv(func, env)
return func
end
return nil, err
end
end
setfenv(func, env)
local success, value_or_err = pcall(func)
if success then
return value_or_err
end
return nil, value_or_err
end

46
builtin/common/strict.lua Normal file
View File

@ -0,0 +1,46 @@
local getinfo, rawget, rawset = debug.getinfo, rawget, rawset
function core.global_exists(name)
if type(name) ~= "string" then
error("core.global_exists: " .. tostring(name) .. " is not a string")
end
return rawget(_G, name) ~= nil
end
local meta = {}
local declared = {}
-- Key is source file, line, and variable name; seperated by NULs
local warned = {}
function meta:__newindex(name, value)
if declared[name] then
return
end
local info = getinfo(2, "Sl")
local desc = ("%s:%d"):format(info.short_src, info.currentline)
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
if not warned[warn_key] and info.what ~= "main" and info.what ~= "C" then
core.log("warning", ("Assignment to undeclared global %q inside a function at %s.")
:format(name, desc))
warned[warn_key] = true
end
rawset(self, name, value)
declared[name] = true
end
function meta:__index(name)
if declared[name] then
return
end
local info = getinfo(2, "Sl")
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
if not warned[warn_key] and info.what ~= "C" then
core.log("warning", ("Undeclared global variable %q accessed at %s:%s")
:format(name, info.short_src, info.currentline))
warned[warn_key] = true
end
end
setmetatable(_G, meta)

View File

@ -0,0 +1,173 @@
_G.core = {}
_G.vector = {metatable = {}}
dofile("builtin/common/vector.lua")
dofile("builtin/common/misc_helpers.lua")
describe("string", function()
it("trim()", function()
assert.equal("foo bar", string.trim("\n \t\tfoo bar\t "))
end)
describe("split()", function()
it("removes empty", function()
assert.same({ "hello" }, string.split("hello"))
assert.same({ "hello", "world" }, string.split("hello,world"))
assert.same({ "hello", "world" }, string.split("hello,world,,,"))
assert.same({ "hello", "world" }, string.split(",,,hello,world"))
assert.same({ "hello", "world", "2" }, string.split("hello,,,world,2"))
assert.same({ "hello ", " world" }, string.split("hello :| world", ":|"))
end)
it("keeps empty", function()
assert.same({ "hello" }, string.split("hello", ",", true))
assert.same({ "hello", "world" }, string.split("hello,world", ",", true))
assert.same({ "hello", "world", "" }, string.split("hello,world,", ",", true))
assert.same({ "hello", "", "", "world", "2" }, string.split("hello,,,world,2", ",", true))
assert.same({ "", "", "hello", "world", "2" }, string.split(",,hello,world,2", ",", true))
assert.same({ "hello ", " world | :" }, string.split("hello :| world | :", ":|"))
end)
it("max_splits", function()
assert.same({ "one" }, string.split("one", ",", true, 2))
assert.same({ "one,two,three,four" }, string.split("one,two,three,four", ",", true, 0))
assert.same({ "one", "two", "three,four" }, string.split("one,two,three,four", ",", true, 2))
assert.same({ "one", "", "two,three,four" }, string.split("one,,two,three,four", ",", true, 2))
assert.same({ "one", "two", "three,four" }, string.split("one,,,,,,two,three,four", ",", false, 2))
end)
it("pattern", function()
assert.same({ "one", "two" }, string.split("one,two", ",", false, -1, true))
assert.same({ "one", "two", "three" }, string.split("one2two3three", "%d", false, -1, true))
end)
end)
end)
describe("privs", function()
it("from string", function()
assert.same({ a = true, b = true }, core.string_to_privs("a,b"))
end)
it("to string", function()
assert.equal("one", core.privs_to_string({ one=true }))
local ret = core.privs_to_string({ a=true, b=true })
assert(ret == "a,b" or ret == "b,a")
end)
end)
describe("pos", function()
it("from string", function()
assert.equal(vector.new(10, 5.1, -2), core.string_to_pos("10.0, 5.1, -2"))
assert.equal(vector.new(10, 5.1, -2), core.string_to_pos("( 10.0, 5.1, -2)"))
assert.is_nil(core.string_to_pos("asd, 5, -2)"))
end)
it("to string", function()
assert.equal("(10.1,5.2,-2.3)", core.pos_to_string({ x = 10.1, y = 5.2, z = -2.3}))
end)
end)
describe("area parsing", function()
describe("valid inputs", function()
it("accepts absolute numbers", function()
local p1, p2 = core.string_to_area("(10.0, 5, -2) ( 30.2 4 -12.53)")
assert(p1.x == 10 and p1.y == 5 and p1.z == -2)
assert(p2.x == 30.2 and p2.y == 4 and p2.z == -12.53)
end)
it("accepts relative numbers", function()
local p1, p2 = core.string_to_area("(1,2,3) (~5,~-5,~)", {x=10,y=10,z=10})
assert(type(p1) == "table" and type(p2) == "table")
assert(p1.x == 1 and p1.y == 2 and p1.z == 3)
assert(p2.x == 15 and p2.y == 5 and p2.z == 10)
p1, p2 = core.string_to_area("(1 2 3) (~5 ~-5 ~)", {x=10,y=10,z=10})
assert(type(p1) == "table" and type(p2) == "table")
assert(p1.x == 1 and p1.y == 2 and p1.z == 3)
assert(p2.x == 15 and p2.y == 5 and p2.z == 10)
end)
end)
describe("invalid inputs", function()
it("rejects too few numbers", function()
local p1, p2 = core.string_to_area("(1,1) (1,1,1,1)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
end)
it("rejects too many numbers", function()
local p1, p2 = core.string_to_area("(1,1,1,1) (1,1,1,1)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
end)
it("rejects nan & inf", function()
local p1, p2 = core.string_to_area("(1,1,1) (1,1,nan)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(1,1,1) (1,1,~nan)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(1,1,1) (1,~nan,1)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(1,1,1) (1,1,inf)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(1,1,1) (1,1,~inf)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(1,1,1) (1,~inf,1)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(nan,nan,nan) (nan,nan,nan)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(nan,nan,nan) (nan,nan,nan)")
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(inf,inf,inf) (-inf,-inf,-inf)", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(inf,inf,inf) (-inf,-inf,-inf)")
assert(p1 == nil and p2 == nil)
end)
it("rejects words", function()
local p1, p2 = core.string_to_area("bananas", {x=1,y=1,z=1})
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("bananas", "foobar")
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("bananas")
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(bananas,bananas,bananas)")
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(bananas,bananas,bananas) (bananas,bananas,bananas)")
assert(p1 == nil and p2 == nil)
end)
it("requires parenthesis & valid numbers", function()
local p1, p2 = core.string_to_area("(10.0, 5, -2 30.2, 4, -12.53")
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(10.0, 5,) -2 fgdf2, 4, -12.53")
assert(p1 == nil and p2 == nil)
end)
end)
end)
describe("table", function()
it("indexof()", function()
assert.equal(1, table.indexof({"foo", "bar"}, "foo"))
assert.equal(-1, table.indexof({"foo", "bar"}, "baz"))
end)
end)
describe("formspec_escape", function()
it("escapes", function()
assert.equal(nil, core.formspec_escape(nil))
assert.equal("", core.formspec_escape(""))
assert.equal("\\[Hello\\\\\\[", core.formspec_escape("[Hello\\["))
end)
end)

View File

@ -0,0 +1,189 @@
_G.core = {}
_G.vector = {metatable = {}}
_G.setfenv = require 'busted.compatibility'.setfenv
dofile("builtin/common/serialize.lua")
dofile("builtin/common/vector.lua")
-- Supports circular tables; does not support table keys
-- Correctly checks whether a mapping of references ("same") exists
-- Is significantly more efficient than assert.same
local function assert_same(a, b, same)
same = same or {}
if same[a] or same[b] then
assert(same[a] == b and same[b] == a)
return
end
if a == b then
return
end
if type(a) ~= "table" or type(b) ~= "table" then
assert(a == b)
return
end
same[a] = b
same[b] = a
local count = 0
for k, v in pairs(a) do
count = count + 1
assert(type(k) ~= "table")
assert_same(v, b[k], same)
end
for _ in pairs(b) do
count = count - 1
end
assert(count == 0)
end
local x, y = {}, {}
local t1, t2 = {x, x, y, y}, {x, y, x, y}
assert.same(t1, t2) -- will succeed because it only checks whether the depths match
assert(not pcall(assert_same, t1, t2)) -- will correctly fail because it checks whether the refs match
describe("serialize", function()
local function assert_preserves(value)
local preserved_value = core.deserialize(core.serialize(value))
assert_same(value, preserved_value)
end
it("works", function()
assert_preserves({cat={sound="nyan", speed=400}, dog={sound="woof"}})
end)
it("handles characters", function()
assert_preserves({escape_chars="\n\r\t\v\\\"\'", non_european="θשׁ٩∂"})
end)
it("handles NaN & infinities", function()
local nan = core.deserialize(core.serialize(0/0))
assert(nan ~= nan)
assert_preserves(math.huge)
assert_preserves(-math.huge)
end)
it("handles precise numbers", function()
assert_preserves(0.2695949158945771)
end)
it("handles big integers", function()
assert_preserves(269594915894577)
end)
it("handles recursive structures", function()
local test_in = { hello = "world" }
test_in.foo = test_in
assert_preserves(test_in)
end)
it("handles cross-referencing structures", function()
local test_in = {
foo = {
baz = {
{}
},
},
bar = {
baz = {},
},
}
test_in.foo.baz[1].foo = test_in.foo
test_in.foo.baz[1].bar = test_in.bar
test_in.bar.baz[1] = test_in.foo.baz[1]
assert_preserves(test_in)
end)
it("strips functions in safe mode", function()
local test_in = {
func = function(a, b)
error("test")
end,
foo = "bar"
}
setfenv(test_in.func, _G)
local str = core.serialize(test_in)
assert.not_nil(str:find("loadstring"))
local test_out = core.deserialize(str, true)
assert.is_nil(test_out.func)
assert.equals(test_out.foo, "bar")
end)
it("vectors work", function()
local v = vector.new(1, 2, 3)
assert_preserves({v})
assert_preserves(v)
-- abuse
v = vector.new(1, 2, 3)
v.a = "bla"
assert_preserves(v)
end)
it("handles keywords as keys", function()
assert_preserves({["and"] = "keyword", ["for"] = "keyword"})
end)
describe("fuzzing", function()
local atomics = {true, false, math.huge, -math.huge} -- no NaN or nil
local function atomic()
return atomics[math.random(1, #atomics)]
end
local function num()
local sign = math.random() < 0.5 and -1 or 1
-- HACK math.random(a, b) requires a, b & b - a to fit within a 32-bit int
-- Use two random calls to generate a random number from 0 - 2^50 as lower & upper 25 bits
local val = math.random(0, 2^25) * 2^25 + math.random(0, 2^25 - 1)
local exp = math.random() < 0.5 and 1 or 2^(math.random(-120, 120))
return sign * val * exp
end
local function charcodes(count)
if count == 0 then return end
return math.random(0, 0xFF), charcodes(count - 1)
end
local function str()
return string.char(charcodes(math.random(0, 100)))
end
local primitives = {atomic, num, str}
local function primitive()
return primitives[math.random(1, #primitives)]()
end
local function tab(max_actions)
local root = {}
local tables = {root}
local function random_table()
return tables[math.random(1, #tables)]
end
for _ = 1, math.random(1, max_actions) do
local tab = random_table()
local value
if math.random() < 0.5 then
if math.random() < 0.5 then
value = random_table()
else
value = {}
table.insert(tables, value)
end
else
value = primitive()
end
tab[math.random() < 0.5 and (#tab + 1) or primitive()] = value
end
return root
end
it("primitives work", function()
for _ = 1, 1e3 do
assert_preserves(primitive())
end
end)
it("tables work", function()
for _ = 1, 100 do
local fuzzed_table = tab(1e3)
assert_same(fuzzed_table, table.copy(fuzzed_table))
assert_preserves(fuzzed_table)
end
end)
end)
end)

View File

@ -0,0 +1,465 @@
_G.vector = {metatable = {}}
dofile("builtin/common/vector.lua")
describe("vector", function()
describe("new()", function()
it("constructs", function()
assert.same({x = 0, y = 0, z = 0}, vector.new())
assert.same({x = 1, y = 2, z = 3}, vector.new(1, 2, 3))
assert.same({x = 3, y = 2, z = 1}, vector.new({x = 3, y = 2, z = 1}))
assert.is_true(vector.check(vector.new()))
assert.is_true(vector.check(vector.new(1, 2, 3)))
assert.is_true(vector.check(vector.new({x = 3, y = 2, z = 1})))
local input = vector.new({ x = 3, y = 2, z = 1 })
local output = vector.new(input)
assert.same(input, output)
assert.equal(input, output)
assert.is_false(rawequal(input, output))
assert.equal(input, input:new())
end)
it("throws on invalid input", function()
assert.has.errors(function()
vector.new({ x = 3 })
end)
assert.has.errors(function()
vector.new({ d = 3 })
end)
end)
end)
it("zero()", function()
assert.same({x = 0, y = 0, z = 0}, vector.zero())
assert.same(vector.new(), vector.zero())
assert.equal(vector.new(), vector.zero())
assert.is_true(vector.check(vector.zero()))
end)
it("copy()", function()
local v = vector.new(1, 2, 3)
assert.same(v, vector.copy(v))
assert.same(vector.new(v), vector.copy(v))
assert.equal(vector.new(v), vector.copy(v))
assert.is_true(vector.check(vector.copy(v)))
end)
it("indexes", function()
local some_vector = vector.new(24, 42, 13)
assert.equal(24, some_vector[1])
assert.equal(24, some_vector.x)
assert.equal(42, some_vector[2])
assert.equal(42, some_vector.y)
assert.equal(13, some_vector[3])
assert.equal(13, some_vector.z)
some_vector[1] = 100
assert.equal(100, some_vector.x)
some_vector.x = 101
assert.equal(101, some_vector[1])
some_vector[2] = 100
assert.equal(100, some_vector.y)
some_vector.y = 102
assert.equal(102, some_vector[2])
some_vector[3] = 100
assert.equal(100, some_vector.z)
some_vector.z = 103
assert.equal(103, some_vector[3])
end)
it("direction()", function()
local a = vector.new(1, 0, 0)
local b = vector.new(1, 42, 0)
assert.equal(vector.new(0, 1, 0), vector.direction(a, b))
assert.equal(vector.new(0, 1, 0), a:direction(b))
end)
it("distance()", function()
local a = vector.new(1, 0, 0)
local b = vector.new(3, 42, 9)
assert.is_true(math.abs(43 - vector.distance(a, b)) < 1.0e-12)
assert.is_true(math.abs(43 - a:distance(b)) < 1.0e-12)
assert.equal(0, vector.distance(a, a))
assert.equal(0, b:distance(b))
end)
it("length()", function()
local a = vector.new(0, 0, -23)
assert.equal(0, vector.length(vector.new()))
assert.equal(23, vector.length(a))
assert.equal(23, a:length())
end)
it("normalize()", function()
local a = vector.new(0, 0, -23)
assert.equal(vector.new(0, 0, -1), vector.normalize(a))
assert.equal(vector.new(0, 0, -1), a:normalize())
assert.equal(vector.new(), vector.normalize(vector.new()))
end)
it("floor()", function()
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(0, 0, -1), vector.floor(a))
assert.equal(vector.new(0, 0, -1), a:floor())
end)
it("round()", function()
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(0, 1, -1), vector.round(a))
assert.equal(vector.new(0, 1, -1), a:round())
end)
it("apply()", function()
local i = 0
local f = function(x)
i = i + 1
return x + i
end
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(1, 1, 0), vector.apply(a, math.ceil))
assert.equal(vector.new(1, 1, 0), a:apply(math.ceil))
assert.equal(vector.new(0.1, 0.9, 0.5), vector.apply(a, math.abs))
assert.equal(vector.new(0.1, 0.9, 0.5), a:apply(math.abs))
assert.equal(vector.new(1.1, 2.9, 2.5), vector.apply(a, f))
assert.equal(vector.new(4.1, 5.9, 5.5), a:apply(f))
end)
it("combine()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(3, 2, 1)
assert.equal(vector.add(a, b), vector.combine(a, b, function(x, y) return x + y end))
assert.equal(vector.new(3, 2, 3), vector.combine(a, b, math.max))
assert.equal(vector.new(1, 2, 1), vector.combine(a, b, math.min))
end)
it("equals()", function()
local function assertE(a, b)
assert.is_true(vector.equals(a, b))
end
local function assertNE(a, b)
assert.is_false(vector.equals(a, b))
end
assertE({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
assertE({x = -1, y = 0, z = 1}, {x = -1, y = 0, z = 1})
assertE({x = -1, y = 0, z = 1}, vector.new(-1, 0, 1))
local a = {x = 2, y = 4, z = -10}
assertE(a, a)
assertNE({x = -1, y = 0, z = 1}, a)
assert.equal(vector.new(1, 2, 3), vector.new(1, 2, 3))
assert.is_true(vector.new(1, 2, 3):equals(vector.new(1, 2, 3)))
assert.not_equal(vector.new(1, 2, 3), vector.new(1, 2, 4))
assert.is_true(vector.new(1, 2, 3) == vector.new(1, 2, 3))
assert.is_false(vector.new(1, 2, 3) == vector.new(1, 3, 3))
end)
it("metatable is same", function()
local a = vector.new()
local b = vector.new(1, 2, 3)
assert.equal(true, vector.check(a))
assert.equal(true, vector.check(b))
assert.equal(vector.metatable, getmetatable(a))
assert.equal(vector.metatable, getmetatable(b))
assert.equal(vector.metatable, a.metatable)
end)
it("sort()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(0.5, 232, -2)
local sorted = {vector.new(0.5, 2, -2), vector.new(1, 232, 3)}
assert.same(sorted, {vector.sort(a, b)})
assert.same(sorted, {a:sort(b)})
end)
it("angle()", function()
assert.equal(math.pi, vector.angle(vector.new(-1, -2, -3), vector.new(1, 2, 3)))
assert.equal(math.pi/2, vector.new(0, 1, 0):angle(vector.new(1, 0, 0)))
end)
it("dot()", function()
assert.equal(-14, vector.dot(vector.new(-1, -2, -3), vector.new(1, 2, 3)))
assert.equal(0, vector.new():dot(vector.new(1, 2, 3)))
end)
it("cross()", function()
local a = vector.new(-1, -2, 0)
local b = vector.new(1, 2, 3)
assert.equal(vector.new(-6, 3, 0), vector.cross(a, b))
assert.equal(vector.new(-6, 3, 0), a:cross(b))
end)
it("offset()", function()
assert.same({x = 41, y = 52, z = 63}, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
assert.equal(vector.new(41, 52, 63), vector.offset(vector.new(1, 2, 3), 40, 50, 60))
assert.equal(vector.new(41, 52, 63), vector.new(1, 2, 3):offset(40, 50, 60))
end)
it("is()", function()
local some_table1 = {foo = 13, [42] = 1, "bar", 2}
local some_table2 = {1, 2, 3}
local some_table3 = {x = 1, 2, 3}
local some_table4 = {1, 2, z = 3}
local old = {x = 1, y = 2, z = 3}
local real = vector.new(1, 2, 3)
assert.is_false(vector.check(nil))
assert.is_false(vector.check(1))
assert.is_false(vector.check(true))
assert.is_false(vector.check("foo"))
assert.is_false(vector.check(some_table1))
assert.is_false(vector.check(some_table2))
assert.is_false(vector.check(some_table3))
assert.is_false(vector.check(some_table4))
assert.is_false(vector.check(old))
assert.is_true(vector.check(real))
assert.is_true(real:check())
end)
it("global pairs", function()
local out = {}
local vec = vector.new(10, 20, 30)
for k, v in pairs(vec) do
out[k] = v
end
assert.same({x = 10, y = 20, z = 30}, out)
end)
it("abusing works", function()
local v = vector.new(1, 2, 3)
v.a = 1
assert.equal(1, v.a)
local a_is_there = false
for key, value in pairs(v) do
if key == "a" then
a_is_there = true
assert.equal(value, 1)
break
end
end
assert.is_true(a_is_there)
end)
it("add()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(1, 4, 3)
local c = vector.new(2, 6, 6)
assert.equal(c, vector.add(a, {x = 1, y = 4, z = 3}))
assert.equal(c, vector.add(a, b))
assert.equal(c, a:add(b))
assert.equal(c, a + b)
assert.equal(c, b + a)
end)
it("subtract()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(2, 4, 3)
local c = vector.new(-1, -2, 0)
assert.equal(c, vector.subtract(a, {x = 2, y = 4, z = 3}))
assert.equal(c, vector.subtract(a, b))
assert.equal(c, a:subtract(b))
assert.equal(c, a - b)
assert.equal(c, -b + a)
end)
it("multiply()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(2, 4, 3)
local c = vector.new(2, 8, 9)
local s = 2
local d = vector.new(2, 4, 6)
assert.equal(c, vector.multiply(a, {x = 2, y = 4, z = 3}))
assert.equal(c, vector.multiply(a, b))
assert.equal(d, vector.multiply(a, s))
assert.equal(d, a:multiply(s))
assert.equal(d, a * s)
assert.equal(d, s * a)
assert.equal(-a, -1 * a)
end)
it("divide()", function()
local a = vector.new(1, 2, 3)
local b = vector.new(2, 4, 3)
local c = vector.new(0.5, 0.5, 1)
local s = 2
local d = vector.new(0.5, 1, 1.5)
assert.equal(c, vector.divide(a, {x = 2, y = 4, z = 3}))
assert.equal(c, vector.divide(a, b))
assert.equal(d, vector.divide(a, s))
assert.equal(d, a:divide(s))
assert.equal(d, a / s)
assert.equal(d, 1/s * a)
assert.equal(-a, a / -1)
end)
it("to_string()", function()
local v = vector.new(1, 2, 3.14)
assert.same("(1, 2, 3.14)", vector.to_string(v))
assert.same("(1, 2, 3.14)", v:to_string())
assert.same("(1, 2, 3.14)", tostring(v))
end)
it("from_string()", function()
local v = vector.new(1, 2, 3.14)
assert.is_true(vector.check(vector.from_string("(1, 2, 3.14)")))
assert.same({v, 13}, {vector.from_string("(1, 2, 3.14)")})
assert.same({v, 12}, {vector.from_string("(1,2 ,3.14)")})
assert.same({v, 12}, {vector.from_string("(1,2,3.14,)")})
assert.same({v, 11}, {vector.from_string("(1 2 3.14)")})
assert.same({v, 15}, {vector.from_string("( 1, 2, 3.14 )")})
assert.same({v, 15}, {vector.from_string(" ( 1, 2, 3.14) ")})
assert.same({vector.new(), 8}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ")})
assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 8)})
assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 9)})
assert.same(nil, vector.from_string("nothing"))
end)
-- This function is needed because of floating point imprecision.
local function almost_equal(a, b)
if type(a) == "number" then
return math.abs(a - b) < 0.00000000001
end
return vector.distance(a, b) < 0.000000000001
end
describe("rotate_around_axis()", function()
it("rotates", function()
assert.True(almost_equal({x = -1, y = 0, z = 0},
vector.rotate_around_axis({x = 1, y = 0, z = 0}, {x = 0, y = 1, z = 0}, math.pi)))
assert.True(almost_equal({x = 0, y = 1, z = 0},
vector.rotate_around_axis({x = 0, y = 0, z = 1}, {x = 1, y = 0, z = 0}, math.pi / 2)))
assert.True(almost_equal({x = 4, y = 1, z = 1},
vector.rotate_around_axis({x = 4, y = 1, z = 1}, {x = 4, y = 1, z = 1}, math.pi / 6)))
end)
it("keeps distance to axis", function()
local rotate1 = {x = 1, y = 3, z = 1}
local axis1 = {x = 1, y = 3, z = 2}
local rotated1 = vector.rotate_around_axis(rotate1, axis1, math.pi / 13)
assert.True(almost_equal(vector.distance(axis1, rotate1), vector.distance(axis1, rotated1)))
local rotate2 = {x = 1, y = 1, z = 3}
local axis2 = {x = 2, y = 6, z = 100}
local rotated2 = vector.rotate_around_axis(rotate2, axis2, math.pi / 23)
assert.True(almost_equal(vector.distance(axis2, rotate2), vector.distance(axis2, rotated2)))
local rotate3 = {x = 1, y = -1, z = 3}
local axis3 = {x = 2, y = 6, z = 100}
local rotated3 = vector.rotate_around_axis(rotate3, axis3, math.pi / 2)
assert.True(almost_equal(vector.distance(axis3, rotate3), vector.distance(axis3, rotated3)))
end)
it("rotates back", function()
local rotate1 = {x = 1, y = 3, z = 1}
local axis1 = {x = 1, y = 3, z = 2}
local rotated1 = vector.rotate_around_axis(rotate1, axis1, math.pi / 13)
rotated1 = vector.rotate_around_axis(rotated1, axis1, -math.pi / 13)
assert.True(almost_equal(rotate1, rotated1))
local rotate2 = {x = 1, y = 1, z = 3}
local axis2 = {x = 2, y = 6, z = 100}
local rotated2 = vector.rotate_around_axis(rotate2, axis2, math.pi / 23)
rotated2 = vector.rotate_around_axis(rotated2, axis2, -math.pi / 23)
assert.True(almost_equal(rotate2, rotated2))
local rotate3 = {x = 1, y = -1, z = 3}
local axis3 = {x = 2, y = 6, z = 100}
local rotated3 = vector.rotate_around_axis(rotate3, axis3, math.pi / 2)
rotated3 = vector.rotate_around_axis(rotated3, axis3, -math.pi / 2)
assert.True(almost_equal(rotate3, rotated3))
end)
it("is right handed", function()
local v_before1 = {x = 0, y = 1, z = -1}
local v_after1 = vector.rotate_around_axis(v_before1, {x = 1, y = 0, z = 0}, math.pi / 4)
assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0}))
local v_before2 = {x = 0, y = 3, z = 4}
local v_after2 = vector.rotate_around_axis(v_before2, {x = 1, y = 0, z = 0}, 2 * math.pi / 5)
assert.True(almost_equal(vector.normalize(vector.cross(v_after2, v_before2)), {x = 1, y = 0, z = 0}))
local v_before3 = {x = 1, y = 0, z = -1}
local v_after3 = vector.rotate_around_axis(v_before3, {x = 0, y = 1, z = 0}, math.pi / 4)
assert.True(almost_equal(vector.normalize(vector.cross(v_after3, v_before3)), {x = 0, y = 1, z = 0}))
local v_before4 = {x = 3, y = 0, z = 4}
local v_after4 = vector.rotate_around_axis(v_before4, {x = 0, y = 1, z = 0}, 2 * math.pi / 5)
assert.True(almost_equal(vector.normalize(vector.cross(v_after4, v_before4)), {x = 0, y = 1, z = 0}))
local v_before5 = {x = 1, y = -1, z = 0}
local v_after5 = vector.rotate_around_axis(v_before5, {x = 0, y = 0, z = 1}, math.pi / 4)
assert.True(almost_equal(vector.normalize(vector.cross(v_after5, v_before5)), {x = 0, y = 0, z = 1}))
local v_before6 = {x = 3, y = 4, z = 0}
local v_after6 = vector.rotate_around_axis(v_before6, {x = 0, y = 0, z = 1}, 2 * math.pi / 5)
assert.True(almost_equal(vector.normalize(vector.cross(v_after6, v_before6)), {x = 0, y = 0, z = 1}))
end)
end)
describe("rotate()", function()
it("rotates", function()
assert.True(almost_equal({x = -1, y = 0, z = 0},
vector.rotate({x = 1, y = 0, z = 0}, {x = 0, y = math.pi, z = 0})))
assert.True(almost_equal({x = 0, y = -1, z = 0},
vector.rotate({x = 1, y = 0, z = 0}, {x = 0, y = 0, z = math.pi / 2})))
assert.True(almost_equal({x = 1, y = 0, z = 0},
vector.rotate({x = 1, y = 0, z = 0}, {x = math.pi / 123, y = 0, z = 0})))
end)
it("is counterclockwise", function()
local v_before1 = {x = 0, y = 1, z = -1}
local v_after1 = vector.rotate(v_before1, {x = math.pi / 4, y = 0, z = 0})
assert.True(almost_equal(vector.normalize(vector.cross(v_after1, v_before1)), {x = 1, y = 0, z = 0}))
local v_before2 = {x = 0, y = 3, z = 4}
local v_after2 = vector.rotate(v_before2, {x = 2 * math.pi / 5, y = 0, z = 0})
assert.True(almost_equal(vector.normalize(vector.cross(v_after2, v_before2)), {x = 1, y = 0, z = 0}))
local v_before3 = {x = 1, y = 0, z = -1}
local v_after3 = vector.rotate(v_before3, {x = 0, y = math.pi / 4, z = 0})
assert.True(almost_equal(vector.normalize(vector.cross(v_after3, v_before3)), {x = 0, y = 1, z = 0}))
local v_before4 = {x = 3, y = 0, z = 4}
local v_after4 = vector.rotate(v_before4, {x = 0, y = 2 * math.pi / 5, z = 0})
assert.True(almost_equal(vector.normalize(vector.cross(v_after4, v_before4)), {x = 0, y = 1, z = 0}))
local v_before5 = {x = 1, y = -1, z = 0}
local v_after5 = vector.rotate(v_before5, {x = 0, y = 0, z = math.pi / 4})
assert.True(almost_equal(vector.normalize(vector.cross(v_after5, v_before5)), {x = 0, y = 0, z = 1}))
local v_before6 = {x = 3, y = 4, z = 0}
local v_after6 = vector.rotate(v_before6, {x = 0, y = 0, z = 2 * math.pi / 5})
assert.True(almost_equal(vector.normalize(vector.cross(v_after6, v_before6)), {x = 0, y = 0, z = 1}))
end)
end)
it("dir_to_rotation()", function()
-- Comparing rotations (pitch, yaw, roll) is hard because of certain ambiguities,
-- e.g. (pi, 0, pi) looks exactly the same as (0, pi, 0)
-- So instead we convert the rotation back to vectors and compare these.
local function forward_at_rot(rot)
return vector.rotate(vector.new(0, 0, 1), rot)
end
local function up_at_rot(rot)
return vector.rotate(vector.new(0, 1, 0), rot)
end
local rot1 = vector.dir_to_rotation({x = 1, y = 0, z = 0}, {x = 0, y = 1, z = 0})
assert.True(almost_equal({x = 1, y = 0, z = 0}, forward_at_rot(rot1)))
assert.True(almost_equal({x = 0, y = 1, z = 0}, up_at_rot(rot1)))
local rot2 = vector.dir_to_rotation({x = 1, y = 1, z = 0}, {x = 0, y = 0, z = 1})
assert.True(almost_equal({x = 1/math.sqrt(2), y = 1/math.sqrt(2), z = 0}, forward_at_rot(rot2)))
assert.True(almost_equal({x = 0, y = 0, z = 1}, up_at_rot(rot2)))
for i = 1, 1000 do
local rand_vec = vector.new(math.random(), math.random(), math.random())
if vector.length(rand_vec) ~= 0 then
local rot_1 = vector.dir_to_rotation(rand_vec)
local rot_2 = {
x = math.atan2(rand_vec.y, math.sqrt(rand_vec.z * rand_vec.z + rand_vec.x * rand_vec.x)),
y = -math.atan2(rand_vec.x, rand_vec.z),
z = 0
}
assert.True(almost_equal(rot_1, rot_2))
end
end
end)
end)

368
builtin/common/vector.lua Normal file
View File

@ -0,0 +1,368 @@
--[[
Vector helpers
Note: The vector.*-functions must be able to accept old vectors that had no metatables
]]
-- localize functions
local setmetatable = setmetatable
-- vector.metatable is set by C++.
local metatable = vector.metatable
local xyz = {"x", "y", "z"}
-- only called when rawget(v, key) returns nil
function metatable.__index(v, key)
return rawget(v, xyz[key]) or vector[key]
end
-- only called when rawget(v, key) returns nil
function metatable.__newindex(v, key, value)
rawset(v, xyz[key] or key, value)
end
-- constructors
local function fast_new(x, y, z)
return setmetatable({x = x, y = y, z = z}, metatable)
end
function vector.new(a, b, c)
if a and b and c then
return fast_new(a, b, c)
end
-- deprecated, use vector.copy and vector.zero directly
if type(a) == "table" then
return vector.copy(a)
else
assert(not a, "Invalid arguments for vector.new()")
return vector.zero()
end
end
function vector.zero()
return fast_new(0, 0, 0)
end
function vector.copy(v)
assert(v.x and v.y and v.z, "Invalid vector passed to vector.copy()")
return fast_new(v.x, v.y, v.z)
end
function vector.from_string(s, init)
local x, y, z, np = string.match(s, "^%s*%(%s*([^%s,]+)%s*[,%s]%s*([^%s,]+)%s*[,%s]" ..
"%s*([^%s,]+)%s*[,%s]?%s*%)()", init)
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
if not (x and y and z) then
return nil
end
return fast_new(x, y, z), np
end
function vector.to_string(v)
return string.format("(%g, %g, %g)", v.x, v.y, v.z)
end
metatable.__tostring = vector.to_string
function vector.equals(a, b)
return a.x == b.x and
a.y == b.y and
a.z == b.z
end
metatable.__eq = vector.equals
-- unary operations
function vector.length(v)
return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
end
-- Note: we can not use __len because it is already used for primitive table length
function vector.normalize(v)
local len = vector.length(v)
if len == 0 then
return fast_new(0, 0, 0)
else
return vector.divide(v, len)
end
end
function vector.floor(v)
return vector.apply(v, math.floor)
end
function vector.round(v)
return fast_new(
math.round(v.x),
math.round(v.y),
math.round(v.z)
)
end
function vector.apply(v, func)
return fast_new(
func(v.x),
func(v.y),
func(v.z)
)
end
function vector.combine(a, b, func)
return fast_new(
func(a.x, b.x),
func(a.y, b.y),
func(a.z, b.z)
)
end
function vector.distance(a, b)
local x = a.x - b.x
local y = a.y - b.y
local z = a.z - b.z
return math.sqrt(x * x + y * y + z * z)
end
function vector.direction(pos1, pos2)
return vector.subtract(pos2, pos1):normalize()
end
function vector.angle(a, b)
local dotp = vector.dot(a, b)
local cp = vector.cross(a, b)
local crossplen = vector.length(cp)
return math.atan2(crossplen, dotp)
end
function vector.dot(a, b)
return a.x * b.x + a.y * b.y + a.z * b.z
end
function vector.cross(a, b)
return fast_new(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x
)
end
function metatable.__unm(v)
return fast_new(-v.x, -v.y, -v.z)
end
-- add, sub, mul, div operations
function vector.add(a, b)
if type(b) == "table" then
return fast_new(
a.x + b.x,
a.y + b.y,
a.z + b.z
)
else
return fast_new(
a.x + b,
a.y + b,
a.z + b
)
end
end
function metatable.__add(a, b)
return fast_new(
a.x + b.x,
a.y + b.y,
a.z + b.z
)
end
function vector.subtract(a, b)
if type(b) == "table" then
return fast_new(
a.x - b.x,
a.y - b.y,
a.z - b.z
)
else
return fast_new(
a.x - b,
a.y - b,
a.z - b
)
end
end
function metatable.__sub(a, b)
return fast_new(
a.x - b.x,
a.y - b.y,
a.z - b.z
)
end
function vector.multiply(a, b)
if type(b) == "table" then
return fast_new(
a.x * b.x,
a.y * b.y,
a.z * b.z
)
else
return fast_new(
a.x * b,
a.y * b,
a.z * b
)
end
end
function metatable.__mul(a, b)
if type(a) == "table" then
return fast_new(
a.x * b,
a.y * b,
a.z * b
)
else
return fast_new(
a * b.x,
a * b.y,
a * b.z
)
end
end
function vector.divide(a, b)
if type(b) == "table" then
return fast_new(
a.x / b.x,
a.y / b.y,
a.z / b.z
)
else
return fast_new(
a.x / b,
a.y / b,
a.z / b
)
end
end
function metatable.__div(a, b)
-- scalar/vector makes no sense
return fast_new(
a.x / b,
a.y / b,
a.z / b
)
end
-- misc stuff
function vector.offset(v, x, y, z)
return fast_new(
v.x + x,
v.y + y,
v.z + z
)
end
function vector.sort(a, b)
return fast_new(math.min(a.x, b.x), math.min(a.y, b.y), math.min(a.z, b.z)),
fast_new(math.max(a.x, b.x), math.max(a.y, b.y), math.max(a.z, b.z))
end
function vector.check(v)
return getmetatable(v) == metatable
end
local function sin(x)
if x % math.pi == 0 then
return 0
else
return math.sin(x)
end
end
local function cos(x)
if x % math.pi == math.pi / 2 then
return 0
else
return math.cos(x)
end
end
function vector.rotate_around_axis(v, axis, angle)
local cosangle = cos(angle)
local sinangle = sin(angle)
axis = vector.normalize(axis)
-- https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
local dot_axis = vector.multiply(axis, vector.dot(axis, v))
local cross = vector.cross(v, axis)
return vector.new(
cross.x * sinangle + (v.x - dot_axis.x) * cosangle + dot_axis.x,
cross.y * sinangle + (v.y - dot_axis.y) * cosangle + dot_axis.y,
cross.z * sinangle + (v.z - dot_axis.z) * cosangle + dot_axis.z
)
end
function vector.rotate(v, rot)
local sinpitch = sin(-rot.x)
local sinyaw = sin(-rot.y)
local sinroll = sin(-rot.z)
local cospitch = cos(rot.x)
local cosyaw = cos(rot.y)
local cosroll = math.cos(rot.z)
-- Rotation matrix that applies yaw, pitch and roll
local matrix = {
{
sinyaw * sinpitch * sinroll + cosyaw * cosroll,
sinyaw * sinpitch * cosroll - cosyaw * sinroll,
sinyaw * cospitch,
},
{
cospitch * sinroll,
cospitch * cosroll,
-sinpitch,
},
{
cosyaw * sinpitch * sinroll - sinyaw * cosroll,
cosyaw * sinpitch * cosroll + sinyaw * sinroll,
cosyaw * cospitch,
},
}
-- Compute matrix multiplication: `matrix` * `v`
return vector.new(
matrix[1][1] * v.x + matrix[1][2] * v.y + matrix[1][3] * v.z,
matrix[2][1] * v.x + matrix[2][2] * v.y + matrix[2][3] * v.z,
matrix[3][1] * v.x + matrix[3][2] * v.y + matrix[3][3] * v.z
)
end
function vector.dir_to_rotation(forward, up)
forward = vector.normalize(forward)
local rot = vector.new(math.asin(forward.y), -math.atan2(forward.x, forward.z), 0)
if not up then
return rot
end
assert(vector.dot(forward, up) < 0.000001,
"Invalid vectors passed to vector.dir_to_rotation().")
up = vector.normalize(up)
-- Calculate vector pointing up with roll = 0, just based on forward vector.
local forwup = vector.rotate(vector.new(0, 1, 0), rot)
-- 'forwup' and 'up' are now in a plane with 'forward' as normal.
-- The angle between them is the absolute of the roll value we're looking for.
rot.z = vector.angle(forwup, up)
-- Since vector.angle never returns a negative value or a value greater
-- than math.pi, rot.z has to be inverted sometimes.
-- To determine wether this is the case, we rotate the up vector back around
-- the forward vector and check if it worked out.
local back = vector.rotate_around_axis(up, forward, -rot.z)
-- We don't use vector.equals for this because of floating point imprecision.
if (back.x - forwup.x) * (back.x - forwup.x) +
(back.y - forwup.y) * (back.y - forwup.y) +
(back.z - forwup.z) * (back.z - forwup.z) > 0.0000001 then
rot.z = -rot.z
end
return rot
end

215
builtin/fstk/buttonbar.lua Normal file
View File

@ -0,0 +1,215 @@
--Minetest
--Copyright (C) 2014 sapier
--
--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.
local function buttonbar_formspec(self)
if self.hidden then
return ""
end
local formspec = string.format("box[%f,%f;%f,%f;%s]",
self.pos.x,self.pos.y ,self.size.x,self.size.y,self.bgcolor)
for i=self.startbutton,#self.buttons,1 do
local btn_name = self.buttons[i].name
local btn_pos = {}
if self.orientation == "horizontal" then
btn_pos.x = self.pos.x + --base pos
(i - self.startbutton) * self.btn_size + --button offset
self.btn_initial_offset
else
btn_pos.x = self.pos.x + (self.btn_size * 0.05)
end
if self.orientation == "vertical" then
btn_pos.y = self.pos.y + --base pos
(i - self.startbutton) * self.btn_size + --button offset
self.btn_initial_offset
else
btn_pos.y = self.pos.y + (self.btn_size * 0.05)
end
if (self.orientation == "vertical" and
(btn_pos.y + self.btn_size <= self.pos.y + self.size.y)) or
(self.orientation == "horizontal" and
(btn_pos.x + self.btn_size <= self.pos.x + self.size.x)) then
local borders="true"
if self.buttons[i].image ~= nil then
borders="false"
end
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;%s]tooltip[%s;%s]",
btn_pos.x, btn_pos.y, self.btn_size, self.btn_size,
self.buttons[i].image, btn_name, self.buttons[i].caption,
borders, btn_name, self.buttons[i].tooltip)
else
--print("end of displayable buttons: orientation: " .. self.orientation)
--print( "button_end: " .. (btn_pos.y + self.btn_size - (self.btn_size * 0.05)))
--print( "bar_end: " .. (self.pos.x + self.size.x))
break
end
end
if (self.have_move_buttons) then
local btn_dec_pos = {}
btn_dec_pos.x = self.pos.x + (self.btn_size * 0.05)
btn_dec_pos.y = self.pos.y + (self.btn_size * 0.05)
local btn_inc_pos = {}
local btn_size = {}
if self.orientation == "horizontal" then
btn_size.x = 0.5
btn_size.y = self.btn_size
btn_inc_pos.x = self.pos.x + self.size.x - 0.5
btn_inc_pos.y = self.pos.y + (self.btn_size * 0.05)
else
btn_size.x = self.btn_size
btn_size.y = 0.5
btn_inc_pos.x = self.pos.x + (self.btn_size * 0.05)
btn_inc_pos.y = self.pos.y + self.size.y - 0.5
end
local text_dec = "<"
local text_inc = ">"
if self.orientation == "vertical" then
text_dec = "^"
text_inc = "v"
end
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;;btnbar_dec_%s;%s;true;true]",
btn_dec_pos.x, btn_dec_pos.y, btn_size.x, btn_size.y,
self.name, text_dec)
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;;btnbar_inc_%s;%s;true;true]",
btn_inc_pos.x, btn_inc_pos.y, btn_size.x, btn_size.y,
self.name, text_inc)
end
return formspec
end
local function buttonbar_buttonhandler(self, fields)
if fields["btnbar_inc_" .. self.name] ~= nil and
self.startbutton < #self.buttons then
self.startbutton = self.startbutton + 1
return true
end
if fields["btnbar_dec_" .. self.name] ~= nil and self.startbutton > 1 then
self.startbutton = self.startbutton - 1
return true
end
for i=1,#self.buttons,1 do
if fields[self.buttons[i].name] ~= nil then
return self.userbuttonhandler(fields)
end
end
end
local buttonbar_metatable = {
handle_buttons = buttonbar_buttonhandler,
handle_events = function(self, event) end,
get_formspec = buttonbar_formspec,
hide = function(self) self.hidden = true end,
show = function(self) self.hidden = false end,
delete = function(self) ui.delete(self) end,
add_button = function(self, name, caption, image, tooltip)
if caption == nil then caption = "" end
if image == nil then image = "" end
if tooltip == nil then tooltip = "" end
self.buttons[#self.buttons + 1] = {
name = name,
caption = caption,
image = image,
tooltip = tooltip
}
if self.orientation == "horizontal" then
if ( (self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.x ) then
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
self.have_move_buttons = true
end
else
if ((self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.y ) then
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
self.have_move_buttons = true
end
end
end,
set_bgparams = function(self, bgcolor)
if (type(bgcolor) == "string") then
self.bgcolor = bgcolor
end
end,
}
buttonbar_metatable.__index = buttonbar_metatable
function buttonbar_create(name, cbf_buttonhandler, pos, orientation, size)
assert(name ~= nil)
assert(cbf_buttonhandler ~= nil)
assert(orientation == "vertical" or orientation == "horizontal")
assert(pos ~= nil and type(pos) == "table")
assert(size ~= nil and type(size) == "table")
local self = {}
self.name = name
self.type = "addon"
self.bgcolor = "#000000"
self.pos = pos
self.size = size
self.orientation = orientation
self.startbutton = 1
self.have_move_buttons = false
self.hidden = false
if self.orientation == "horizontal" then
self.btn_size = self.size.y
else
self.btn_size = self.size.x
end
if (self.btn_initial_offset == nil) then
self.btn_initial_offset = self.btn_size * 0.05
end
self.userbuttonhandler = cbf_buttonhandler
self.buttons = {}
setmetatable(self,buttonbar_metatable)
ui.add(self)
return self
end

88
builtin/fstk/dialog.lua Normal file
View File

@ -0,0 +1,88 @@
--Minetest
--Copyright (C) 2014 sapier
--
--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.
local function dialog_event_handler(self,event)
if self.user_eventhandler == nil or
self.user_eventhandler(event) == false then
--close dialog on esc
if event == "MenuQuit" then
self:delete()
return true
end
end
end
local dialog_metatable = {
eventhandler = dialog_event_handler,
get_formspec = function(self)
if not self.hidden then return self.formspec(self.data) end
end,
handle_buttons = function(self,fields)
if not self.hidden then return self.buttonhandler(self,fields) end
end,
handle_events = function(self,event)
if not self.hidden then return self.eventhandler(self,event) end
end,
hide = function(self) self.hidden = true end,
show = function(self) self.hidden = false end,
delete = function(self)
if self.parent ~= nil then
self.parent:show()
end
ui.delete(self)
end,
set_parent = function(self,parent) self.parent = parent end
}
dialog_metatable.__index = dialog_metatable
function dialog_create(name,get_formspec,buttonhandler,eventhandler)
local self = {}
self.name = name
self.type = "toplevel"
self.hidden = true
self.data = {}
self.formspec = get_formspec
self.buttonhandler = buttonhandler
self.user_eventhandler = eventhandler
setmetatable(self,dialog_metatable)
ui.add(self)
return self
end
function messagebox(name, message)
return dialog_create(name,
function()
return ([[
formspec_version[3]
size[8,3]
textarea[0.375,0.375;7.25,1.2;;;%s]
button[3,1.825;2,0.8;ok;%s]
]]):format(message, fgettext("OK"))
end,
function(this, fields)
if fields.ok then
this:delete()
return true
end
end,
nil)
end

257
builtin/fstk/tabview.lua Normal file
View File

@ -0,0 +1,257 @@
--Minetest
--Copyright (C) 2014 sapier
--
--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.
--------------------------------------------------------------------------------
-- A tabview implementation --
-- Usage: --
-- tabview.create: returns initialized tabview raw element --
-- element.add(tab): add a tab declaration --
-- element.handle_buttons() --
-- element.handle_events() --
-- element.getFormspec() returns formspec of tabview --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function add_tab(self,tab)
assert(tab.size == nil or (type(tab.size) == table and
tab.size.x ~= nil and tab.size.y ~= nil))
assert(tab.cbf_formspec ~= nil and type(tab.cbf_formspec) == "function")
assert(tab.cbf_button_handler == nil or
type(tab.cbf_button_handler) == "function")
assert(tab.cbf_events == nil or type(tab.cbf_events) == "function")
local newtab = {
name = tab.name,
caption = tab.caption,
button_handler = tab.cbf_button_handler,
event_handler = tab.cbf_events,
get_formspec = tab.cbf_formspec,
tabsize = tab.tabsize,
on_change = tab.on_change,
tabdata = {},
}
self.tablist[#self.tablist + 1] = newtab
if self.last_tab_index == #self.tablist then
self.current_tab = tab.name
if tab.on_activate ~= nil then
tab.on_activate(nil,tab.name)
end
end
end
--------------------------------------------------------------------------------
local function get_formspec(self)
if self.hidden or (self.parent ~= nil and self.parent.hidden) then
return ""
end
local tab = self.tablist[self.last_tab_index]
local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize)
if self.parent == nil and not prepend then
local tsize = tab.tabsize or {width=self.width, height=self.height}
prepend = string.format("size[%f,%f,%s]", tsize.width, tsize.height,
dump(self.fixed_size))
end
local formspec = (prepend or "") .. self:tab_header() .. content
return formspec
end
--------------------------------------------------------------------------------
local function handle_buttons(self,fields)
if self.hidden then
return false
end
if self:handle_tab_buttons(fields) then
return true
end
if self.glb_btn_handler ~= nil and
self.glb_btn_handler(self,fields) then
return true
end
local tab = self.tablist[self.last_tab_index]
if tab.button_handler ~= nil then
return tab.button_handler(self, fields, tab.name, tab.tabdata)
end
return false
end
--------------------------------------------------------------------------------
local function handle_events(self,event)
if self.hidden then
return false
end
if self.glb_evt_handler ~= nil and
self.glb_evt_handler(self,event) then
return true
end
local tab = self.tablist[self.last_tab_index]
if tab.evt_handler ~= nil then
return tab.evt_handler(self, event, tab.name, tab.tabdata)
end
return false
end
--------------------------------------------------------------------------------
local function tab_header(self)
local toadd = ""
for i=1,#self.tablist,1 do
if toadd ~= "" then
toadd = toadd .. ","
end
toadd = toadd .. self.tablist[i].caption
end
return string.format("tabheader[%f,%f;%s;%s;%i;true;false]",
self.header_x, self.header_y, self.name, toadd, self.last_tab_index);
end
--------------------------------------------------------------------------------
local function switch_to_tab(self, index)
--first call on_change for tab to leave
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("LEAVE",
self.current_tab, self.tablist[index].name)
end
--update tabview data
self.last_tab_index = index
local old_tab = self.current_tab
self.current_tab = self.tablist[index].name
if (self.autosave_tab) then
core.settings:set(self.name .. "_LAST",self.current_tab)
end
-- call for tab to enter
if self.tablist[index].on_change ~= nil then
self.tablist[index].on_change("ENTER",
old_tab,self.current_tab)
end
end
--------------------------------------------------------------------------------
local function handle_tab_buttons(self,fields)
--save tab selection to config file
if fields[self.name] then
local index = tonumber(fields[self.name])
switch_to_tab(self, index)
return true
end
return false
end
--------------------------------------------------------------------------------
local function set_tab_by_name(self, name)
for i=1,#self.tablist,1 do
if self.tablist[i].name == name then
switch_to_tab(self, i)
return true
end
end
return false
end
--------------------------------------------------------------------------------
local function hide_tabview(self)
self.hidden=true
--call on_change as we're not gonna show self tab any longer
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("LEAVE",
self.current_tab, nil)
end
end
--------------------------------------------------------------------------------
local function show_tabview(self)
self.hidden=false
-- call for tab to enter
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("ENTER",
nil,self.current_tab)
end
end
local tabview_metatable = {
add = add_tab,
handle_buttons = handle_buttons,
handle_events = handle_events,
get_formspec = get_formspec,
show = show_tabview,
hide = hide_tabview,
delete = function(self) ui.delete(self) end,
set_parent = function(self,parent) self.parent = parent end,
set_autosave_tab =
function(self,value) self.autosave_tab = value end,
set_tab = set_tab_by_name,
set_global_button_handler =
function(self,handler) self.glb_btn_handler = handler end,
set_global_event_handler =
function(self,handler) self.glb_evt_handler = handler end,
set_fixed_size =
function(self,state) self.fixed_size = state end,
tab_header = tab_header,
handle_tab_buttons = handle_tab_buttons
}
tabview_metatable.__index = tabview_metatable
--------------------------------------------------------------------------------
function tabview_create(name, size, tabheaderpos)
local self = {}
self.name = name
self.type = "toplevel"
self.width = size.x
self.height = size.y
self.header_x = tabheaderpos.x
self.header_y = tabheaderpos.y
setmetatable(self, tabview_metatable)
self.fixed_size = true
self.hidden = true
self.current_tab = nil
self.last_tab_index = 1
self.tablist = {}
self.autosave_tab = false
ui.add(self)
return self
end

212
builtin/fstk/ui.lua Normal file
View File

@ -0,0 +1,212 @@
--Minetest
--Copyright (C) 2014 sapier
--
--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.
ui = {}
ui.childlist = {}
ui.default = nil
-- Whether fstk is currently showing its own formspec instead of active ui elements.
ui.overridden = false
--------------------------------------------------------------------------------
function ui.add(child)
--TODO check child
ui.childlist[child.name] = child
return child.name
end
--------------------------------------------------------------------------------
function ui.delete(child)
if ui.childlist[child.name] == nil then
return false
end
ui.childlist[child.name] = nil
return true
end
--------------------------------------------------------------------------------
function ui.set_default(name)
ui.default = name
end
--------------------------------------------------------------------------------
function ui.find_by_name(name)
return ui.childlist[name]
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Internal functions not to be called from user
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function ui.update()
ui.overridden = false
local formspec = {}
-- handle errors
if gamedata ~= nil and gamedata.reconnect_requested then
local error_message = core.formspec_escape(
gamedata.errormessage or fgettext("<none available>"))
formspec = {
"size[14,8]",
"real_coordinates[true]",
"set_focus[btn_reconnect_yes;true]",
"box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
fgettext("The server has requested a reconnect:"), error_message),
"button[2,6.6;4,1;btn_reconnect_yes;" .. fgettext("Reconnect") .. "]",
"button[8,6.6;4,1;btn_reconnect_no;" .. fgettext("Main menu") .. "]"
}
ui.overridden = true
elseif gamedata ~= nil and gamedata.errormessage ~= nil then
local error_message = core.formspec_escape(gamedata.errormessage)
local error_title
if string.find(gamedata.errormessage, "ModError") then
error_title = fgettext("An error occurred in a Lua script:")
else
error_title = fgettext("An error occurred:")
end
formspec = {
"size[14,8]",
"real_coordinates[true]",
"set_focus[btn_error_confirm;true]",
"box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
error_title, error_message),
"button[5,6.6;4,1;btn_error_confirm;" .. fgettext("OK") .. "]"
}
ui.overridden = true
else
local active_toplevel_ui_elements = 0
for key,value in pairs(ui.childlist) do
if (value.type == "toplevel") then
local retval = value:get_formspec()
if retval ~= nil and retval ~= "" then
active_toplevel_ui_elements = active_toplevel_ui_elements + 1
table.insert(formspec, retval)
end
end
end
-- no need to show addons if there ain't a toplevel element
if (active_toplevel_ui_elements > 0) then
for key,value in pairs(ui.childlist) do
if (value.type == "addon") then
local retval = value:get_formspec()
if retval ~= nil and retval ~= "" then
table.insert(formspec, retval)
end
end
end
end
if (active_toplevel_ui_elements > 1) then
core.log("warning", "more than one active ui "..
"element, self most likely isn't intended")
end
if (active_toplevel_ui_elements == 0) then
core.log("warning", "no toplevel ui element "..
"active; switching to default")
ui.childlist[ui.default]:show()
formspec = {ui.childlist[ui.default]:get_formspec()}
end
end
core.update_formspec(table.concat(formspec))
end
--------------------------------------------------------------------------------
function ui.handle_buttons(fields)
for key,value in pairs(ui.childlist) do
local retval = value:handle_buttons(fields)
if retval then
ui.update()
return
end
end
end
--------------------------------------------------------------------------------
function ui.handle_events(event)
for key,value in pairs(ui.childlist) do
if value.handle_events ~= nil then
local retval = value:handle_events(event)
if retval then
return retval
end
end
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- initialize callbacks
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
core.button_handler = function(fields)
if fields["btn_reconnect_yes"] then
gamedata.reconnect_requested = false
gamedata.errormessage = nil
gamedata.do_reconnect = true
core.start()
return
elseif fields["btn_reconnect_no"] or fields["btn_error_confirm"] then
gamedata.errormessage = nil
gamedata.reconnect_requested = false
ui.update()
return
end
if ui.handle_buttons(fields) then
ui.update()
end
end
--------------------------------------------------------------------------------
core.event_handler = function(event)
-- Handle error messages
if ui.overridden then
if event == "MenuQuit" then
gamedata.errormessage = nil
gamedata.reconnect_requested = false
ui.update()
end
return
end
if ui.handle_events(event) then
ui.update()
return
end
if event == "Refresh" then
ui.update()
return
end
end

22
builtin/game/async.lua Normal file
View File

@ -0,0 +1,22 @@
core.async_jobs = {}
function core.async_event_handler(jobid, retval)
local callback = core.async_jobs[jobid]
assert(type(callback) == "function")
callback(unpack(retval, 1, retval.n))
core.async_jobs[jobid] = nil
end
function core.handle_async(func, callback, ...)
assert(type(func) == "function" and type(callback) == "function",
"Invalid minetest.handle_async invocation")
local args = {n = select("#", ...), ...}
local mod_origin = core.get_last_run_mod()
local jobid = core.do_async_callback(func, args, mod_origin)
core.async_jobs[jobid] = callback
return true
end

185
builtin/game/auth.lua Normal file
View File

@ -0,0 +1,185 @@
-- Minetest: builtin/auth.lua
--
-- Builtin authentication handler
--
-- Make the auth object private, deny access to mods
local core_auth = core.auth
core.auth = nil
core.builtin_auth_handler = {
get_auth = function(name)
assert(type(name) == "string")
local auth_entry = core_auth.read(name)
-- If no such auth found, return nil
if not auth_entry then
return nil
end
-- Figure out what privileges the player should have.
-- Take a copy of the privilege table
local privileges = {}
for priv, _ in pairs(auth_entry.privileges) do
privileges[priv] = true
end
-- If singleplayer, give all privileges except those marked as give_to_singleplayer = false
if core.is_singleplayer() then
for priv, def in pairs(core.registered_privileges) do
if def.give_to_singleplayer then
privileges[priv] = true
end
end
-- For the admin, give everything
elseif name == core.settings:get("name") then
for priv, def in pairs(core.registered_privileges) do
if def.give_to_admin then
privileges[priv] = true
end
end
end
-- All done
return {
password = auth_entry.password,
privileges = privileges,
last_login = auth_entry.last_login,
}
end,
create_auth = function(name, password)
assert(type(name) == "string")
assert(type(password) == "string")
core.log('info', "Built-in authentication handler adding player '"..name.."'")
return core_auth.create({
name = name,
password = password,
privileges = core.string_to_privs(core.settings:get("default_privs")),
last_login = -1, -- Defer login time calculation until record_login (called by on_joinplayer)
})
end,
delete_auth = function(name)
assert(type(name) == "string")
local auth_entry = core_auth.read(name)
if not auth_entry then
return false
end
core.log('info', "Built-in authentication handler deleting player '"..name.."'")
return core_auth.delete(name)
end,
set_password = function(name, password)
assert(type(name) == "string")
assert(type(password) == "string")
local auth_entry = core_auth.read(name)
if not auth_entry then
core.builtin_auth_handler.create_auth(name, password)
else
core.log('info', "Built-in authentication handler setting password of player '"..name.."'")
auth_entry.password = password
core_auth.save(auth_entry)
end
return true
end,
set_privileges = function(name, privileges)
assert(type(name) == "string")
assert(type(privileges) == "table")
local auth_entry = core_auth.read(name)
if not auth_entry then
auth_entry = core.builtin_auth_handler.create_auth(name,
core.get_password_hash(name,
core.settings:get("default_password")))
end
auth_entry.privileges = privileges
core_auth.save(auth_entry)
-- Run grant callbacks
for priv, _ in pairs(privileges) do
if not auth_entry.privileges[priv] then
core.run_priv_callbacks(name, priv, nil, "grant")
end
end
-- Run revoke callbacks
for priv, _ in pairs(auth_entry.privileges) do
if not privileges[priv] then
core.run_priv_callbacks(name, priv, nil, "revoke")
end
end
core.notify_authentication_modified(name)
end,
reload = function()
core_auth.reload()
return true
end,
record_login = function(name)
assert(type(name) == "string")
local auth_entry = core_auth.read(name)
assert(auth_entry)
auth_entry.last_login = os.time()
core_auth.save(auth_entry)
end,
iterate = function()
local names = {}
local nameslist = core_auth.list_names()
for k,v in pairs(nameslist) do
names[v] = true
end
return pairs(names)
end,
}
core.register_on_prejoinplayer(function(name, ip)
if core.registered_auth_handler ~= nil then
return -- Don't do anything if custom auth handler registered
end
local auth_entry = core_auth.read(name)
if auth_entry ~= nil then
return
end
local name_lower = name:lower()
for k in core.builtin_auth_handler.iterate() do
if k:lower() == name_lower then
return string.format("\nCannot create new player called '%s'. "..
"Another account called '%s' is already registered. "..
"Please check the spelling if it's your account "..
"or use a different nickname.", name, k)
end
end
end)
--
-- Authentication API
--
function core.register_authentication_handler(handler)
if core.registered_auth_handler then
error("Add-on authentication handler already registered by "..core.registered_auth_handler_modname)
end
core.registered_auth_handler = handler
core.registered_auth_handler_modname = core.get_current_modname()
handler.mod_origin = core.registered_auth_handler_modname
end
function core.get_auth_handler()
return core.registered_auth_handler or core.builtin_auth_handler
end
local function auth_pass(name)
return function(...)
local auth_handler = core.get_auth_handler()
if auth_handler[name] then
return auth_handler[name](...)
end
return false
end
end
core.set_player_password = auth_pass("set_password")
core.set_player_privs = auth_pass("set_privileges")
core.remove_player_auth = auth_pass("delete_auth")
core.auth_reload = auth_pass("reload")
local record_login = auth_pass("record_login")
core.register_on_joinplayer(function(player)
record_login(player:get_player_name())
end)

1359
builtin/game/chat.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
-- Minetest: builtin/constants.lua
--
-- Constants values for use with the Lua API
--
-- mapnode.h
-- Built-in Content IDs (for use with VoxelManip API)
core.CONTENT_UNKNOWN = 125
core.CONTENT_AIR = 126
core.CONTENT_IGNORE = 127
-- emerge.h
-- Block emerge status constants (for use with core.emerge_area)
core.EMERGE_CANCELLED = 0
core.EMERGE_ERRORED = 1
core.EMERGE_FROM_MEMORY = 2
core.EMERGE_FROM_DISK = 3
core.EMERGE_GENERATED = 4
-- constants.h
-- Size of mapblocks in nodes
core.MAP_BLOCKSIZE = 16
-- Default maximal HP of a player
core.PLAYER_MAX_HP_DEFAULT = 20
-- Default maximal breath of a player
core.PLAYER_MAX_BREATH_DEFAULT = 10
-- light.h
-- Maximum value for node 'light_source' parameter
core.LIGHT_MAX = 14

Some files were not shown because too many files have changed in this diff Show More