Merge branch 'main' of https://github.com/MihailRis/VoxelEngine-Cpp
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
custom: ['https://www.donationalerts.com/r/mihailris']
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
name: Найден баг
|
||||||
|
about: Создайте отчет, чтобы помочь нам исправить этот баг
|
||||||
|
title: BUG
|
||||||
|
labels: bug, wontfix
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Опишите ошибку**
|
||||||
|
Четкое и краткое описание ошибки.
|
||||||
|
|
||||||
|
**Для воспроизведения**
|
||||||
|
Шаги для воспроизведения поведения:
|
||||||
|
1. Перейдите в раздел «...»
|
||||||
|
2. Нажмите «....»
|
||||||
|
3. Прокрутите вниз до «....»
|
||||||
|
4. См. ошибку
|
||||||
|
|
||||||
|
**Ожидаемое поведение**
|
||||||
|
Четкое и краткое описание того, что вы ожидаете.
|
||||||
|
|
||||||
|
**Скриншоты**
|
||||||
|
Если применимо, добавьте снимки экрана, которые помогут объяснить вашу проблему.
|
||||||
|
|
||||||
|
**Техническая информация (заполните следующую информацию):**
|
||||||
|
- ОС: [например. Windows 10]
|
||||||
|
- Версия [например. 0.17]
|
||||||
|
|
||||||
|
**Дополнительный контекст**
|
||||||
|
Добавьте сюда любой другой контекст проблемы.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Новая фича
|
||||||
|
about: Новая идея для этого проекта
|
||||||
|
title: 'ENHANCEMENT '
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Связан ли ваш запрос на добавление функции с проблемой? Пожалуйста, опишите.**
|
||||||
|
Четкое и краткое описание проблемы. Бывший. Я всегда расстраиваюсь, когда [...]
|
||||||
|
|
||||||
|
**Опишите желаемое решение**
|
||||||
|
Четкое и краткое описание того, чего вы хотите.
|
||||||
|
|
||||||
|
**Опишите альтернативы, которые вы рассматривали**
|
||||||
|
Четкое и краткое описание любых альтернативных решений или функций, которые вы рассматривали.
|
||||||
|
|
||||||
|
**Дополнительный контекст**
|
||||||
|
Добавьте сюда любой другой контекст или снимки экрана о запросе функции.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
name: Вопрос
|
||||||
|
about: Вопрос другого характера
|
||||||
|
title: QUESTION
|
||||||
|
labels: question
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Опишите свой вопрос**
|
||||||
|
Кратко и понятно опишите ваш вопрос.
|
||||||
|
Перед созданием этого запроса убедитесь, что ранее не были созданы подобные.
|
||||||
@@ -25,11 +25,16 @@ Debug/voxel_engine
|
|||||||
.settings
|
.settings
|
||||||
.cproject
|
.cproject
|
||||||
.project
|
.project
|
||||||
|
.fleet
|
||||||
.git
|
.git
|
||||||
/Default/
|
/Default/
|
||||||
AppDir
|
AppDir
|
||||||
appimage-build/
|
appimage-build/
|
||||||
|
|
||||||
|
# for vcpkg
|
||||||
|
/vcpkg/
|
||||||
|
.gitmodules
|
||||||
|
|
||||||
# macOS folder attributes
|
# macOS folder attributes
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
|
||||||
|
|||||||
+47
-4
@@ -1,3 +1,8 @@
|
|||||||
|
option(VOXELENGINE_BUILD_WINDOWS_VCPKG OFF)
|
||||||
|
if(VOXELENGINE_BUILD_WINDOWS_VCPKG AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake")
|
||||||
|
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
|
||||||
|
endif()
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
project(VoxelEngine)
|
project(VoxelEngine)
|
||||||
|
|
||||||
@@ -28,8 +33,10 @@ if(VOXELENGINE_BUILD_APPDIR)
|
|||||||
install(TARGETS VoxelEngine DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/AppDir/usr/bin)
|
install(TARGETS VoxelEngine DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/AppDir/usr/bin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
||||||
|
endif()
|
||||||
if((CMAKE_BUILD_TYPE EQUAL "Release") OR (CMAKE_BUILD_TYPE EQUAL "RelWithDebInfo"))
|
if((CMAKE_BUILD_TYPE EQUAL "Release") OR (CMAKE_BUILD_TYPE EQUAL "RelWithDebInfo"))
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Release>:Release>")
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Release>:Release>")
|
||||||
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /MT /O2)
|
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /MT /O2)
|
||||||
@@ -45,16 +52,52 @@ else()
|
|||||||
-Wwrite-strings -Wno-unused-parameter)
|
-Wwrite-strings -Wno-unused-parameter)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(VOXELENGINE_BUILD_WINDOWS_VCPKG AND WIN32)
|
||||||
|
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/.git")
|
||||||
|
find_package(Git QUIET)
|
||||||
|
if(GIT_FOUND)
|
||||||
|
message(STATUS "Adding vcpkg as a git submodule...")
|
||||||
|
execute_process(COMMAND ${GIT_EXECUTABLE} submodule add https://github.com/microsoft/vcpkg.git vcpkg WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Git not found, cannot add vcpkg submodule.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/.git")
|
||||||
|
message(STATUS "Initializing and updating vcpkg submodule...")
|
||||||
|
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E chdir vcpkg ./bootstrap-vcpkg.bat WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
|
||||||
|
string(TOUPPER ${CONFIG_TYPE} CONFIG_TYPE_UPPER)
|
||||||
|
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_SOURCE_DIR}/res ${CMAKE_BINARY_DIR}/${CONFIG_TYPE_UPPER}/res)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
find_package(GLEW REQUIRED)
|
find_package(GLEW REQUIRED)
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
# luajit has no CMakeLists.txt to use it as subdirectory, so install it
|
find_package(ZLIB REQUIRED)
|
||||||
find_package(Lua REQUIRED)
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
if(VOXELENGINE_BUILD_WINDOWS_VCPKG)
|
||||||
|
set(LUA_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/packages/luajit_x64-windows/lib/lua51.lib")
|
||||||
|
set(LUA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/packages/luajit_x64-windows/include/luajit")
|
||||||
|
find_package(glfw3 REQUIRED)
|
||||||
|
find_package(spng REQUIRED)
|
||||||
|
find_package(glm REQUIRED)
|
||||||
|
set(PNGLIB spng::spng)
|
||||||
|
else()
|
||||||
|
find_package(Lua REQUIRED)
|
||||||
set(PNGLIB spng)
|
set(PNGLIB spng)
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/glfw)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/glfw)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
|
# luajit has no CMakeLists.txt to use it as subdirectory, so install it manually
|
||||||
|
find_package(Lua REQUIRED)
|
||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
set(PNGLIB PNG::PNG)
|
set(PNGLIB PNG::PNG)
|
||||||
endif()
|
endif()
|
||||||
@@ -75,7 +118,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${LUA_INCLUDE_DIR})
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
target_link_libraries(${PROJECT_NAME} ${LIBS} glfw OpenGL::GL ${OPENAL_LIBRARY} GLEW::GLEW ${PNGLIB} ${LUA_LIBRARIES} ${CMAKE_DL_LIBS})
|
target_link_libraries(${PROJECT_NAME} ${LIBS} glfw OpenGL::GL ${OPENAL_LIBRARY} GLEW::GLEW ZLIB::ZLIB ${PNGLIB} ${LUA_LIBRARIES} ${CMAKE_DL_LIBS})
|
||||||
|
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
# Build docker container: docker build -t voxel-engine .
|
||||||
|
# Build project: docker run --rm -it -v$(pwd):/project voxel-engine bash -c "cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && cmake --build build"
|
||||||
|
# Run project in docker: docker run --rm -it -v$(pwd):/project -v/tmp/.X11-unix:/tmp/.X11-unix -v${XAUTHORITY}:/home/user/.Xauthority:ro -eDISPLAY --network=host voxel-engine ./build/VoxelEngine
|
||||||
|
|
||||||
|
FROM debian:bullseye-slim
|
||||||
|
LABEL Description="Docker container for building VoxelEngine for Linux"
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||||
|
git \
|
||||||
|
g++ \
|
||||||
|
make \
|
||||||
|
cmake \
|
||||||
|
xauth \
|
||||||
|
gdb \
|
||||||
|
gdbserver \
|
||||||
|
libglfw3-dev \
|
||||||
|
libglfw3 \
|
||||||
|
libglew-dev \
|
||||||
|
libglm-dev \
|
||||||
|
libpng-dev \
|
||||||
|
libopenal-dev \
|
||||||
|
libluajit-5.1-dev \
|
||||||
|
ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# CMake missing LUA_INCLUDE_DIR and LUA_LIBRARIES fix:
|
||||||
|
RUN ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua5.1.a \
|
||||||
|
&& ln -s /usr/include/luajit-2.1 /usr/include/lua
|
||||||
|
|
||||||
|
# Install LuaJIT:
|
||||||
|
RUN git clone https://luajit.org/git/luajit.git \
|
||||||
|
&& cd luajit \
|
||||||
|
&& make && make install INSTALL_INC=/usr/include/lua \
|
||||||
|
&& cd .. && rm -rf luajit
|
||||||
|
|
||||||
|
# Create default user, due to:
|
||||||
|
# - Build and test artifacts have user permissions and not root permissions
|
||||||
|
# - Don't give root privileges from host to containers (security)
|
||||||
|
ARG USER=user
|
||||||
|
ARG UID=1000
|
||||||
|
ARG GID=1000
|
||||||
|
RUN useradd -m ${USER} --uid=${UID}
|
||||||
|
USER ${UID}:${GID}
|
||||||
|
|
||||||
|
# Project workspace
|
||||||
|
WORKDIR /project
|
||||||
@@ -76,3 +76,44 @@ brew install glfw3 glew glm libpng lua luajit openal-soft
|
|||||||
```
|
```
|
||||||
|
|
||||||
If homebrew for some reason could not install the necessary packages: ```lua luajit openal-soft```, then download, install and compile them manually (Lua, LuaJIT and OpenAL).
|
If homebrew for some reason could not install the necessary packages: ```lua luajit openal-soft```, then download, install and compile them manually (Lua, LuaJIT and OpenAL).
|
||||||
|
|
||||||
|
## Build using Docker
|
||||||
|
|
||||||
|
### Step 0. Install docker on your system
|
||||||
|
|
||||||
|
See https://docs.docker.com/engine/install
|
||||||
|
|
||||||
|
### Step 1. Build docker container
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t voxel-engine .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2. Build project using the docker container
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm -it -v$(pwd):/project voxel-engine bash -c "cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && cmake --build build"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3. Run project using the docker container
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm -it -v$(pwd):/project -v/tmp/.X11-unix:/tmp/.X11-unix -v${XAUTHORITY}:/home/user/.Xauthority:ro -eDISPLAY --network=host voxel-engine ./build/VoxelEngine
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build with CMake and vcpkg for Windows
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://github.com/MihailRis/VoxelEngine-Cpp.git
|
||||||
|
cd VoxelEngine-Cpp
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_WINDOWS_VCPKG=ON ..
|
||||||
|
del CMakeCache.txt
|
||||||
|
rmdir /s /q CMakeFiles
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_WINDOWS_VCPKG=ON ..
|
||||||
|
cmake --build . --config Release
|
||||||
|
```
|
||||||
|
note: you can use ```rm CMakeCache.txt``` and ```rm -rf CMakeFiles``` while using Git Bash
|
||||||
|
|
||||||
|
If you have issues during the vcpkg integration, try navigate to ```vcpkg\downloads``` and extract PowerShell-[version]-win-x86 to ```vcpkg\downloads\tools``` as powershell-core-[version]-windows. Then rerun ```cmake -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_WINDOWS_VCPKG=ON ..```
|
||||||
@@ -16,7 +16,7 @@ void main(){
|
|||||||
float depth = (a_distance/256.0);
|
float depth = (a_distance/256.0);
|
||||||
float alpha = a_color.a * tex_color.a;
|
float alpha = a_color.a * tex_color.a;
|
||||||
// anyway it's any alpha-test alternative required
|
// anyway it's any alpha-test alternative required
|
||||||
if (alpha < 0.1f)
|
if (alpha < 0.3f)
|
||||||
discard;
|
discard;
|
||||||
f_color = mix(a_color * tex_color, vec4(fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve)));
|
f_color = mix(a_color * tex_color, vec4(fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve)));
|
||||||
f_color.a = alpha;
|
f_color.a = alpha;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ world.Name=Назва
|
|||||||
menu.Create World=Стварыць Свет
|
menu.Create World=Стварыць Свет
|
||||||
|
|
||||||
world.convert-request=Ёсць змены ў індэксах! Канвертаваць свет?
|
world.convert-request=Ёсць змены ў індэксах! Канвертаваць свет?
|
||||||
|
world.delete-confirm=Выдаліць свет незваротна?
|
||||||
|
|
||||||
# Настройки
|
# Настройки
|
||||||
settings.Load Distance=Дыстанцыя Загрузкі
|
settings.Load Distance=Дыстанцыя Загрузкі
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
menu.missing-content=Missing Content!
|
menu.missing-content=Missing Content!
|
||||||
world.convert-request=Content indices have changed! Convert world files?
|
world.convert-request=Content indices have changed! Convert world files?
|
||||||
error.pack-not-found=Could not to find pack
|
error.pack-not-found=Could not to find pack
|
||||||
|
world.delete-confirm=Do you want to delete world forever?
|
||||||
|
|
||||||
# Bindings
|
# Bindings
|
||||||
movement.forward=Forward
|
movement.forward=Forward
|
||||||
|
|||||||
+9
-7
@@ -12,8 +12,9 @@ error.pack-not-found=Pakettia ei löytynyt!
|
|||||||
menu.New World = Uusi Maailma
|
menu.New World = Uusi Maailma
|
||||||
menu.Quit=Poistu
|
menu.Quit=Poistu
|
||||||
menu.Continue=Jatka
|
menu.Continue=Jatka
|
||||||
menu.Save and Quit to Menu=Tallenna ja Takaisin valikoon
|
menu.Save and Quit to Menu=Tallenna ja poistu valikkoon
|
||||||
menu.missing-content=Puuttuu jotkut lisäosat!
|
menu.missing-content=Puuttuu jotkut lisäosat!
|
||||||
|
menu.Content Error=Sisältövirhe!
|
||||||
menu.Controls=Ohjaus
|
menu.Controls=Ohjaus
|
||||||
menu.Back to Main Menu=Takaisin Valikoon
|
menu.Back to Main Menu=Takaisin Valikoon
|
||||||
menu.Settings=Asetukset
|
menu.Settings=Asetukset
|
||||||
@@ -23,12 +24,13 @@ menu.Name=Nimi
|
|||||||
menu.Create World=Luo Maailma
|
menu.Create World=Luo Maailma
|
||||||
|
|
||||||
world.convert-request=Indeksit vaihdettu! Lataa maailma uudeleen?
|
world.convert-request=Indeksit vaihdettu! Lataa maailma uudeleen?
|
||||||
|
world.delete-confirm=Poistetaanko maailma ikuisesti?
|
||||||
|
|
||||||
# Настройки
|
# Настройки
|
||||||
settings.Load Distance=Lataus Alue
|
settings.Load Distance=Latausalue
|
||||||
settings.Load Speed=Lataus Nopeus
|
settings.Load Speed=Latausnopeus
|
||||||
settings.Fog Curve=Sumun valaistus
|
settings.Fog Curve=Sumun tiheys
|
||||||
settings.Backlight=Valaistus
|
settings.Backlight=Taustavalo
|
||||||
settings.V-Sync=Pystytahdistus
|
settings.V-Sync=Pystytahdistus
|
||||||
|
|
||||||
settings.FOV=Näkökenttä
|
settings.FOV=Näkökenttä
|
||||||
@@ -41,8 +43,8 @@ movement.back=Taaksepäin
|
|||||||
movement.left=Vaseemalle
|
movement.left=Vaseemalle
|
||||||
movement.right=Oikealle
|
movement.right=Oikealle
|
||||||
movement.jump=Hyppy
|
movement.jump=Hyppy
|
||||||
movement.sprint=Kiihtyvyys
|
movement.sprint=Juoksu
|
||||||
movement.crouch=Istu alas
|
movement.crouch=Hiipiä
|
||||||
movement.cheat=Huijata
|
movement.cheat=Huijata
|
||||||
hud.inventory=Varasto
|
hud.inventory=Varasto
|
||||||
player.pick=Ottaa lohko
|
player.pick=Ottaa lohko
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ world.Name=Название
|
|||||||
menu.Create World=Создать Мир
|
menu.Create World=Создать Мир
|
||||||
|
|
||||||
world.convert-request=Есть изменения в индексах! Конвертировать мир?
|
world.convert-request=Есть изменения в индексах! Конвертировать мир?
|
||||||
|
world.delete-confirm=Удалить мир безвозвратно?
|
||||||
|
|
||||||
# Настройки
|
# Настройки
|
||||||
settings.Load Distance=Дистанция Загрузки
|
settings.Load Distance=Дистанция Загрузки
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 237 B |
|
Before Width: | Height: | Size: 132 B After Width: | Height: | Size: 132 B |
@@ -58,7 +58,8 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool allAssets) {
|
|||||||
loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui3d", "ui3d");
|
loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui3d", "ui3d");
|
||||||
loader.add(ASSET_SHADER, SHADERS_FOLDER"/background", "background");
|
loader.add(ASSET_SHADER, SHADERS_FOLDER"/background", "background");
|
||||||
loader.add(ASSET_SHADER, SHADERS_FOLDER"/skybox_gen", "skybox_gen");
|
loader.add(ASSET_SHADER, SHADERS_FOLDER"/skybox_gen", "skybox_gen");
|
||||||
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/menubg.png", "menubg");
|
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/menubg.png", "gui/menubg");
|
||||||
|
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/delete_icon.png", "gui/delete_icon");
|
||||||
loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal");
|
loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal");
|
||||||
}
|
}
|
||||||
loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/blocks", "blocks");
|
loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/blocks", "blocks");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "gzip.h"
|
||||||
#include "byte_utils.h"
|
#include "byte_utils.h"
|
||||||
|
|
||||||
using namespace json;
|
using namespace json;
|
||||||
@@ -148,6 +149,14 @@ static Map* object_from_binary(ByteReader& reader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
|
std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
|
||||||
|
if (size < 2) {
|
||||||
|
throw std::runtime_error("bytes length is less than 2");
|
||||||
|
}
|
||||||
|
if (src[0] == gzip::MAGIC[0] && src[1] == gzip::MAGIC[1]) {
|
||||||
|
// reading compressed document
|
||||||
|
auto data = gzip::decompress(src, size);
|
||||||
|
return from_binary(data.data(), data.size());
|
||||||
|
} else {
|
||||||
ByteReader reader(src, size);
|
ByteReader reader(src, size);
|
||||||
std::unique_ptr<Value> value (value_from_binary(reader));
|
std::unique_ptr<Value> value (value_from_binary(reader));
|
||||||
if (value->type != valtype::map) {
|
if (value->type != valtype::map) {
|
||||||
@@ -156,4 +165,5 @@ std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
|
|||||||
std::unique_ptr<Map> obj (value->value.map);
|
std::unique_ptr<Map> obj (value->value.map);
|
||||||
value->value.map = nullptr;
|
value->value.map = nullptr;
|
||||||
return obj;
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
namespace gzip {
|
namespace gzip {
|
||||||
|
const unsigned char MAGIC[] = "\x1F\x8B";
|
||||||
std::vector<ubyte> compress(const ubyte* src, size_t size);
|
std::vector<ubyte> compress(const ubyte* src, size_t size);
|
||||||
std::vector<ubyte> decompress(const ubyte* src, size_t size);
|
std::vector<ubyte> decompress(const ubyte* src, size_t size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ void ContentLoader::loadBlock(Block* def, std::string name, fs::path file) {
|
|||||||
root->flag("sky-light-passing", def->skyLightPassing);
|
root->flag("sky-light-passing", def->skyLightPassing);
|
||||||
root->num("draw-group", def->drawGroup);
|
root->num("draw-group", def->drawGroup);
|
||||||
root->str("picking-item", def->pickingItem);
|
root->str("picking-item", def->pickingItem);
|
||||||
|
root->str("script-name", def->scriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::loadCustomBlockModel(Block* def, dynamic::Map* primitives) {
|
void ContentLoader::loadCustomBlockModel(Block* def, dynamic::Map* primitives) {
|
||||||
@@ -233,6 +234,8 @@ void ContentLoader::loadItem(ItemDef* def, std::string name, fs::path file) {
|
|||||||
}
|
}
|
||||||
root->str("icon", def->icon);
|
root->str("icon", def->icon);
|
||||||
root->str("placing-block", def->placingBlock);
|
root->str("placing-block", def->placingBlock);
|
||||||
|
root->str("script-name", def->scriptName);
|
||||||
|
root->num("stack-size", def->stackSize);
|
||||||
|
|
||||||
// item light emission [r, g, b] where r,g,b in range [0..15]
|
// item light emission [r, g, b] where r,g,b in range [0..15]
|
||||||
auto emissionarr = root->list("emission");
|
auto emissionarr = root->list("emission");
|
||||||
@@ -247,7 +250,7 @@ void ContentLoader::loadBlock(Block* def, std::string full, std::string name) {
|
|||||||
auto folder = pack->folder;
|
auto folder = pack->folder;
|
||||||
|
|
||||||
fs::path configFile = folder/fs::path("blocks/"+name+".json");
|
fs::path configFile = folder/fs::path("blocks/"+name+".json");
|
||||||
fs::path scriptfile = folder/fs::path("scripts/"+name+".lua");
|
fs::path scriptfile = folder/fs::path("scripts/"+def->scriptName+".lua");
|
||||||
loadBlock(def, full, configFile);
|
loadBlock(def, full, configFile);
|
||||||
if (fs::is_regular_file(scriptfile)) {
|
if (fs::is_regular_file(scriptfile)) {
|
||||||
scripting::load_block_script(full, scriptfile, &def->rt.funcsset);
|
scripting::load_block_script(full, scriptfile, &def->rt.funcsset);
|
||||||
@@ -258,7 +261,7 @@ void ContentLoader::loadItem(ItemDef* def, std::string full, std::string name) {
|
|||||||
auto folder = pack->folder;
|
auto folder = pack->folder;
|
||||||
|
|
||||||
fs::path configFile = folder/fs::path("items/"+name+".json");
|
fs::path configFile = folder/fs::path("items/"+name+".json");
|
||||||
fs::path scriptfile = folder/fs::path("scripts/"+name+".lua");
|
fs::path scriptfile = folder/fs::path("scripts/"+def->scriptName+".lua");
|
||||||
loadItem(def, full, configFile);
|
loadItem(def, full, configFile);
|
||||||
if (fs::is_regular_file(scriptfile)) {
|
if (fs::is_regular_file(scriptfile)) {
|
||||||
scripting::load_item_script(full, scriptfile, &def->rt.funcsset);
|
scripting::load_item_script(full, scriptfile, &def->rt.funcsset);
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ Engine::Engine(EngineSettings& settings, EnginePaths* paths)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto resdir = paths->getResources();
|
auto resdir = paths->getResources();
|
||||||
scripting::initialize(paths);
|
scripting::initialize(this);
|
||||||
|
|
||||||
std::cout << "-- loading assets" << std::endl;
|
std::cout << "-- loading assets" << std::endl;
|
||||||
std::vector<fs::path> roots {resdir};
|
std::vector<fs::path> roots {resdir};
|
||||||
|
|||||||
+280
-92
@@ -1,126 +1,180 @@
|
|||||||
#include "InventoryView.h"
|
#include "InventoryView.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "BlocksPreview.h"
|
#include "BlocksPreview.h"
|
||||||
#include "LevelFrontend.h"
|
#include "LevelFrontend.h"
|
||||||
#include "../window/Events.h"
|
#include "../window/Events.h"
|
||||||
|
#include "../window/input.h"
|
||||||
#include "../assets/Assets.h"
|
#include "../assets/Assets.h"
|
||||||
#include "../graphics/Atlas.h"
|
#include "../graphics/Atlas.h"
|
||||||
#include "../graphics/Shader.h"
|
#include "../graphics/Shader.h"
|
||||||
#include "../graphics/Batch2D.h"
|
#include "../graphics/Batch2D.h"
|
||||||
#include "../graphics/GfxContext.h"
|
#include "../graphics/GfxContext.h"
|
||||||
|
#include "../graphics/Font.h"
|
||||||
#include "../content/Content.h"
|
#include "../content/Content.h"
|
||||||
#include "../items/ItemDef.h"
|
#include "../items/ItemDef.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
#include "../maths/voxmaths.h"
|
#include "../maths/voxmaths.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../voxels/Block.h"
|
#include "../voxels/Block.h"
|
||||||
|
#include "../frontend/gui/controls.h"
|
||||||
|
#include "../util/stringutil.h"
|
||||||
|
|
||||||
InventoryView::InventoryView(
|
InventoryLayout::InventoryLayout(glm::vec2 size) : size(size) {}
|
||||||
int columns,
|
|
||||||
const Content* content,
|
void InventoryLayout::add(SlotLayout slot) {
|
||||||
|
slots.push_back(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InventoryLayout::setSize(glm::vec2 size) {
|
||||||
|
this->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InventoryLayout::setOrigin(glm::vec2 origin) {
|
||||||
|
this->origin = origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 InventoryLayout::getSize() const {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 InventoryLayout::getOrigin() const {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SlotLayout>& InventoryLayout::getSlots() {
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotLayout::SlotLayout(
|
||||||
|
glm::vec2 position,
|
||||||
|
bool background,
|
||||||
|
bool itemSource,
|
||||||
|
itemsharefunc shareFunc,
|
||||||
|
slotcallback rightClick
|
||||||
|
)
|
||||||
|
: position(position),
|
||||||
|
background(background),
|
||||||
|
itemSource(itemSource),
|
||||||
|
shareFunc(shareFunc),
|
||||||
|
rightClick(rightClick) {}
|
||||||
|
|
||||||
|
InventoryPanel::InventoryPanel(
|
||||||
|
glm::vec2 position,
|
||||||
|
glm::vec2 size,
|
||||||
|
glm::vec4 color)
|
||||||
|
: position(position), size(size), color(color) {}
|
||||||
|
|
||||||
|
InventoryBuilder::InventoryBuilder()
|
||||||
|
: layout(std::make_unique<InventoryLayout>(glm::vec2()))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void InventoryBuilder::addGrid(
|
||||||
|
int cols, int rows,
|
||||||
|
glm::vec2 coord,
|
||||||
|
int padding,
|
||||||
|
SlotLayout slotLayout)
|
||||||
|
{
|
||||||
|
const int slotSize = InventoryView::SLOT_SIZE;
|
||||||
|
const int interval = InventoryView::SLOT_INTERVAL;
|
||||||
|
|
||||||
|
uint width = cols * (slotSize + interval) - interval + padding*2;
|
||||||
|
uint height = rows * (slotSize + interval) - interval + padding*2;
|
||||||
|
|
||||||
|
auto lsize = layout->getSize();
|
||||||
|
if (coord.x + width > lsize.x) {
|
||||||
|
lsize.x = coord.x + width;
|
||||||
|
}
|
||||||
|
if (coord.y + height > lsize.y) {
|
||||||
|
lsize.y = coord.y + height;
|
||||||
|
}
|
||||||
|
layout->setSize(lsize);
|
||||||
|
|
||||||
|
for (int row = 0; row < rows; row++) {
|
||||||
|
for (int col = 0; col < cols; col++) {
|
||||||
|
glm::vec2 position (
|
||||||
|
col * (slotSize + interval) + padding,
|
||||||
|
row * (slotSize + interval) + padding
|
||||||
|
);
|
||||||
|
auto builtSlot = slotLayout;
|
||||||
|
builtSlot.position = position;
|
||||||
|
layout->add(builtSlot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<InventoryLayout> InventoryBuilder::build() {
|
||||||
|
return std::unique_ptr<InventoryLayout>(layout.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotView::SlotView(
|
||||||
|
ItemStack& stack,
|
||||||
LevelFrontend* frontend,
|
LevelFrontend* frontend,
|
||||||
std::vector<itemid_t> items)
|
InventoryInteraction* interaction,
|
||||||
: content(content),
|
const Content* content,
|
||||||
indices(content->getIndices()),
|
SlotLayout layout)
|
||||||
items(items),
|
: UINode(glm::vec2(), glm::vec2(InventoryView::SLOT_SIZE)),
|
||||||
frontend(frontend),
|
frontend(frontend),
|
||||||
columns(columns) {
|
interaction(interaction),
|
||||||
|
content(content),
|
||||||
|
stack(stack),
|
||||||
|
layout(layout) {
|
||||||
|
color(glm::vec4(0, 0, 0, 0.2f));
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryView::~InventoryView() {
|
// performance disaster
|
||||||
}
|
void SlotView::draw(Batch2D* batch, Assets* assets) {
|
||||||
|
glm::vec2 coord = calcCoord();
|
||||||
|
|
||||||
void InventoryView::setPosition(int x, int y) {
|
int slotSize = InventoryView::SLOT_SIZE;
|
||||||
position.x = x;
|
|
||||||
position.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
int InventoryView::getWidth() const {
|
glm::vec4 tint(1.0f);
|
||||||
return columns * iconSize + (columns-1) * interval + padding.x * 2;
|
glm::vec4 color = color_;
|
||||||
}
|
if (hover_ || highlighted) {
|
||||||
|
tint *= 1.333f;
|
||||||
|
color = glm::vec4(1, 1, 1, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
int InventoryView::getHeight() const {
|
batch->color = color;
|
||||||
uint inv_rows = ceildiv(items.size(), columns);
|
if (color.a > 0.0) {
|
||||||
return inv_rows * iconSize + (inv_rows-1) * interval + padding.y * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InventoryView::setSlotConsumer(slotconsumer consumer) {
|
|
||||||
this->consumer = consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InventoryView::setItems(std::vector<itemid_t> items) {
|
|
||||||
this->items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InventoryView::actAndDraw(const GfxContext* ctx) {
|
|
||||||
Assets* assets = frontend->getAssets();
|
|
||||||
Shader* uiShader = assets->getShader("ui");
|
|
||||||
|
|
||||||
auto viewport = ctx->getViewport();
|
|
||||||
uint inv_w = getWidth();
|
|
||||||
uint inv_h = getHeight();
|
|
||||||
int xs = position.x + padding.x;
|
|
||||||
int ys = position.y + padding.y;
|
|
||||||
|
|
||||||
glm::vec4 tint (1.0f);
|
|
||||||
int mx = Events::cursor.x;
|
|
||||||
int my = Events::cursor.y;
|
|
||||||
|
|
||||||
// background
|
|
||||||
auto batch = ctx->getBatch2D();
|
|
||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
batch->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.5f);
|
if (highlighted) {
|
||||||
batch->rect(position.x, position.y, inv_w, inv_h);
|
batch->rect(coord.x-4, coord.y-4, slotSize+8, slotSize+8);
|
||||||
batch->render();
|
|
||||||
|
|
||||||
// blocks & items
|
|
||||||
if (Events::scroll) {
|
|
||||||
scroll -= Events::scroll * (iconSize+interval);
|
|
||||||
}
|
|
||||||
scroll = std::min(scroll, int(inv_h-viewport.getHeight()));
|
|
||||||
scroll = std::max(scroll, 0);
|
|
||||||
|
|
||||||
auto blocksPreview = frontend->getBlocksPreview();
|
|
||||||
// todo: optimize
|
|
||||||
{
|
|
||||||
Window::clearDepth();
|
|
||||||
GfxContext subctx = ctx->sub();
|
|
||||||
subctx.depthTest(true);
|
|
||||||
subctx.cullFace(true);
|
|
||||||
uint index = 0;
|
|
||||||
for (uint i = 0; i < items.size(); i++) {
|
|
||||||
ItemDef* item = indices->getItemDef(items[i]);
|
|
||||||
int x = xs + (iconSize+interval) * (index % columns);
|
|
||||||
int y = ys + (iconSize+interval) * (index / columns) - scroll;
|
|
||||||
if (y < -int(iconSize+interval) || y >= int(viewport.getHeight())) {
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (mx > x && mx < x + (int)iconSize && my > y && my < y + (int)iconSize) {
|
|
||||||
tint.r *= 1.2f;
|
|
||||||
tint.g *= 1.2f;
|
|
||||||
tint.b *= 1.2f;
|
|
||||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
|
||||||
if (consumer) {
|
|
||||||
consumer(items[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
tint = glm::vec4(1.0f);
|
batch->rect(coord.x, coord.y, slotSize, slotSize);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
batch->color = glm::vec4(1.0f);
|
||||||
|
|
||||||
|
Shader* uiShader = assets->getShader("ui");
|
||||||
|
Viewport viewport(Window::width, Window::height);
|
||||||
|
GfxContext ctx(nullptr, viewport, batch);
|
||||||
|
|
||||||
|
auto preview = frontend->getBlocksPreview();
|
||||||
|
auto indices = content->getIndices();
|
||||||
|
|
||||||
|
ItemDef* item = indices->getItemDef(stack.getItemId());
|
||||||
switch (item->iconType) {
|
switch (item->iconType) {
|
||||||
case item_icon_type::none:
|
case item_icon_type::none:
|
||||||
break;
|
break;
|
||||||
case item_icon_type::block: {
|
case item_icon_type::block:
|
||||||
|
batch->render();
|
||||||
|
{
|
||||||
|
GfxContext subctx = ctx.sub();
|
||||||
|
subctx.depthTest(true);
|
||||||
|
subctx.cullFace(true);
|
||||||
|
|
||||||
Block* cblock = content->requireBlock(item->icon);
|
Block* cblock = content->requireBlock(item->icon);
|
||||||
blocksPreview->begin(&ctx->getViewport());
|
preview->begin(&subctx.getViewport());
|
||||||
blocksPreview->draw(cblock, x, y, iconSize, tint);
|
preview->draw(cblock, coord.x, coord.y, slotSize, tint);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case item_icon_type::sprite: {
|
|
||||||
batch->begin();
|
|
||||||
uiShader->use();
|
uiShader->use();
|
||||||
|
batch->begin();
|
||||||
|
break;
|
||||||
|
case item_icon_type::sprite: {
|
||||||
size_t index = item->icon.find(':');
|
size_t index = item->icon.find(':');
|
||||||
std::string name = item->icon.substr(index+1);
|
std::string name = item->icon.substr(index+1);
|
||||||
UVRegion region(0.0f, 0.0, 1.0f, 1.0f);
|
UVRegion region(0.0f, 0.0, 1.0f, 1.0f);
|
||||||
@@ -134,13 +188,147 @@ void InventoryView::actAndDraw(const GfxContext* ctx) {
|
|||||||
batch->texture(atlas->getTexture());
|
batch->texture(atlas->getTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch->rect(x, y, 48, 48, 0, 0, 0, region, false, true, glm::vec4(1.0f));
|
batch->rect(
|
||||||
batch->render();
|
coord.x, coord.y, slotSize, slotSize,
|
||||||
|
0, 0, 0, region, false, true, tint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stack.getCount() > 1) {
|
||||||
|
auto font = assets->getFont("normal");
|
||||||
|
std::wstring text = std::to_wstring(stack.getCount());
|
||||||
|
|
||||||
|
int x = coord.x+slotSize-text.length()*8;
|
||||||
|
int y = coord.y+slotSize-16;
|
||||||
|
|
||||||
|
batch->color = glm::vec4(0, 0, 0, 1.0f);
|
||||||
|
font->draw(batch, text, x+1, y+1);
|
||||||
|
batch->color = glm::vec4(1.0f);
|
||||||
|
font->draw(batch, text, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlotView::setHighlighted(bool flag) {
|
||||||
|
highlighted = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SlotView::isHighlighted() const {
|
||||||
|
return highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlotView::clicked(gui::GUI* gui, int button) {
|
||||||
|
ItemStack& grabbed = interaction->getGrabbedItem();
|
||||||
|
if (button == mousecode::BUTTON_1) {
|
||||||
|
if (Events::pressed(keycode::LEFT_SHIFT)) {
|
||||||
|
if (layout.shareFunc) {
|
||||||
|
layout.shareFunc(stack);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!layout.itemSource && stack.accepts(grabbed)) {
|
||||||
|
stack.move(grabbed, content->getIndices());
|
||||||
|
} else {
|
||||||
|
if (layout.itemSource) {
|
||||||
|
if (grabbed.isEmpty()) {
|
||||||
|
grabbed.set(stack);
|
||||||
|
} else {
|
||||||
|
grabbed.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::swap(grabbed, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (button == mousecode::BUTTON_2) {
|
||||||
|
if (layout.rightClick) {
|
||||||
|
layout.rightClick(stack, grabbed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (layout.itemSource)
|
||||||
|
return;
|
||||||
|
if (grabbed.isEmpty()) {
|
||||||
|
if (!stack.isEmpty()) {
|
||||||
|
grabbed.set(stack);
|
||||||
|
int halfremain = stack.getCount() / 2;
|
||||||
|
grabbed.setCount(stack.getCount() - halfremain);
|
||||||
|
stack.setCount(halfremain);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (stack.isEmpty()) {
|
||||||
|
stack.set(grabbed);
|
||||||
|
stack.setCount(1);
|
||||||
|
} else {
|
||||||
|
stack.setCount(stack.getCount()+1);
|
||||||
|
}
|
||||||
|
grabbed.setCount(grabbed.getCount()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryView::InventoryView(
|
||||||
|
const Content* content,
|
||||||
|
LevelFrontend* frontend,
|
||||||
|
InventoryInteraction* interaction,
|
||||||
|
std::shared_ptr<Inventory> inventory,
|
||||||
|
std::unique_ptr<InventoryLayout> layout)
|
||||||
|
: Container(glm::vec2(), glm::vec2()),
|
||||||
|
content(content),
|
||||||
|
indices(content->getIndices()),
|
||||||
|
inventory(inventory),
|
||||||
|
layout(std::move(layout)),
|
||||||
|
frontend(frontend),
|
||||||
|
interaction(interaction) {
|
||||||
|
size(this->layout->getSize());
|
||||||
|
color(glm::vec4(0, 0, 0, 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryView::~InventoryView() {}
|
||||||
|
|
||||||
|
void InventoryView::build() {
|
||||||
|
int index = 0;
|
||||||
|
for (auto& slot : layout->getSlots()) {
|
||||||
|
ItemStack& item = inventory->getSlot(index);
|
||||||
|
|
||||||
|
auto view = std::make_shared<SlotView>(
|
||||||
|
item, frontend, interaction, content, slot
|
||||||
|
);
|
||||||
|
if (!slot.background) {
|
||||||
|
view->color(glm::vec4());
|
||||||
|
}
|
||||||
|
slots.push_back(view.get());
|
||||||
|
add(view, slot.position);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InventoryView::setSelected(int index) {
|
||||||
|
for (int i = 0; i < int(slots.size()); i++) {
|
||||||
|
auto slot = slots[i];
|
||||||
|
slot->setHighlighted(i == index);
|
||||||
}
|
}
|
||||||
uiShader->use();
|
}
|
||||||
|
|
||||||
|
void InventoryView::setCoord(glm::vec2 coord) {
|
||||||
|
Container::setCoord(coord - layout->getOrigin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void InventoryView::setInventory(std::shared_ptr<Inventory> inventory) {
|
||||||
|
this->inventory = inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryLayout* InventoryView::getLayout() const {
|
||||||
|
return layout.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// performance disaster x2
|
||||||
|
void InventoryView::draw(Batch2D* batch, Assets* assets) {
|
||||||
|
Container::draw(batch, assets);
|
||||||
|
Window::clearDepth();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InventoryView::drawBackground(Batch2D* batch, Assets* assets) {
|
||||||
|
glm::vec2 coord = calcCoord();
|
||||||
|
batch->texture(nullptr);
|
||||||
|
batch->color = color_;
|
||||||
|
batch->rect(coord.x-1, coord.y-1, size_.x+2, size_.y+2);
|
||||||
}
|
}
|
||||||
|
|||||||
+121
-17
@@ -5,46 +5,150 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "../frontend/gui/UINode.h"
|
||||||
|
#include "../frontend/gui/panels.h"
|
||||||
|
#include "../frontend/gui/controls.h"
|
||||||
|
#include "../items/ItemStack.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
class Batch2D;
|
||||||
class Assets;
|
class Assets;
|
||||||
class GfxContext;
|
class GfxContext;
|
||||||
class Content;
|
class Content;
|
||||||
class ContentIndices;
|
class ContentIndices;
|
||||||
class LevelFrontend;
|
class LevelFrontend;
|
||||||
|
class Inventory;
|
||||||
|
|
||||||
typedef std::function<void(itemid_t)> slotconsumer;
|
typedef std::function<void(ItemStack&)> itemsharefunc;
|
||||||
|
typedef std::function<void(ItemStack&, ItemStack&)> slotcallback;
|
||||||
|
|
||||||
class InventoryView {
|
class InventoryInteraction;
|
||||||
|
|
||||||
|
struct SlotLayout {
|
||||||
|
glm::vec2 position;
|
||||||
|
bool background;
|
||||||
|
bool itemSource;
|
||||||
|
itemsharefunc shareFunc;
|
||||||
|
slotcallback rightClick;
|
||||||
|
|
||||||
|
SlotLayout(glm::vec2 position,
|
||||||
|
bool background,
|
||||||
|
bool itemSource,
|
||||||
|
itemsharefunc shareFunc,
|
||||||
|
slotcallback rightClick);
|
||||||
|
};
|
||||||
|
|
||||||
|
// temporary unused
|
||||||
|
struct InventoryPanel {
|
||||||
|
glm::vec2 position;
|
||||||
|
glm::vec2 size;
|
||||||
|
glm::vec4 color;
|
||||||
|
|
||||||
|
InventoryPanel(glm::vec2 position,
|
||||||
|
glm::vec2 size,
|
||||||
|
glm::vec4 color);
|
||||||
|
};
|
||||||
|
|
||||||
|
class InventoryLayout {
|
||||||
|
glm::vec2 size;
|
||||||
|
glm::vec2 origin;
|
||||||
|
std::vector<SlotLayout> slots;
|
||||||
|
public:
|
||||||
|
InventoryLayout(glm::vec2 size);
|
||||||
|
|
||||||
|
void add(SlotLayout slot);
|
||||||
|
void setSize(glm::vec2 size);
|
||||||
|
void setOrigin(glm::vec2 origin);
|
||||||
|
|
||||||
|
glm::vec2 getSize() const;
|
||||||
|
glm::vec2 getOrigin() const;
|
||||||
|
|
||||||
|
std::vector<SlotLayout>& getSlots();
|
||||||
|
};
|
||||||
|
|
||||||
|
class InventoryBuilder {
|
||||||
|
std::unique_ptr<InventoryLayout> layout;
|
||||||
|
public:
|
||||||
|
InventoryBuilder();
|
||||||
|
|
||||||
|
void addGrid(
|
||||||
|
int cols, int rows,
|
||||||
|
glm::vec2 coord,
|
||||||
|
int padding,
|
||||||
|
SlotLayout slotLayout);
|
||||||
|
std::unique_ptr<InventoryLayout> build();
|
||||||
|
};
|
||||||
|
|
||||||
|
class SlotView : public gui::UINode {
|
||||||
|
LevelFrontend* frontend;
|
||||||
|
InventoryInteraction* interaction;
|
||||||
|
const Content* const content;
|
||||||
|
ItemStack& stack;
|
||||||
|
bool highlighted = false;
|
||||||
|
|
||||||
|
SlotLayout layout;
|
||||||
|
public:
|
||||||
|
SlotView(ItemStack& stack,
|
||||||
|
LevelFrontend* frontend,
|
||||||
|
InventoryInteraction* interaction,
|
||||||
|
const Content* content,
|
||||||
|
SlotLayout layout);
|
||||||
|
|
||||||
|
virtual void draw(Batch2D* batch, Assets* assets) override;
|
||||||
|
|
||||||
|
void setHighlighted(bool flag);
|
||||||
|
bool isHighlighted() const;
|
||||||
|
|
||||||
|
virtual void clicked(gui::GUI*, int) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InventoryView : public gui::Container {
|
||||||
const Content* content;
|
const Content* content;
|
||||||
const ContentIndices* indices;
|
const ContentIndices* indices;
|
||||||
std::vector<itemid_t> items;
|
|
||||||
slotconsumer consumer = nullptr;
|
std::shared_ptr<Inventory> inventory;
|
||||||
|
std::unique_ptr<InventoryLayout> layout;
|
||||||
LevelFrontend* frontend;
|
LevelFrontend* frontend;
|
||||||
|
InventoryInteraction* interaction;
|
||||||
|
|
||||||
|
std::vector<SlotView*> slots;
|
||||||
|
|
||||||
int scroll = 0;
|
int scroll = 0;
|
||||||
int columns;
|
|
||||||
uint iconSize = 48;
|
|
||||||
uint interval = 4;
|
|
||||||
glm::ivec2 padding {interval, interval};
|
|
||||||
glm::ivec2 position {0, 0};
|
|
||||||
public:
|
public:
|
||||||
InventoryView(
|
InventoryView(
|
||||||
int columns,
|
|
||||||
const Content* content,
|
const Content* content,
|
||||||
LevelFrontend* frontend,
|
LevelFrontend* frontend,
|
||||||
std::vector<itemid_t> items);
|
InventoryInteraction* interaction,
|
||||||
|
std::shared_ptr<Inventory> inventory,
|
||||||
|
std::unique_ptr<InventoryLayout> layout);
|
||||||
|
|
||||||
virtual ~InventoryView();
|
virtual ~InventoryView();
|
||||||
|
|
||||||
virtual void actAndDraw(const GfxContext* ctx);
|
void build();
|
||||||
|
|
||||||
void setItems(std::vector<itemid_t> items);
|
virtual void draw(Batch2D* batch, Assets* assets) override;
|
||||||
|
virtual void drawBackground(Batch2D* batch, Assets* assets) override;
|
||||||
|
|
||||||
void setPosition(int x, int y);
|
void setInventory(std::shared_ptr<Inventory> inventory);
|
||||||
int getWidth() const;
|
|
||||||
int getHeight() const;
|
virtual void setCoord(glm::vec2 coord) override;
|
||||||
void setSlotConsumer(slotconsumer consumer);
|
|
||||||
|
InventoryLayout* getLayout() const;
|
||||||
|
|
||||||
|
void setSelected(int index);
|
||||||
|
|
||||||
|
static const int SLOT_INTERVAL = 4;
|
||||||
|
static const int SLOT_SIZE = 48;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InventoryInteraction {
|
||||||
|
ItemStack grabbedItem;
|
||||||
|
public:
|
||||||
|
InventoryInteraction() = default;
|
||||||
|
|
||||||
|
ItemStack& getGrabbedItem() {
|
||||||
|
return grabbedItem;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FRONTEND_INVENTORY_VIEW_H_
|
#endif // FRONTEND_INVENTORY_VIEW_H_
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "../settings.h"
|
#include "../settings.h"
|
||||||
#include "../engine.h"
|
#include "../engine.h"
|
||||||
#include "../items/ItemDef.h"
|
#include "../items/ItemDef.h"
|
||||||
|
#include "../items/ItemStack.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
#include "LevelFrontend.h"
|
#include "LevelFrontend.h"
|
||||||
#include "graphics/Skybox.h"
|
#include "graphics/Skybox.h"
|
||||||
|
|
||||||
@@ -169,8 +171,10 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible
|
|||||||
shader->uniform3f("u_cameraPos", camera->position);
|
shader->uniform3f("u_cameraPos", camera->position);
|
||||||
shader->uniform1i("u_cubemap", 1);
|
shader->uniform1i("u_cubemap", 1);
|
||||||
{
|
{
|
||||||
itemid_t id = level->player->getChosenItem();
|
auto player = level->player;
|
||||||
ItemDef* item = indices->getItemDef(id);
|
auto inventory = player->getInventory();
|
||||||
|
ItemStack& stack = inventory->getSlot(player->getChosenSlot());
|
||||||
|
ItemDef* item = indices->getItemDef(stack.getItemId());
|
||||||
assert(item != nullptr);
|
assert(item != nullptr);
|
||||||
float multiplier = 0.5f;
|
float multiplier = 0.5f;
|
||||||
shader->uniform3f("u_torchlightColor",
|
shader->uniform3f("u_torchlightColor",
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ PagesControl* GUI::getMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GUI::actMouse(float delta) {
|
void GUI::actMouse(float delta) {
|
||||||
|
|
||||||
auto hover = container->getAt(Events::cursor, nullptr);
|
auto hover = container->getAt(Events::cursor, nullptr);
|
||||||
if (this->hover && this->hover != hover) {
|
if (this->hover && this->hover != hover) {
|
||||||
this->hover->hover(false);
|
this->hover->hover(false);
|
||||||
@@ -53,7 +52,7 @@ void GUI::actMouse(float delta) {
|
|||||||
}
|
}
|
||||||
this->hover = hover;
|
this->hover = hover;
|
||||||
|
|
||||||
if (Events::jclicked(0)) {
|
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||||
if (pressed == nullptr && this->hover) {
|
if (pressed == nullptr && this->hover) {
|
||||||
pressed = hover;
|
pressed = hover;
|
||||||
pressed->click(this, Events::cursor.x, Events::cursor.y);
|
pressed->click(this, Events::cursor.x, Events::cursor.y);
|
||||||
@@ -73,6 +72,14 @@ void GUI::actMouse(float delta) {
|
|||||||
pressed->mouseRelease(this, Events::cursor.x, Events::cursor.y);
|
pressed->mouseRelease(this, Events::cursor.x, Events::cursor.y);
|
||||||
pressed = nullptr;
|
pressed = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hover) {
|
||||||
|
for (int i = mousecode::BUTTON_1; i < mousecode::BUTTON_1+12; i++) {
|
||||||
|
if (Events::jclicked(i)) {
|
||||||
|
hover->clicked(this, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::act(float delta) {
|
void GUI::act(float delta) {
|
||||||
@@ -100,13 +107,6 @@ void GUI::act(float delta) {
|
|||||||
if (Events::clicked(mousecode::BUTTON_1)) {
|
if (Events::clicked(mousecode::BUTTON_1)) {
|
||||||
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
|
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
|
||||||
}
|
}
|
||||||
if (prevfocus == focus){
|
|
||||||
for (int i = mousecode::BUTTON_1; i < mousecode::BUTTON_1+12; i++) {
|
|
||||||
if (Events::jclicked(i)) {
|
|
||||||
focus->clicked(this, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ using gui::Align;
|
|||||||
using glm::vec2;
|
using glm::vec2;
|
||||||
using glm::vec4;
|
using glm::vec4;
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
UINode::UINode(vec2 coord, vec2 size) : coord(coord), size_(size) {
|
UINode::UINode(vec2 coord, vec2 size) : coord(coord), size_(size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,9 +76,20 @@ bool UINode::isInside(glm::vec2 pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<UINode> UINode::getAt(vec2 pos, shared_ptr<UINode> self) {
|
shared_ptr<UINode> UINode::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||||
|
if (!interactive) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return isInside(pos) ? self : nullptr;
|
return isInside(pos) ? self : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UINode::isInteractive() const {
|
||||||
|
return interactive && visible();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UINode::setInteractive(bool flag) {
|
||||||
|
interactive = flag;
|
||||||
|
}
|
||||||
|
|
||||||
vec2 UINode::calcCoord() const {
|
vec2 UINode::calcCoord() const {
|
||||||
if (parent) {
|
if (parent) {
|
||||||
return coord + parent->calcCoord() + parent->contentOffset();
|
return coord + parent->calcCoord() + parent->contentOffset();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace gui {
|
|||||||
bool hover_ = false;
|
bool hover_ = false;
|
||||||
bool pressed_ = false;
|
bool pressed_ = false;
|
||||||
bool focused_ = false;
|
bool focused_ = false;
|
||||||
|
bool interactive = true;
|
||||||
Align align_ = Align::left;
|
Align align_ = Align::left;
|
||||||
UINode* parent = nullptr;
|
UINode* parent = nullptr;
|
||||||
UINode(glm::vec2 coord, glm::vec2 size);
|
UINode(glm::vec2 coord, glm::vec2 size);
|
||||||
@@ -74,9 +75,12 @@ namespace gui {
|
|||||||
virtual bool isInside(glm::vec2 pos);
|
virtual bool isInside(glm::vec2 pos);
|
||||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self);
|
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self);
|
||||||
|
|
||||||
|
virtual bool isInteractive() const;
|
||||||
|
virtual void setInteractive(bool flag);
|
||||||
|
|
||||||
virtual glm::vec2 contentOffset() {return glm::vec2(0.0f);};
|
virtual glm::vec2 contentOffset() {return glm::vec2(0.0f);};
|
||||||
glm::vec2 calcCoord() const;
|
glm::vec2 calcCoord() const;
|
||||||
void setCoord(glm::vec2 coord);
|
virtual void setCoord(glm::vec2 coord);
|
||||||
glm::vec2 size() const;
|
glm::vec2 size() const;
|
||||||
virtual void size(glm::vec2 size);
|
virtual void size(glm::vec2 size);
|
||||||
void _size(glm::vec2 size);
|
void _size(glm::vec2 size);
|
||||||
|
|||||||
@@ -62,8 +62,21 @@ void Label::size(vec2 sizenew) {
|
|||||||
UINode::size(vec2(UINode::size().x, sizenew.y));
|
UINode::size(vec2(UINode::size().x, sizenew.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ================================= Image ====================================
|
||||||
|
Image::Image(string texture, vec2 size) : UINode(vec2(), size), texture(texture) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::draw(Batch2D* batch, Assets* assets) {
|
||||||
|
vec2 coord = calcCoord();
|
||||||
|
batch->texture(assets->getTexture(texture));
|
||||||
|
batch->color = color_;
|
||||||
|
batch->rect(coord.x, coord.y, size_.x, size_.y, 0, 0, 0, UVRegion(), false, true, color_);
|
||||||
|
}
|
||||||
|
|
||||||
// ================================= Button ===================================
|
// ================================= Button ===================================
|
||||||
Button::Button(shared_ptr<UINode> content, glm::vec4 padding) : Panel(vec2(32,32), padding, 0) {
|
Button::Button(shared_ptr<UINode> content, glm::vec4 padding)
|
||||||
|
: Panel(content->size()+vec2(padding[0]+padding[2]+content->margin()[0]+content->margin()[2],
|
||||||
|
padding[1]+padding[3]+content->margin()[1]+content->margin()[3]), padding, 0) {
|
||||||
add(content);
|
add(content);
|
||||||
scrollable(false);
|
scrollable(false);
|
||||||
}
|
}
|
||||||
@@ -100,6 +113,11 @@ Button* Button::textSupplier(wstringsupplier supplier) {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Button::setHoverColor(glm::vec4 color) {
|
||||||
|
hoverColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
void Button::drawBackground(Batch2D* batch, Assets* assets) {
|
void Button::drawBackground(Batch2D* batch, Assets* assets) {
|
||||||
vec2 coord = calcCoord();
|
vec2 coord = calcCoord();
|
||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
@@ -133,6 +151,35 @@ void Button::textAlign(Align align) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================== RichButton ==================================
|
||||||
|
RichButton::RichButton(vec2 size) : Container(vec2(), size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichButton::mouseRelease(GUI* gui, int x, int y) {
|
||||||
|
UINode::mouseRelease(gui, x, y);
|
||||||
|
if (isInside(vec2(x, y))) {
|
||||||
|
for (auto callback : actions) {
|
||||||
|
callback(gui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RichButton* RichButton::listenAction(onaction action) {
|
||||||
|
actions.push_back(action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichButton::setHoverColor(glm::vec4 color) {
|
||||||
|
hoverColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichButton::drawBackground(Batch2D* batch, Assets* assets) {
|
||||||
|
vec2 coord = calcCoord();
|
||||||
|
batch->texture(nullptr);
|
||||||
|
batch->color = (ispressed() ? pressedColor : (hover_ ? hoverColor : color_));
|
||||||
|
batch->rect(coord.x, coord.y, size_.x, size_.y);
|
||||||
|
}
|
||||||
|
|
||||||
// ================================ TextBox ===================================
|
// ================================ TextBox ===================================
|
||||||
TextBox::TextBox(wstring placeholder, vec4 padding)
|
TextBox::TextBox(wstring placeholder, vec4 padding)
|
||||||
: Panel(vec2(200,32), padding, 0, false),
|
: Panel(vec2(200,32), padding, 0, false),
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ namespace gui {
|
|||||||
virtual void size(glm::vec2 size) override;
|
virtual void size(glm::vec2 size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Image : public UINode {
|
||||||
|
protected:
|
||||||
|
std::string texture;
|
||||||
|
public:
|
||||||
|
Image(std::string texture, glm::vec2 size);
|
||||||
|
|
||||||
|
virtual void draw(Batch2D* batch, Assets* assets) override;
|
||||||
|
};
|
||||||
|
|
||||||
class Button : public Panel {
|
class Button : public Panel {
|
||||||
protected:
|
protected:
|
||||||
glm::vec4 hoverColor {0.05f, 0.1f, 0.15f, 0.75f};
|
glm::vec4 hoverColor {0.05f, 0.1f, 0.15f, 0.75f};
|
||||||
@@ -55,7 +64,7 @@ namespace gui {
|
|||||||
glm::vec4 padding=glm::vec4(2.0f),
|
glm::vec4 padding=glm::vec4(2.0f),
|
||||||
glm::vec4 margin=glm::vec4(1.0f));
|
glm::vec4 margin=glm::vec4(1.0f));
|
||||||
|
|
||||||
virtual void drawBackground(Batch2D* batch, Assets* assets);
|
virtual void drawBackground(Batch2D* batch, Assets* assets) override;
|
||||||
|
|
||||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||||
|
|
||||||
@@ -68,6 +77,24 @@ namespace gui {
|
|||||||
virtual std::wstring text() const;
|
virtual std::wstring text() const;
|
||||||
|
|
||||||
virtual Button* textSupplier(wstringsupplier supplier);
|
virtual Button* textSupplier(wstringsupplier supplier);
|
||||||
|
|
||||||
|
virtual void setHoverColor(glm::vec4 color);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RichButton : public Container {
|
||||||
|
protected:
|
||||||
|
glm::vec4 hoverColor {0.05f, 0.1f, 0.15f, 0.75f};
|
||||||
|
glm::vec4 pressedColor {0.0f, 0.0f, 0.0f, 0.95f};
|
||||||
|
std::vector<onaction> actions;
|
||||||
|
public:
|
||||||
|
RichButton(glm::vec2 size);
|
||||||
|
|
||||||
|
virtual void drawBackground(Batch2D* batch, Assets* assets) override;
|
||||||
|
|
||||||
|
virtual void mouseRelease(GUI*, int x, int y) override;
|
||||||
|
virtual RichButton* listenAction(onaction action);
|
||||||
|
|
||||||
|
virtual void setHoverColor(glm::vec4 color);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextBox : public Panel {
|
class TextBox : public Panel {
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ Container::Container(vec2 coord, vec2 size) : UINode(coord, size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<UINode> Container::getAt(vec2 pos, shared_ptr<UINode> self) {
|
shared_ptr<UINode> Container::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||||
|
if (!interactive) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
if (!isInside(pos)) return nullptr;
|
if (!isInside(pos)) return nullptr;
|
||||||
for (auto node : nodes) {
|
for (auto node : nodes) {
|
||||||
if (!node->visible())
|
if (!node->visible())
|
||||||
@@ -58,7 +61,7 @@ void Container::act(float delta) {
|
|||||||
void Container::scrolled(int value) {
|
void Container::scrolled(int value) {
|
||||||
int diff = (actualLength-size().y);
|
int diff = (actualLength-size().y);
|
||||||
if (diff > 0 && scrollable_) {
|
if (diff > 0 && scrollable_) {
|
||||||
scroll += value * 20;
|
scroll += value * 40;
|
||||||
if (scroll > 0)
|
if (scroll > 0)
|
||||||
scroll = 0;
|
scroll = 0;
|
||||||
if (-scroll > diff) {
|
if (-scroll > diff) {
|
||||||
@@ -98,6 +101,11 @@ void Container::add(UINode* node) {
|
|||||||
add(shared_ptr<UINode>(node));
|
add(shared_ptr<UINode>(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Container::add(shared_ptr<UINode> node, glm::vec2 coord) {
|
||||||
|
node->setCoord(coord);
|
||||||
|
add(node);
|
||||||
|
}
|
||||||
|
|
||||||
void Container::remove(shared_ptr<UINode> selected) {
|
void Container::remove(shared_ptr<UINode> selected) {
|
||||||
selected->setParent(nullptr);
|
selected->setParent(nullptr);
|
||||||
nodes.erase(std::remove_if(nodes.begin(), nodes.end(),
|
nodes.erase(std::remove_if(nodes.begin(), nodes.end(),
|
||||||
@@ -190,15 +198,12 @@ void Panel::refresh() {
|
|||||||
node->refresh();
|
node->refresh();
|
||||||
maxh = fmax(maxh, y+margin.y+node->size().y+margin.w+padding.w);
|
maxh = fmax(maxh, y+margin.y+node->size().y+margin.w+padding.w);
|
||||||
}
|
}
|
||||||
bool increased = maxh > size.y;
|
|
||||||
if (resizing_) {
|
if (resizing_) {
|
||||||
if (maxLength_)
|
if (maxLength_)
|
||||||
this->size(vec2(glm::min(maxLength_, (int)(x+padding.z)), size.y));
|
this->size(vec2(glm::min(maxLength_, (int)(x+padding.z)), size.y));
|
||||||
else
|
else
|
||||||
this->size(vec2(x+padding.z, size.y));
|
this->size(vec2(x+padding.z, size.y));
|
||||||
}
|
}
|
||||||
if (increased)
|
|
||||||
refresh();
|
|
||||||
actualLength = size.y;
|
actualLength = size.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace gui {
|
|||||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||||
virtual void add(std::shared_ptr<UINode> node);
|
virtual void add(std::shared_ptr<UINode> node);
|
||||||
virtual void add(UINode* node);
|
virtual void add(UINode* node);
|
||||||
|
virtual void add(std::shared_ptr<UINode> node, glm::vec2 coord);
|
||||||
virtual void remove(std::shared_ptr<UINode> node);
|
virtual void remove(std::shared_ptr<UINode> node);
|
||||||
virtual void scrolled(int value) override;
|
virtual void scrolled(int value) override;
|
||||||
virtual void scrollable(bool flag);
|
virtual void scrollable(bool flag);
|
||||||
|
|||||||
+184
-23
@@ -44,6 +44,7 @@
|
|||||||
#include "../engine.h"
|
#include "../engine.h"
|
||||||
#include "../core_defs.h"
|
#include "../core_defs.h"
|
||||||
#include "../items/ItemDef.h"
|
#include "../items/ItemDef.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
|
|
||||||
using glm::vec2;
|
using glm::vec2;
|
||||||
using glm::vec3;
|
using glm::vec3;
|
||||||
@@ -163,26 +164,142 @@ void HudRenderer::createDebugPanel(Engine* engine) {
|
|||||||
panel->refresh();
|
panel->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<InventoryView> HudRenderer::createContentAccess() {
|
||||||
|
auto level = frontend->getLevel();
|
||||||
|
auto content = level->content;
|
||||||
|
auto indices = content->getIndices();
|
||||||
|
auto player = level->player;
|
||||||
|
auto inventory = player->getInventory();
|
||||||
|
|
||||||
|
int itemsCount = indices->countItemDefs();
|
||||||
|
auto accessInventory = std::make_shared<Inventory>(itemsCount);
|
||||||
|
for (int id = 1; id < itemsCount; id++) {
|
||||||
|
accessInventory->getSlot(id-1).set(ItemStack(id, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int slotSize = InventoryView::SLOT_SIZE;
|
||||||
|
const int interval = InventoryView::SLOT_INTERVAL;
|
||||||
|
int padding = 8;
|
||||||
|
|
||||||
|
int columns = 8;
|
||||||
|
int rows = ceildiv(itemsCount-1, columns);
|
||||||
|
uint cawidth = columns * (slotSize + interval) - interval + padding;
|
||||||
|
uint caheight = rows * (slotSize + interval) - interval + padding*2;
|
||||||
|
auto layout = std::make_unique<InventoryLayout>(glm::vec2(cawidth, caheight));
|
||||||
|
for (int i = 0; i < itemsCount-1; i++) {
|
||||||
|
int row = i / columns;
|
||||||
|
int col = i % columns;
|
||||||
|
glm::vec2 position (
|
||||||
|
col * slotSize + (col-1) * interval + padding,
|
||||||
|
row * slotSize + (row-1) * interval + padding
|
||||||
|
);
|
||||||
|
layout->add(SlotLayout(position, false, true,
|
||||||
|
[=](ItemStack& item) {
|
||||||
|
auto copy = ItemStack(item);
|
||||||
|
inventory->move(copy, indices);
|
||||||
|
},
|
||||||
|
[=](ItemStack& item, ItemStack& grabbed) {
|
||||||
|
inventory->getSlot(player->getChosenSlot()).set(item);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
auto contentAccess = std::make_shared<InventoryView>(
|
||||||
|
content,
|
||||||
|
frontend,
|
||||||
|
interaction.get(),
|
||||||
|
accessInventory,
|
||||||
|
std::move(layout)
|
||||||
|
);
|
||||||
|
contentAccess->build();
|
||||||
|
return contentAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<InventoryView> HudRenderer::createHotbar() {
|
||||||
|
auto level = frontend->getLevel();
|
||||||
|
auto player = level->player;
|
||||||
|
auto inventory = player->getInventory();
|
||||||
|
auto content = level->content;
|
||||||
|
|
||||||
|
const int slotSize = InventoryView::SLOT_SIZE;
|
||||||
|
const int interval = InventoryView::SLOT_INTERVAL;
|
||||||
|
|
||||||
|
int padding = 4;
|
||||||
|
uint width = 10 * (slotSize + interval) - interval + padding*2;
|
||||||
|
uint height = slotSize + padding * 2;
|
||||||
|
auto layout = std::make_unique<InventoryLayout>(glm::vec2(width, height));
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
glm::vec2 position (i * (slotSize + interval) + padding, padding);
|
||||||
|
layout->add(SlotLayout(position, false, false, nullptr, nullptr));
|
||||||
|
}
|
||||||
|
layout->setOrigin(glm::vec2(width / 2, 0));
|
||||||
|
auto view = std::make_shared<InventoryView>(
|
||||||
|
content,
|
||||||
|
frontend,
|
||||||
|
interaction.get(),
|
||||||
|
inventory,
|
||||||
|
std::move(layout)
|
||||||
|
);
|
||||||
|
view->build();
|
||||||
|
view->setInteractive(false);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<InventoryView> HudRenderer::createInventory() {
|
||||||
|
auto level = frontend->getLevel();
|
||||||
|
auto player = level->player;
|
||||||
|
auto inventory = player->getInventory();
|
||||||
|
auto content = level->content;
|
||||||
|
|
||||||
|
SlotLayout slotLayout(glm::vec2(), true, false, [=](ItemStack& stack) {
|
||||||
|
stack.clear();
|
||||||
|
}, nullptr);
|
||||||
|
|
||||||
|
int columns = 10;
|
||||||
|
int rows = ceildiv(inventory->size(), columns);
|
||||||
|
int padding = 4;
|
||||||
|
|
||||||
|
InventoryBuilder builder;
|
||||||
|
builder.addGrid(columns, rows, glm::vec2(), padding, slotLayout);
|
||||||
|
auto layout = builder.build();
|
||||||
|
|
||||||
|
auto view = std::make_shared<InventoryView>(
|
||||||
|
content,
|
||||||
|
frontend,
|
||||||
|
interaction.get(),
|
||||||
|
inventory,
|
||||||
|
std::move(layout)
|
||||||
|
);
|
||||||
|
view->build();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
HudRenderer::HudRenderer(Engine* engine, LevelFrontend* frontend)
|
HudRenderer::HudRenderer(Engine* engine, LevelFrontend* frontend)
|
||||||
: assets(engine->getAssets()),
|
: assets(engine->getAssets()),
|
||||||
gui(engine->getGUI()),
|
gui(engine->getGUI()),
|
||||||
frontend(frontend) {
|
frontend(frontend)
|
||||||
|
{
|
||||||
auto level = frontend->getLevel();
|
|
||||||
auto menu = gui->getMenu();
|
auto menu = gui->getMenu();
|
||||||
auto content = level->content;
|
|
||||||
auto indices = content->getIndices();
|
|
||||||
|
|
||||||
std::vector<itemid_t> items;
|
interaction = std::make_unique<InventoryInteraction>();
|
||||||
for (itemid_t id = 1; id < indices->countItemDefs(); id++) {
|
grabbedItemView = std::make_shared<SlotView>(
|
||||||
items.push_back(id);
|
interaction->getGrabbedItem(),
|
||||||
}
|
frontend,
|
||||||
contentAccess.reset(new InventoryView(8, content, frontend, items));
|
interaction.get(),
|
||||||
contentAccess->setSlotConsumer([=](blockid_t id) {
|
frontend->getLevel()->content,
|
||||||
level->player->setChosenItem(id);
|
SlotLayout(glm::vec2(), false, false, nullptr, nullptr)
|
||||||
});
|
);
|
||||||
|
grabbedItemView->color(glm::vec4());
|
||||||
|
grabbedItemView->setInteractive(false);
|
||||||
|
|
||||||
hotbarView.reset(new InventoryView(1, content, frontend, std::vector<itemid_t> {0}));
|
contentAccess = createContentAccess();
|
||||||
|
contentAccessPanel = std::make_shared<Panel>(
|
||||||
|
contentAccess->size(), vec4(0.0f), 0.0f
|
||||||
|
);
|
||||||
|
contentAccessPanel->color(glm::vec4());
|
||||||
|
contentAccessPanel->add(contentAccess);
|
||||||
|
contentAccessPanel->scrollable(true);
|
||||||
|
|
||||||
|
hotbarView = createHotbar();
|
||||||
|
inventoryView = createInventory();
|
||||||
|
|
||||||
uicamera = new Camera(vec3(), 1);
|
uicamera = new Camera(vec3(), 1);
|
||||||
uicamera->perspective = false;
|
uicamera->perspective = false;
|
||||||
@@ -191,10 +308,18 @@ HudRenderer::HudRenderer(Engine* engine, LevelFrontend* frontend)
|
|||||||
createDebugPanel(engine);
|
createDebugPanel(engine);
|
||||||
menu->reset();
|
menu->reset();
|
||||||
|
|
||||||
gui->add(this->debugPanel);
|
gui->add(debugPanel);
|
||||||
|
gui->add(contentAccessPanel);
|
||||||
|
gui->add(hotbarView);
|
||||||
|
gui->add(inventoryView);
|
||||||
|
gui->add(grabbedItemView);
|
||||||
}
|
}
|
||||||
|
|
||||||
HudRenderer::~HudRenderer() {
|
HudRenderer::~HudRenderer() {
|
||||||
|
gui->remove(grabbedItemView);
|
||||||
|
gui->remove(inventoryView);
|
||||||
|
gui->remove(hotbarView);
|
||||||
|
gui->remove(contentAccessPanel);
|
||||||
gui->remove(debugPanel);
|
gui->remove(debugPanel);
|
||||||
delete uicamera;
|
delete uicamera;
|
||||||
}
|
}
|
||||||
@@ -206,7 +331,12 @@ void HudRenderer::drawDebug(int fps){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HudRenderer::update(bool visible) {
|
void HudRenderer::update(bool visible) {
|
||||||
|
auto level = frontend->getLevel();
|
||||||
|
auto player = level->player;
|
||||||
auto menu = gui->getMenu();
|
auto menu = gui->getMenu();
|
||||||
|
|
||||||
|
menu->visible(pause);
|
||||||
|
|
||||||
if (!visible && inventoryOpen) {
|
if (!visible && inventoryOpen) {
|
||||||
inventoryOpen = false;
|
inventoryOpen = false;
|
||||||
}
|
}
|
||||||
@@ -232,13 +362,35 @@ void HudRenderer::update(bool visible) {
|
|||||||
if ((pause || inventoryOpen) == Events::_cursor_locked) {
|
if ((pause || inventoryOpen) == Events::_cursor_locked) {
|
||||||
Events::toggleCursor();
|
Events::toggleCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec2 invSize = contentAccessPanel->size();
|
||||||
|
inventoryView->visible(inventoryOpen);
|
||||||
|
contentAccessPanel->visible(inventoryOpen);
|
||||||
|
contentAccessPanel->size(glm::vec2(invSize.x, Window::height));
|
||||||
|
|
||||||
|
for (int i = keycode::NUM_1; i <= keycode::NUM_9; i++) {
|
||||||
|
if (Events::jpressed(i)) {
|
||||||
|
player->setChosenSlot(i - keycode::NUM_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Events::jpressed(keycode::NUM_0)) {
|
||||||
|
player->setChosenSlot(9);
|
||||||
|
}
|
||||||
|
if (!inventoryOpen && Events::scroll) {
|
||||||
|
int slot = player->getChosenSlot();
|
||||||
|
slot = (slot + Events::scroll) % 10;
|
||||||
|
if (slot < 0) {
|
||||||
|
slot += 10;
|
||||||
|
}
|
||||||
|
player->setChosenSlot(slot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HudRenderer::drawOverlay(const GfxContext& ctx) {
|
void HudRenderer::drawOverlay(const GfxContext& ctx) {
|
||||||
if (pause) {
|
if (pause) {
|
||||||
Shader* uishader = assets->getShader("ui");
|
Shader* uishader = assets->getShader("ui");
|
||||||
uishader->use();
|
uishader->use();
|
||||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||||
|
|
||||||
const Viewport& viewport = ctx.getViewport();
|
const Viewport& viewport = ctx.getViewport();
|
||||||
const uint width = viewport.getWidth();
|
const uint width = viewport.getWidth();
|
||||||
@@ -271,12 +423,11 @@ void HudRenderer::draw(const GfxContext& ctx){
|
|||||||
|
|
||||||
Shader* uishader = assets->getShader("ui");
|
Shader* uishader = assets->getShader("ui");
|
||||||
uishader->use();
|
uishader->use();
|
||||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||||
|
|
||||||
// Draw selected item preview
|
// Draw selected item preview
|
||||||
hotbarView->setPosition(width-60, height-60);
|
hotbarView->setCoord(glm::vec2(width/2, height-65));
|
||||||
hotbarView->setItems({player->getChosenItem()});
|
hotbarView->setSelected(player->getChosenSlot());
|
||||||
hotbarView->actAndDraw(&ctx);
|
|
||||||
|
|
||||||
// Crosshair
|
// Crosshair
|
||||||
batch->begin();
|
batch->begin();
|
||||||
@@ -289,10 +440,20 @@ void HudRenderer::draw(const GfxContext& ctx){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inventoryOpen) {
|
if (inventoryOpen) {
|
||||||
// draw content access panel (all available items)
|
auto caLayout = contentAccess->getLayout();
|
||||||
contentAccess->setPosition(viewport.getWidth()-contentAccess->getWidth(), 0);
|
auto invLayout = inventoryView->getLayout();
|
||||||
contentAccess->actAndDraw(&ctx);
|
float caWidth = caLayout->getSize().x;
|
||||||
|
glm::vec2 invSize = invLayout->getSize();
|
||||||
|
|
||||||
|
float width = viewport.getWidth();
|
||||||
|
|
||||||
|
inventoryView->setCoord(glm::vec2(
|
||||||
|
glm::min(width/2-invSize.x/2, width-caWidth-10-invSize.x),
|
||||||
|
height/2-invSize.y/2
|
||||||
|
));
|
||||||
|
contentAccessPanel->setCoord(glm::vec2(width-caWidth, 0));
|
||||||
}
|
}
|
||||||
|
grabbedItemView->setCoord(glm::vec2(Events::cursor));
|
||||||
batch->render();
|
batch->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-2
@@ -15,12 +15,15 @@ class Assets;
|
|||||||
class Player;
|
class Player;
|
||||||
class Level;
|
class Level;
|
||||||
class Engine;
|
class Engine;
|
||||||
|
class SlotView;
|
||||||
class InventoryView;
|
class InventoryView;
|
||||||
class LevelFrontend;
|
class LevelFrontend;
|
||||||
|
class InventoryInteraction;
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class GUI;
|
class GUI;
|
||||||
class UINode;
|
class UINode;
|
||||||
|
class Panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
class HudRenderer {
|
class HudRenderer {
|
||||||
@@ -34,13 +37,21 @@ class HudRenderer {
|
|||||||
bool inventoryOpen = false;
|
bool inventoryOpen = false;
|
||||||
bool pause = false;
|
bool pause = false;
|
||||||
|
|
||||||
std::unique_ptr<InventoryView> contentAccess;
|
std::shared_ptr<gui::Panel> contentAccessPanel;
|
||||||
std::unique_ptr<InventoryView> hotbarView;
|
std::shared_ptr<InventoryView> contentAccess;
|
||||||
|
std::shared_ptr<InventoryView> hotbarView;
|
||||||
|
std::shared_ptr<InventoryView> inventoryView;
|
||||||
std::shared_ptr<gui::UINode> debugPanel;
|
std::shared_ptr<gui::UINode> debugPanel;
|
||||||
|
std::unique_ptr<InventoryInteraction> interaction;
|
||||||
|
std::shared_ptr<SlotView> grabbedItemView;
|
||||||
gui::GUI* gui;
|
gui::GUI* gui;
|
||||||
LevelFrontend* frontend;
|
LevelFrontend* frontend;
|
||||||
|
|
||||||
void createDebugPanel(Engine* engine);
|
void createDebugPanel(Engine* engine);
|
||||||
|
|
||||||
|
std::shared_ptr<InventoryView> createContentAccess();
|
||||||
|
std::shared_ptr<InventoryView> createHotbar();
|
||||||
|
std::shared_ptr<InventoryView> createInventory();
|
||||||
public:
|
public:
|
||||||
HudRenderer(Engine* engine, LevelFrontend* frontend);
|
HudRenderer(Engine* engine, LevelFrontend* frontend);
|
||||||
~HudRenderer();
|
~HudRenderer();
|
||||||
|
|||||||
+30
-3
@@ -195,13 +195,40 @@ Panel* create_worlds_panel(Engine* engine) {
|
|||||||
if (!entry.is_directory()) {
|
if (!entry.is_directory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto name = entry.path().filename().u8string();
|
auto folder = entry.path();
|
||||||
auto btn = new Button(util::str2wstr_utf8(name),
|
auto name = folder.filename().u8string();
|
||||||
vec4(10.0f, 8.0f, 10.0f, 8.0f));
|
auto namews = util::str2wstr_utf8(name);
|
||||||
|
|
||||||
|
auto btn = std::make_shared<RichButton>(vec2(390, 46));
|
||||||
btn->color(vec4(1.0f, 1.0f, 1.0f, 0.1f));
|
btn->color(vec4(1.0f, 1.0f, 1.0f, 0.1f));
|
||||||
|
btn->setHoverColor(vec4(1.0f, 1.0f, 1.0f, 0.17f));
|
||||||
|
|
||||||
|
auto label = std::make_shared<Label>(namews);
|
||||||
|
label->setInteractive(false);
|
||||||
|
btn->add(label, vec2(8, 8));
|
||||||
btn->listenAction([=](GUI*) {
|
btn->listenAction([=](GUI*) {
|
||||||
open_world(name, engine);
|
open_world(name, engine);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto image = std::make_shared<Image>("gui/delete_icon", vec2(32, 32));
|
||||||
|
image->color(vec4(1, 1, 1, 0.5f));
|
||||||
|
|
||||||
|
auto delbtn = std::make_shared<Button>(image, vec4(2));
|
||||||
|
delbtn->color(vec4(0.0f));
|
||||||
|
delbtn->setHoverColor(vec4(1.0f, 1.0f, 1.0f, 0.17f));
|
||||||
|
|
||||||
|
btn->add(delbtn, vec2(330, 3));
|
||||||
|
|
||||||
|
delbtn->listenAction([=](GUI* gui) {
|
||||||
|
guiutil::confirm(gui, langs::get(L"delete-confirm", L"world")+
|
||||||
|
L" ("+util::str2wstr_utf8(folder.u8string())+L")", [=]()
|
||||||
|
{
|
||||||
|
std::cout << "deleting " << folder.u8string() << std::endl;
|
||||||
|
fs::remove_all(folder);
|
||||||
|
menus::refresh_menus(engine, gui->getMenu());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
panel->add(btn);
|
panel->add(btn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void MenuScreen::draw(float delta) {
|
|||||||
uint height = Window::height;
|
uint height = Window::height;
|
||||||
|
|
||||||
batch->begin();
|
batch->begin();
|
||||||
batch->texture(engine->getAssets()->getTexture("menubg"));
|
batch->texture(engine->getAssets()->getTexture("gui/menubg"));
|
||||||
batch->rect(0, 0,
|
batch->rect(0, 0,
|
||||||
width, height, 0, 0, 0,
|
width, height, 0, 0, 0,
|
||||||
UVRegion(0, 0, width/64, height/64),
|
UVRegion(0, 0, width/64, height/64),
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#include "Inventory.h"
|
||||||
|
|
||||||
|
Inventory::Inventory(size_t size) : slots(size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack& Inventory::getSlot(size_t index) {
|
||||||
|
return slots[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Inventory::findEmptySlot(size_t begin, size_t end) const {
|
||||||
|
end = std::min(slots.size(), end);
|
||||||
|
for (size_t i = begin; i < end; i++) {
|
||||||
|
if (slots[i].isEmpty()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Inventory::findSlotByItem(itemid_t id, size_t begin, size_t end) {
|
||||||
|
end = std::min(slots.size(), end);
|
||||||
|
for (size_t i = begin; i < end; i++) {
|
||||||
|
if (slots[i].getItemId() == id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::move(
|
||||||
|
ItemStack& item,
|
||||||
|
const ContentIndices* indices,
|
||||||
|
size_t begin,
|
||||||
|
size_t end)
|
||||||
|
{
|
||||||
|
end = std::min(slots.size(), end);
|
||||||
|
for (size_t i = begin; i < end && !item.isEmpty(); i++) {
|
||||||
|
ItemStack& slot = slots[i];
|
||||||
|
if (slot.accepts(item)) {
|
||||||
|
slot.move(item, indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::read(const dynamic::Map* src) {
|
||||||
|
auto slotsarr = src->list("slots");
|
||||||
|
size_t slotscount = std::min(slotsarr->size(), slots.size());
|
||||||
|
for (size_t i = 0; i < slotscount; i++) {
|
||||||
|
auto item = slotsarr->map(i);
|
||||||
|
itemid_t id = item->getInt("id", ITEM_EMPTY);
|
||||||
|
itemcount_t count = item->getInt("count", 0);
|
||||||
|
auto& slot = slots[i];
|
||||||
|
slot.set(ItemStack(id, count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<dynamic::Map> Inventory::write() const {
|
||||||
|
auto map = std::make_unique<dynamic::Map>();
|
||||||
|
auto& slotsarr = map->putList("slots");
|
||||||
|
for (size_t i = 0; i < slots.size(); i++) {
|
||||||
|
auto& item = slots[i];
|
||||||
|
itemid_t id = item.getItemId();
|
||||||
|
itemcount_t count = item.getCount();
|
||||||
|
|
||||||
|
auto& slotmap = slotsarr.putMap();
|
||||||
|
slotmap.put("id", id);
|
||||||
|
if (count) {
|
||||||
|
slotmap.put("count", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t Inventory::npos = -1;
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef ITEMS_INVENTORY_H_
|
||||||
|
#define ITEMS_INVENTORY_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "ItemStack.h"
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../data/dynamic.h"
|
||||||
|
|
||||||
|
class ContentIndices;
|
||||||
|
|
||||||
|
class Inventory {
|
||||||
|
std::vector<ItemStack> slots;
|
||||||
|
public:
|
||||||
|
Inventory(size_t size);
|
||||||
|
|
||||||
|
ItemStack& getSlot(size_t index);
|
||||||
|
size_t findEmptySlot(size_t begin=0, size_t end=-1) const;
|
||||||
|
size_t findSlotByItem(itemid_t id, size_t begin=0, size_t end=-1);
|
||||||
|
|
||||||
|
inline size_t size() const {
|
||||||
|
return slots.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(
|
||||||
|
ItemStack& item,
|
||||||
|
const ContentIndices* indices,
|
||||||
|
size_t begin=0,
|
||||||
|
size_t end=-1);
|
||||||
|
|
||||||
|
/* deserializing inventory */
|
||||||
|
void read(const dynamic::Map* src);
|
||||||
|
/* serializing inventory */
|
||||||
|
std::unique_ptr<dynamic::Map> write() const;
|
||||||
|
|
||||||
|
static const size_t npos;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ITEMS_INVENTORY_H_
|
||||||
@@ -22,6 +22,7 @@ class ItemDef {
|
|||||||
public:
|
public:
|
||||||
std::string const name;
|
std::string const name;
|
||||||
|
|
||||||
|
itemcount_t stackSize = 64;
|
||||||
bool generated = false;
|
bool generated = false;
|
||||||
uint8_t emission[4] {0, 0, 0, 0};
|
uint8_t emission[4] {0, 0, 0, 0};
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ public:
|
|||||||
std::string icon = "blocks:notfound";
|
std::string icon = "blocks:notfound";
|
||||||
|
|
||||||
std::string placingBlock = "core:air";
|
std::string placingBlock = "core:air";
|
||||||
|
std::string scriptName = name.substr(name.find(':')+1);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
itemid_t id;
|
itemid_t id;
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include "ItemStack.h"
|
||||||
|
|
||||||
|
#include "ItemDef.h"
|
||||||
|
#include "../content/Content.h"
|
||||||
|
|
||||||
|
ItemStack::ItemStack() : item(ITEM_EMPTY), count(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack::ItemStack(itemid_t item, itemcount_t count) : item(item), count(count) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemStack::set(const ItemStack& item) {
|
||||||
|
this->item = item.item;
|
||||||
|
this->count = item.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemStack::accepts(const ItemStack& other) const {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return item == other.getItemId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemStack::move(ItemStack& item, const ContentIndices* indices) {
|
||||||
|
auto def = indices->getItemDef(item.getItemId());
|
||||||
|
int count = std::min(item.count, def->stackSize-this->count);
|
||||||
|
if (isEmpty()) {
|
||||||
|
set(ItemStack(item.getItemId(), count));
|
||||||
|
} else {
|
||||||
|
setCount(this->count + count);
|
||||||
|
}
|
||||||
|
item.setCount(item.count-count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemStack::setCount(itemcount_t count) {
|
||||||
|
this->count = count;
|
||||||
|
if (count == 0) {
|
||||||
|
item = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef ITEMS_ITEM_STACK_H_
|
||||||
|
#define ITEMS_ITEM_STACK_H_
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../constants.h"
|
||||||
|
|
||||||
|
class ContentIndices;
|
||||||
|
|
||||||
|
class ItemStack {
|
||||||
|
itemid_t item;
|
||||||
|
itemcount_t count;
|
||||||
|
public:
|
||||||
|
ItemStack();
|
||||||
|
|
||||||
|
ItemStack(itemid_t item, itemcount_t count);
|
||||||
|
|
||||||
|
void set(const ItemStack& item);
|
||||||
|
void setCount(itemcount_t count);
|
||||||
|
|
||||||
|
bool accepts(const ItemStack& item) const;
|
||||||
|
void move(ItemStack& item, const ContentIndices* indices);
|
||||||
|
|
||||||
|
inline void clear() {
|
||||||
|
set(ItemStack(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isEmpty() const {
|
||||||
|
return item == ITEM_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline itemid_t getItemId() const {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline itemcount_t getCount() const {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ITEMS_ITEM_STACK_H_
|
||||||
@@ -7,12 +7,11 @@
|
|||||||
#include "../voxels/voxel.h"
|
#include "../voxels/voxel.h"
|
||||||
#include "../voxels/Block.h"
|
#include "../voxels/Block.h"
|
||||||
#include "../constants.h"
|
#include "../constants.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using std::shared_ptr;
|
|
||||||
|
|
||||||
Lighting::Lighting(const Content* content, Chunks* chunks)
|
Lighting::Lighting(const Content* content, Chunks* chunks)
|
||||||
: content(content), chunks(chunks) {
|
: content(content), chunks(chunks) {
|
||||||
auto indices = content->getIndices();
|
auto indices = content->getIndices();
|
||||||
@@ -31,7 +30,7 @@ Lighting::~Lighting(){
|
|||||||
|
|
||||||
void Lighting::clear(){
|
void Lighting::clear(){
|
||||||
for (unsigned int index = 0; index < chunks->volume; index++){
|
for (unsigned int index = 0; index < chunks->volume; index++){
|
||||||
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
auto chunk = chunks->chunks[index];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
Lightmap* lightmap = chunk->lightmap;
|
Lightmap* lightmap = chunk->lightmap;
|
||||||
@@ -98,10 +97,10 @@ void Lighting::onChunkLoaded(int cx, int cz){
|
|||||||
const Block* const* blockDefs = content->getIndices()->getBlockDefs();
|
const Block* const* blockDefs = content->getIndices()->getBlockDefs();
|
||||||
const Chunk* chunk = chunks->getChunk(cx, cz);
|
const Chunk* chunk = chunks->getChunk(cx, cz);
|
||||||
|
|
||||||
for (unsigned int y = 0; y < CHUNK_H; y++){
|
for (uint y = 0; y < CHUNK_H; y++){
|
||||||
for (unsigned int z = 0; z < CHUNK_D; z++){
|
for (uint z = 0; z < CHUNK_D; z++){
|
||||||
for (unsigned int x = 0; x < CHUNK_W; x++){
|
for (uint x = 0; x < CHUNK_W; x++){
|
||||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
voxel& vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||||
const Block* block = blockDefs[vox.id];
|
const Block* block = blockDefs[vox.id];
|
||||||
int gx = x + cx * CHUNK_W;
|
int gx = x + cx * CHUNK_W;
|
||||||
int gz = z + cz * CHUNK_D;
|
int gz = z + cz * CHUNK_D;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "../content/Content.h"
|
#include "../content/Content.h"
|
||||||
#include "../lighting/Lighting.h"
|
#include "../lighting/Lighting.h"
|
||||||
#include "../util/timeutil.h"
|
#include "../util/timeutil.h"
|
||||||
|
#include "../maths/fastmaths.h"
|
||||||
|
|
||||||
#include "scripting/scripting.h"
|
#include "scripting/scripting.h"
|
||||||
|
|
||||||
@@ -89,7 +90,10 @@ void BlocksController::randomTick(int tickid, int parts) {
|
|||||||
// timeutil::ScopeLogTimer timer(5000+tickid);
|
// timeutil::ScopeLogTimer timer(5000+tickid);
|
||||||
const int w = chunks->w;
|
const int w = chunks->w;
|
||||||
const int d = chunks->d;
|
const int d = chunks->d;
|
||||||
|
int segments = 4;
|
||||||
|
int segheight = CHUNK_H / segments;
|
||||||
auto indices = level->content->getIndices();
|
auto indices = level->content->getIndices();
|
||||||
|
|
||||||
for (uint z = padding; z < d-padding; z++){
|
for (uint z = padding; z < d-padding; z++){
|
||||||
for (uint x = padding; x < w-padding; x++){
|
for (uint x = padding; x < w-padding; x++){
|
||||||
int index = z * w + x;
|
int index = z * w + x;
|
||||||
@@ -98,13 +102,11 @@ void BlocksController::randomTick(int tickid, int parts) {
|
|||||||
std::shared_ptr<Chunk> chunk = chunks->chunks[index];
|
std::shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||||
if (chunk == nullptr || !chunk->isLighted())
|
if (chunk == nullptr || !chunk->isLighted())
|
||||||
continue;
|
continue;
|
||||||
int segments = 4;
|
|
||||||
int segheight = CHUNK_H / segments;
|
|
||||||
for (int s = 0; s < segments; s++) {
|
for (int s = 0; s < segments; s++) {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
int bx = rand() % CHUNK_W;
|
int bx = fastmaths::rand() % CHUNK_W;
|
||||||
int by = rand() % segheight + s * segheight;
|
int by = fastmaths::rand() % segheight + s * segheight;
|
||||||
int bz = rand() % CHUNK_D;
|
int bz = fastmaths::rand() % CHUNK_D;
|
||||||
const voxel& vox = chunk->voxels[(by * CHUNK_D + bz) * CHUNK_W + bx];
|
const voxel& vox = chunk->voxels[(by * CHUNK_D + bz) * CHUNK_W + bx];
|
||||||
Block* block = indices->getBlockDef(vox.id);
|
Block* block = indices->getBlockDef(vox.id);
|
||||||
if (block->rt.funcsset.randupdate) {
|
if (block->rt.funcsset.randupdate) {
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ void ChunksController::update(int64_t maxDuration) {
|
|||||||
timeutil::Timer timer;
|
timeutil::Timer timer;
|
||||||
if (loadVisible()) {
|
if (loadVisible()) {
|
||||||
int64_t mcs = timer.stop();
|
int64_t mcs = timer.stop();
|
||||||
avgDurationMcs = mcs * 0.2 + avgDurationMcs * 0.8;
|
if (mcstotal + mcs * 2 < maxDuration * 1000) {
|
||||||
if (mcstotal + max(avgDurationMcs, mcs) * 2 < maxDuration * 1000) {
|
|
||||||
mcstotal += mcs;
|
mcstotal += mcs;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
mcstotal += mcs;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include "../window/Events.h"
|
#include "../window/Events.h"
|
||||||
#include "../window/input.h"
|
#include "../window/input.h"
|
||||||
#include "../items/ItemDef.h"
|
#include "../items/ItemDef.h"
|
||||||
|
#include "../items/ItemStack.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
#include "scripting/scripting.h"
|
#include "scripting/scripting.h"
|
||||||
#include "BlocksController.h"
|
#include "BlocksController.h"
|
||||||
|
|
||||||
@@ -239,7 +241,9 @@ void PlayerController::updateInteraction(){
|
|||||||
int z = iend.z;
|
int z = iend.z;
|
||||||
uint8_t states = 0;
|
uint8_t states = 0;
|
||||||
|
|
||||||
ItemDef* item = indices->getItemDef(player->getChosenItem());
|
auto inventory = player->getInventory();
|
||||||
|
ItemStack& stack = inventory->getSlot(player->getChosenSlot());
|
||||||
|
ItemDef* item = indices->getItemDef(stack.getItemId());
|
||||||
Block* def = indices->getBlockDef(item->rt.placingBlock);
|
Block* def = indices->getBlockDef(item->rt.placingBlock);
|
||||||
if (def && def->rotatable){
|
if (def && def->rotatable){
|
||||||
const std::string& name = def->rotations.name;
|
const std::string& name = def->rotations.name;
|
||||||
@@ -285,7 +289,7 @@ void PlayerController::updateInteraction(){
|
|||||||
scripting::on_block_interact(player, target, x, y, z);
|
scripting::on_block_interact(player, target, x, y, z);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (target->model != BlockModel::xsprite){
|
if (!target->replaceable){
|
||||||
x = (iend.x)+(norm.x);
|
x = (iend.x)+(norm.x);
|
||||||
y = (iend.y)+(norm.y);
|
y = (iend.y)+(norm.y);
|
||||||
z = (iend.z)+(norm.z);
|
z = (iend.z)+(norm.z);
|
||||||
@@ -311,7 +315,18 @@ void PlayerController::updateInteraction(){
|
|||||||
}
|
}
|
||||||
if (Events::jactive(BIND_PLAYER_PICK)){
|
if (Events::jactive(BIND_PLAYER_PICK)){
|
||||||
Block* block = indices->getBlockDef(chunks->get(x,y,z)->id);
|
Block* block = indices->getBlockDef(chunks->get(x,y,z)->id);
|
||||||
player->setChosenItem(block->rt.pickingItem);
|
itemid_t id = block->rt.pickingItem;
|
||||||
|
auto inventory = player->getInventory();
|
||||||
|
size_t slotid = inventory->findSlotByItem(id);
|
||||||
|
if (slotid == Inventory::npos) {
|
||||||
|
slotid = player->getChosenSlot();
|
||||||
|
} else {
|
||||||
|
player->setChosenSlot(slotid);
|
||||||
|
}
|
||||||
|
ItemStack& stack = inventory->getSlot(slotid);
|
||||||
|
if (stack.getItemId() != id) {
|
||||||
|
stack.set(ItemStack(id, 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selectedBlockId = -1;
|
selectedBlockId = -1;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "../../voxels/voxel.h"
|
#include "../../voxels/voxel.h"
|
||||||
#include "../../lighting/Lighting.h"
|
#include "../../lighting/Lighting.h"
|
||||||
#include "../../logic/BlocksController.h"
|
#include "../../logic/BlocksController.h"
|
||||||
|
#include "../../engine.h"
|
||||||
|
|
||||||
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
||||||
lua_pushinteger(L, x);
|
lua_pushinteger(L, x);
|
||||||
@@ -27,7 +28,25 @@ inline void luaL_openlib(lua_State* L, const char* name, const luaL_Reg* libfunc
|
|||||||
lua_setglobal(L, name);
|
lua_setglobal(L, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* == world library ==*/
|
/* == pack library == */
|
||||||
|
static int l_pack_get_folder(lua_State* L) {
|
||||||
|
std::string packName = lua_tostring(L, 1);
|
||||||
|
for (auto& pack : scripting::engine->getContentPacks()) {
|
||||||
|
if (pack.id == packName) {
|
||||||
|
lua_pushstring(L, (pack.folder.u8string()+"/").c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_pushstring(L, "");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const luaL_Reg packlib [] = {
|
||||||
|
{"get_folder", l_pack_get_folder},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* == world library == */
|
||||||
static int l_world_get_day_time(lua_State* L) {
|
static int l_world_get_day_time(lua_State* L) {
|
||||||
lua_pushnumber(L, scripting::level->world->daytime);
|
lua_pushnumber(L, scripting::level->world->daytime);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -266,6 +285,7 @@ static int l_is_replaceable_at(lua_State* L) {
|
|||||||
lua_setglobal(L, NAME))
|
lua_setglobal(L, NAME))
|
||||||
|
|
||||||
void apilua::create_funcs(lua_State* L) {
|
void apilua::create_funcs(lua_State* L) {
|
||||||
|
luaL_openlib(L, "pack", packlib, 0);
|
||||||
luaL_openlib(L, "world", worldlib, 0);
|
luaL_openlib(L, "world", worldlib, 0);
|
||||||
luaL_openlib(L, "player", playerlib, 0);
|
luaL_openlib(L, "player", playerlib, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,19 @@
|
|||||||
#include "../../voxels/Block.h"
|
#include "../../voxels/Block.h"
|
||||||
#include "../../items/ItemDef.h"
|
#include "../../items/ItemDef.h"
|
||||||
#include "../../logic/BlocksController.h"
|
#include "../../logic/BlocksController.h"
|
||||||
|
#include "../../engine.h"
|
||||||
#include "api_lua.h"
|
#include "api_lua.h"
|
||||||
|
|
||||||
using namespace scripting;
|
using namespace scripting;
|
||||||
|
|
||||||
namespace scripting {
|
namespace scripting {
|
||||||
extern lua_State* L;
|
extern lua_State* L;
|
||||||
extern EnginePaths* paths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Engine* scripting::engine = nullptr;
|
||||||
lua_State* scripting::L = nullptr;
|
lua_State* scripting::L = nullptr;
|
||||||
Level* scripting::level = nullptr;
|
Level* scripting::level = nullptr;
|
||||||
const Content* scripting::content = nullptr;
|
const Content* scripting::content = nullptr;
|
||||||
EnginePaths* scripting::paths = nullptr;
|
|
||||||
BlocksController* scripting::blocks = nullptr;
|
BlocksController* scripting::blocks = nullptr;
|
||||||
|
|
||||||
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
||||||
@@ -58,8 +58,8 @@ int call_func(lua_State* L, int argc, const std::string& name) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::initialize(EnginePaths* paths) {
|
void scripting::initialize(Engine* engine) {
|
||||||
scripting::paths = paths;
|
scripting::engine = engine;
|
||||||
|
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
if (L == nullptr) {
|
if (L == nullptr) {
|
||||||
@@ -87,7 +87,7 @@ void scripting::on_world_load(Level* level, BlocksController* blocks) {
|
|||||||
scripting::level = level;
|
scripting::level = level;
|
||||||
scripting::content = level->content;
|
scripting::content = level->content;
|
||||||
scripting::blocks = blocks;
|
scripting::blocks = blocks;
|
||||||
|
auto paths = scripting::engine->getPaths();
|
||||||
fs::path file = paths->getResources()/fs::path("scripts/world.lua");
|
fs::path file = paths->getResources()/fs::path("scripts/world.lua");
|
||||||
std::string src = files::read_string(file);
|
std::string src = files::read_string(file);
|
||||||
luaL_loadbuffer(L, src.c_str(), src.length(), file.string().c_str());
|
luaL_loadbuffer(L, src.c_str(), src.length(), file.string().c_str());
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
class EnginePaths;
|
class Engine;
|
||||||
class Content;
|
class Content;
|
||||||
class Level;
|
class Level;
|
||||||
class Block;
|
class Block;
|
||||||
@@ -14,11 +14,12 @@ struct item_funcs_set;
|
|||||||
class BlocksController;
|
class BlocksController;
|
||||||
|
|
||||||
namespace scripting {
|
namespace scripting {
|
||||||
|
extern Engine* engine;
|
||||||
extern const Content* content;
|
extern const Content* content;
|
||||||
extern Level* level;
|
extern Level* level;
|
||||||
extern BlocksController* blocks;
|
extern BlocksController* blocks;
|
||||||
|
|
||||||
void initialize(EnginePaths* paths);
|
void initialize(Engine* engine);
|
||||||
void on_world_load(Level* level, BlocksController* blocks);
|
void on_world_load(Level* level, BlocksController* blocks);
|
||||||
void on_world_quit();
|
void on_world_quit();
|
||||||
void update_block(const Block* block, int x, int y, int z);
|
void update_block(const Block* block, int x, int y, int z);
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef MATHS_FASTMATHS_H_
|
||||||
|
#define MATHS_FASTMATHS_H_
|
||||||
|
|
||||||
|
namespace fastmaths {
|
||||||
|
static unsigned int g_seed;
|
||||||
|
|
||||||
|
inline void srand(int seed) {
|
||||||
|
g_seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int rand(void) {
|
||||||
|
g_seed = (214013*g_seed+2531011);
|
||||||
|
return (g_seed>>16)&0x7FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MATHS_FASTMATHS_H_
|
||||||
+15
-6
@@ -5,6 +5,7 @@
|
|||||||
#include "../world/Level.h"
|
#include "../world/Level.h"
|
||||||
#include "../window/Events.h"
|
#include "../window/Events.h"
|
||||||
#include "../window/Camera.h"
|
#include "../window/Camera.h"
|
||||||
|
#include "../items/Inventory.h"
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
@@ -18,12 +19,16 @@ const float JUMP_FORCE = 8.0f;
|
|||||||
|
|
||||||
Player::Player(glm::vec3 position, float speed) :
|
Player::Player(glm::vec3 position, float speed) :
|
||||||
speed(speed),
|
speed(speed),
|
||||||
chosenItem(0),
|
chosenSlot(0),
|
||||||
camera(new Camera(position, glm::radians(90.0f))),
|
camera(new Camera(position, glm::radians(90.0f))),
|
||||||
spCamera(new Camera(position, glm::radians(90.0f))),
|
spCamera(new Camera(position, glm::radians(90.0f))),
|
||||||
tpCamera(new Camera(position, glm::radians(90.0f))),
|
tpCamera(new Camera(position, glm::radians(90.0f))),
|
||||||
currentCamera(camera),
|
currentCamera(camera),
|
||||||
hitbox(new Hitbox(position, glm::vec3(0.3f,0.9f,0.3f))) {
|
hitbox(new Hitbox(position, glm::vec3(0.3f,0.9f,0.3f))),
|
||||||
|
inventory(new Inventory(40)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Player::~Player() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::update(
|
void Player::update(
|
||||||
@@ -118,14 +123,18 @@ void Player::teleport(glm::vec3 position) {
|
|||||||
hitbox->position = position;
|
hitbox->position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setChosenItem(itemid_t id) {
|
void Player::setChosenSlot(int index) {
|
||||||
chosenItem = id;
|
chosenSlot = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemid_t Player::getChosenItem() const {
|
int Player::getChosenSlot() const {
|
||||||
return chosenItem;
|
return chosenSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Player::getSpeed() const {
|
float Player::getSpeed() const {
|
||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Inventory> Player::getInventory() const {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
class Hitbox;
|
class Hitbox;
|
||||||
|
class Inventory;
|
||||||
class PhysicsSolver;
|
class PhysicsSolver;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
class Level;
|
class Level;
|
||||||
@@ -30,11 +31,12 @@ struct PlayerInput {
|
|||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
float speed;
|
float speed;
|
||||||
itemid_t chosenItem;
|
int chosenSlot;
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Camera> camera, spCamera, tpCamera;
|
std::shared_ptr<Camera> camera, spCamera, tpCamera;
|
||||||
std::shared_ptr<Camera> currentCamera;
|
std::shared_ptr<Camera> currentCamera;
|
||||||
std::unique_ptr<Hitbox> hitbox;
|
std::unique_ptr<Hitbox> hitbox;
|
||||||
|
std::shared_ptr<Inventory> inventory;
|
||||||
bool flight = false;
|
bool flight = false;
|
||||||
bool noclip = false;
|
bool noclip = false;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
@@ -43,15 +45,17 @@ public:
|
|||||||
glm::vec2 cam = {};
|
glm::vec2 cam = {};
|
||||||
|
|
||||||
Player(glm::vec3 position, float speed);
|
Player(glm::vec3 position, float speed);
|
||||||
~Player() = default;
|
~Player();
|
||||||
|
|
||||||
void teleport(glm::vec3 position);
|
void teleport(glm::vec3 position);
|
||||||
void update(Level* level, PlayerInput& input, float delta);
|
void update(Level* level, PlayerInput& input, float delta);
|
||||||
|
|
||||||
void setChosenItem(itemid_t id);
|
void setChosenSlot(int index);
|
||||||
|
|
||||||
itemid_t getChosenItem() const;
|
int getChosenSlot() const;
|
||||||
float getSpeed() const;
|
float getSpeed() const;
|
||||||
|
|
||||||
|
std::shared_ptr<Inventory> getInventory() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SRC_OBJECTS_PLAYER_H_ */
|
#endif /* SRC_OBJECTS_PLAYER_H_ */
|
||||||
|
|||||||
+2
-1
@@ -81,7 +81,7 @@ public:
|
|||||||
std::vector<glm::vec3> modelExtraPoints = {}; //initially made for tetragons
|
std::vector<glm::vec3> modelExtraPoints = {}; //initially made for tetragons
|
||||||
std::vector<UVRegion> modelUVs = {}; // boxes' tex-UVs also there
|
std::vector<UVRegion> modelUVs = {}; // boxes' tex-UVs also there
|
||||||
uint8_t emission[4] {0, 0, 0, 0};
|
uint8_t emission[4] {0, 0, 0, 0};
|
||||||
unsigned char drawGroup = 0;
|
ubyte drawGroup = 0;
|
||||||
BlockModel model = BlockModel::block;
|
BlockModel model = BlockModel::block;
|
||||||
bool lightPassing = false;
|
bool lightPassing = false;
|
||||||
bool skyLightPassing = false;
|
bool skyLightPassing = false;
|
||||||
@@ -95,6 +95,7 @@ public:
|
|||||||
AABB hitbox;
|
AABB hitbox;
|
||||||
BlockRotProfile rotations;
|
BlockRotProfile rotations;
|
||||||
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
||||||
|
std::string scriptName = name.substr(name.find(':')+1);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
blockid_t id;
|
blockid_t id;
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "voxelengine",
|
||||||
|
"version-string": "1.0.0",
|
||||||
|
"dependencies": [
|
||||||
|
"opengl",
|
||||||
|
"openal-soft",
|
||||||
|
"glfw3",
|
||||||
|
"glew",
|
||||||
|
"glm",
|
||||||
|
"libspng",
|
||||||
|
"zlib",
|
||||||
|
"luajit"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user