Merge branch 'main' of https://github.com/MihailRis/VoxelEngine-Cpp
This commit is contained in:
commit
b80e36f008
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
custom: ['https://www.donationalerts.com/r/mihailris']
|
||||
31
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Найден баг
|
||||
about: Создайте отчет, чтобы помочь нам исправить этот баг
|
||||
title: BUG
|
||||
labels: bug, wontfix
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Опишите ошибку**
|
||||
Четкое и краткое описание ошибки.
|
||||
|
||||
**Для воспроизведения**
|
||||
Шаги для воспроизведения поведения:
|
||||
1. Перейдите в раздел «...»
|
||||
2. Нажмите «....»
|
||||
3. Прокрутите вниз до «....»
|
||||
4. См. ошибку
|
||||
|
||||
**Ожидаемое поведение**
|
||||
Четкое и краткое описание того, что вы ожидаете.
|
||||
|
||||
**Скриншоты**
|
||||
Если применимо, добавьте снимки экрана, которые помогут объяснить вашу проблему.
|
||||
|
||||
**Техническая информация (заполните следующую информацию):**
|
||||
- ОС: [например. Windows 10]
|
||||
- Версия [например. 0.17]
|
||||
|
||||
**Дополнительный контекст**
|
||||
Добавьте сюда любой другой контекст проблемы.
|
||||
20
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Новая фича
|
||||
about: Новая идея для этого проекта
|
||||
title: 'ENHANCEMENT '
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Связан ли ваш запрос на добавление функции с проблемой? Пожалуйста, опишите.**
|
||||
Четкое и краткое описание проблемы. Бывший. Я всегда расстраиваюсь, когда [...]
|
||||
|
||||
**Опишите желаемое решение**
|
||||
Четкое и краткое описание того, чего вы хотите.
|
||||
|
||||
**Опишите альтернативы, которые вы рассматривали**
|
||||
Четкое и краткое описание любых альтернативных решений или функций, которые вы рассматривали.
|
||||
|
||||
**Дополнительный контекст**
|
||||
Добавьте сюда любой другой контекст или снимки экрана о запросе функции.
|
||||
12
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
name: Вопрос
|
||||
about: Вопрос другого характера
|
||||
title: QUESTION
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Опишите свой вопрос**
|
||||
Кратко и понятно опишите ваш вопрос.
|
||||
Перед созданием этого запроса убедитесь, что ранее не были созданы подобные.
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -25,11 +25,16 @@ Debug/voxel_engine
|
||||
.settings
|
||||
.cproject
|
||||
.project
|
||||
.fleet
|
||||
.git
|
||||
/Default/
|
||||
AppDir
|
||||
appimage-build/
|
||||
|
||||
# for vcpkg
|
||||
/vcpkg/
|
||||
.gitmodules
|
||||
|
||||
# macOS folder attributes
|
||||
*.DS_Store
|
||||
|
||||
|
||||
@ -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)
|
||||
project(VoxelEngine)
|
||||
|
||||
@ -28,8 +33,10 @@ if(VOXELENGINE_BUILD_APPDIR)
|
||||
install(TARGETS VoxelEngine DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/AppDir/usr/bin)
|
||||
endif()
|
||||
|
||||
|
||||
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"))
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Release>:Release>")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /MT /O2)
|
||||
@ -45,16 +52,52 @@ else()
|
||||
-Wwrite-strings -Wno-unused-parameter)
|
||||
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(GLEW REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
# luajit has no CMakeLists.txt to use it as subdirectory, so install it
|
||||
find_package(Lua REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
if (WIN32)
|
||||
set(PNGLIB spng)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/glfw)
|
||||
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)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/glfw)
|
||||
endif()
|
||||
else()
|
||||
# luajit has no CMakeLists.txt to use it as subdirectory, so install it manually
|
||||
find_package(Lua REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
set(PNGLIB PNG::PNG)
|
||||
endif()
|
||||
@ -75,7 +118,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
endif()
|
||||
|
||||
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})
|
||||
|
||||
|
||||
47
Dockerfile
Normal file
47
Dockerfile
Normal file
@ -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
|
||||
43
README.md
43
README.md
@ -10,7 +10,7 @@
|
||||
- <kbd>**Tab**</kbd> - open inventory
|
||||
- <kbd>**W**</kbd> <kbd>**A**</kbd> <kbd>**S**</kbd> <kbd>**D**</kbd> - movement
|
||||
- <kbd>**Space**</kbd> - jump
|
||||
- <kbd>**LMB**</kbd> - remove block
|
||||
- <kbd>**LMB**</kbd> - remove block
|
||||
- <kbd>**RMB**</kbd> - place block
|
||||
- <kbd>**F**</kbd> - toggle flight mode
|
||||
- <kbd>**N**</kbd> - noclip mode
|
||||
@ -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).
|
||||
|
||||
## 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 alpha = a_color.a * tex_color.a;
|
||||
// anyway it's any alpha-test alternative required
|
||||
if (alpha < 0.1f)
|
||||
if (alpha < 0.3f)
|
||||
discard;
|
||||
f_color = mix(a_color * tex_color, vec4(fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve)));
|
||||
f_color.a = alpha;
|
||||
|
||||
@ -24,6 +24,7 @@ world.Name=Назва
|
||||
menu.Create World=Стварыць Свет
|
||||
|
||||
world.convert-request=Ёсць змены ў індэксах! Канвертаваць свет?
|
||||
world.delete-confirm=Выдаліць свет незваротна?
|
||||
|
||||
# Настройки
|
||||
settings.Load Distance=Дыстанцыя Загрузкі
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
menu.missing-content=Missing Content!
|
||||
world.convert-request=Content indices have changed! Convert world files?
|
||||
error.pack-not-found=Could not to find pack
|
||||
world.delete-confirm=Do you want to delete world forever?
|
||||
|
||||
# Bindings
|
||||
movement.forward=Forward
|
||||
|
||||
@ -12,8 +12,9 @@ error.pack-not-found=Pakettia ei löytynyt!
|
||||
menu.New World = Uusi Maailma
|
||||
menu.Quit=Poistu
|
||||
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.Content Error=Sisältövirhe!
|
||||
menu.Controls=Ohjaus
|
||||
menu.Back to Main Menu=Takaisin Valikoon
|
||||
menu.Settings=Asetukset
|
||||
@ -23,12 +24,13 @@ menu.Name=Nimi
|
||||
menu.Create World=Luo Maailma
|
||||
|
||||
world.convert-request=Indeksit vaihdettu! Lataa maailma uudeleen?
|
||||
world.delete-confirm=Poistetaanko maailma ikuisesti?
|
||||
|
||||
# Настройки
|
||||
settings.Load Distance=Lataus Alue
|
||||
settings.Load Speed=Lataus Nopeus
|
||||
settings.Fog Curve=Sumun valaistus
|
||||
settings.Backlight=Valaistus
|
||||
settings.Load Distance=Latausalue
|
||||
settings.Load Speed=Latausnopeus
|
||||
settings.Fog Curve=Sumun tiheys
|
||||
settings.Backlight=Taustavalo
|
||||
settings.V-Sync=Pystytahdistus
|
||||
|
||||
settings.FOV=Näkökenttä
|
||||
@ -41,8 +43,8 @@ movement.back=Taaksepäin
|
||||
movement.left=Vaseemalle
|
||||
movement.right=Oikealle
|
||||
movement.jump=Hyppy
|
||||
movement.sprint=Kiihtyvyys
|
||||
movement.crouch=Istu alas
|
||||
movement.sprint=Juoksu
|
||||
movement.crouch=Hiipiä
|
||||
movement.cheat=Huijata
|
||||
hud.inventory=Varasto
|
||||
player.pick=Ottaa lohko
|
||||
@ -50,4 +52,4 @@ player.attack=Lyödä / Rikkoa
|
||||
player.build=Aseta lohko
|
||||
player.flight=Lento
|
||||
camera.zoom=Lähentäminen
|
||||
camera.mode=Vaihda Kameratila
|
||||
camera.mode=Vaihda Kameratila
|
||||
|
||||
@ -24,6 +24,7 @@ world.Name=Название
|
||||
menu.Create World=Создать Мир
|
||||
|
||||
world.convert-request=Есть изменения в индексах! Конвертировать мир?
|
||||
world.delete-confirm=Удалить мир безвозвратно?
|
||||
|
||||
# Настройки
|
||||
settings.Load Distance=Дистанция Загрузки
|
||||
|
||||
BIN
res/textures/gui/delete_icon.png
Normal file
BIN
res/textures/gui/delete_icon.png
Normal file
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"/background", "background");
|
||||
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_ATLAS, TEXTURES_FOLDER"/blocks", "blocks");
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "gzip.h"
|
||||
#include "byte_utils.h"
|
||||
|
||||
using namespace json;
|
||||
@ -148,12 +149,21 @@ static Map* object_from_binary(ByteReader& reader) {
|
||||
}
|
||||
|
||||
std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
|
||||
ByteReader reader(src, size);
|
||||
std::unique_ptr<Value> value (value_from_binary(reader));
|
||||
if (value->type != valtype::map) {
|
||||
throw std::runtime_error("root value is not an object");
|
||||
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);
|
||||
std::unique_ptr<Value> value (value_from_binary(reader));
|
||||
if (value->type != valtype::map) {
|
||||
throw std::runtime_error("root value is not an object");
|
||||
}
|
||||
std::unique_ptr<Map> obj (value->value.map);
|
||||
value->value.map = nullptr;
|
||||
return obj;
|
||||
}
|
||||
std::unique_ptr<Map> obj (value->value.map);
|
||||
value->value.map = nullptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "../typedefs.h"
|
||||
|
||||
namespace gzip {
|
||||
const unsigned char MAGIC[] = "\x1F\x8B";
|
||||
std::vector<ubyte> compress(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->num("draw-group", def->drawGroup);
|
||||
root->str("picking-item", def->pickingItem);
|
||||
root->str("script-name", def->scriptName);
|
||||
}
|
||||
|
||||
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("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]
|
||||
auto emissionarr = root->list("emission");
|
||||
@ -247,7 +250,7 @@ void ContentLoader::loadBlock(Block* def, std::string full, std::string name) {
|
||||
auto folder = pack->folder;
|
||||
|
||||
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);
|
||||
if (fs::is_regular_file(scriptfile)) {
|
||||
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;
|
||||
|
||||
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);
|
||||
if (fs::is_regular_file(scriptfile)) {
|
||||
scripting::load_item_script(full, scriptfile, &def->rt.funcsset);
|
||||
|
||||
@ -46,7 +46,7 @@ Engine::Engine(EngineSettings& settings, EnginePaths* paths)
|
||||
}
|
||||
|
||||
auto resdir = paths->getResources();
|
||||
scripting::initialize(paths);
|
||||
scripting::initialize(this);
|
||||
|
||||
std::cout << "-- loading assets" << std::endl;
|
||||
std::vector<fs::path> roots {resdir};
|
||||
|
||||
@ -1,146 +1,334 @@
|
||||
#include "InventoryView.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "BlocksPreview.h"
|
||||
#include "LevelFrontend.h"
|
||||
#include "../window/Events.h"
|
||||
#include "../window/input.h"
|
||||
#include "../assets/Assets.h"
|
||||
#include "../graphics/Atlas.h"
|
||||
#include "../graphics/Shader.h"
|
||||
#include "../graphics/Batch2D.h"
|
||||
#include "../graphics/GfxContext.h"
|
||||
#include "../graphics/Font.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../items/ItemDef.h"
|
||||
#include "../items/Inventory.h"
|
||||
#include "../maths/voxmaths.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../frontend/gui/controls.h"
|
||||
#include "../util/stringutil.h"
|
||||
|
||||
InventoryLayout::InventoryLayout(glm::vec2 size) : size(size) {}
|
||||
|
||||
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,
|
||||
InventoryInteraction* interaction,
|
||||
const Content* content,
|
||||
SlotLayout layout)
|
||||
: UINode(glm::vec2(), glm::vec2(InventoryView::SLOT_SIZE)),
|
||||
frontend(frontend),
|
||||
interaction(interaction),
|
||||
content(content),
|
||||
stack(stack),
|
||||
layout(layout) {
|
||||
color(glm::vec4(0, 0, 0, 0.2f));
|
||||
}
|
||||
|
||||
// performance disaster
|
||||
void SlotView::draw(Batch2D* batch, Assets* assets) {
|
||||
glm::vec2 coord = calcCoord();
|
||||
|
||||
int slotSize = InventoryView::SLOT_SIZE;
|
||||
|
||||
glm::vec4 tint(1.0f);
|
||||
glm::vec4 color = color_;
|
||||
if (hover_ || highlighted) {
|
||||
tint *= 1.333f;
|
||||
color = glm::vec4(1, 1, 1, 0.2f);
|
||||
}
|
||||
|
||||
batch->color = color;
|
||||
if (color.a > 0.0) {
|
||||
batch->texture(nullptr);
|
||||
if (highlighted) {
|
||||
batch->rect(coord.x-4, coord.y-4, slotSize+8, slotSize+8);
|
||||
} else {
|
||||
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) {
|
||||
case item_icon_type::none:
|
||||
break;
|
||||
case item_icon_type::block:
|
||||
batch->render();
|
||||
{
|
||||
GfxContext subctx = ctx.sub();
|
||||
subctx.depthTest(true);
|
||||
subctx.cullFace(true);
|
||||
|
||||
Block* cblock = content->requireBlock(item->icon);
|
||||
preview->begin(&subctx.getViewport());
|
||||
preview->draw(cblock, coord.x, coord.y, slotSize, tint);
|
||||
}
|
||||
uiShader->use();
|
||||
batch->begin();
|
||||
break;
|
||||
case item_icon_type::sprite: {
|
||||
size_t index = item->icon.find(':');
|
||||
std::string name = item->icon.substr(index+1);
|
||||
UVRegion region(0.0f, 0.0, 1.0f, 1.0f);
|
||||
if (index == std::string::npos) {
|
||||
batch->texture(assets->getTexture(name));
|
||||
} else {
|
||||
std::string atlasname = item->icon.substr(0, index);
|
||||
Atlas* atlas = assets->getAtlas(atlasname);
|
||||
if (atlas && atlas->has(name)) {
|
||||
region = atlas->get(name);
|
||||
batch->texture(atlas->getTexture());
|
||||
}
|
||||
}
|
||||
batch->rect(
|
||||
coord.x, coord.y, slotSize, slotSize,
|
||||
0, 0, 0, region, false, true, tint);
|
||||
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(
|
||||
int columns,
|
||||
const Content* content,
|
||||
LevelFrontend* frontend,
|
||||
std::vector<itemid_t> items)
|
||||
: content(content),
|
||||
InventoryInteraction* interaction,
|
||||
std::shared_ptr<Inventory> inventory,
|
||||
std::unique_ptr<InventoryLayout> layout)
|
||||
: Container(glm::vec2(), glm::vec2()),
|
||||
content(content),
|
||||
indices(content->getIndices()),
|
||||
items(items),
|
||||
inventory(inventory),
|
||||
layout(std::move(layout)),
|
||||
frontend(frontend),
|
||||
columns(columns) {
|
||||
interaction(interaction) {
|
||||
size(this->layout->getSize());
|
||||
color(glm::vec4(0, 0, 0, 0.5f));
|
||||
}
|
||||
|
||||
InventoryView::~InventoryView() {
|
||||
}
|
||||
InventoryView::~InventoryView() {}
|
||||
|
||||
void InventoryView::setPosition(int x, int y) {
|
||||
position.x = x;
|
||||
position.y = y;
|
||||
}
|
||||
void InventoryView::build() {
|
||||
int index = 0;
|
||||
for (auto& slot : layout->getSlots()) {
|
||||
ItemStack& item = inventory->getSlot(index);
|
||||
|
||||
int InventoryView::getWidth() const {
|
||||
return columns * iconSize + (columns-1) * interval + padding.x * 2;
|
||||
}
|
||||
|
||||
int InventoryView::getHeight() const {
|
||||
uint inv_rows = ceildiv(items.size(), columns);
|
||||
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->color = glm::vec4(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
batch->rect(position.x, position.y, inv_w, inv_h);
|
||||
batch->render();
|
||||
|
||||
// blocks & items
|
||||
if (Events::scroll) {
|
||||
scroll -= Events::scroll * (iconSize+interval);
|
||||
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++;
|
||||
}
|
||||
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 {
|
||||
tint = glm::vec4(1.0f);
|
||||
}
|
||||
switch (item->iconType) {
|
||||
case item_icon_type::none:
|
||||
break;
|
||||
case item_icon_type::block: {
|
||||
Block* cblock = content->requireBlock(item->icon);
|
||||
blocksPreview->begin(&ctx->getViewport());
|
||||
blocksPreview->draw(cblock, x, y, iconSize, tint);
|
||||
break;
|
||||
}
|
||||
case item_icon_type::sprite: {
|
||||
batch->begin();
|
||||
uiShader->use();
|
||||
size_t index = item->icon.find(':');
|
||||
std::string name = item->icon.substr(index+1);
|
||||
UVRegion region(0.0f, 0.0, 1.0f, 1.0f);
|
||||
if (index == std::string::npos) {
|
||||
batch->texture(assets->getTexture(name));
|
||||
} else {
|
||||
std::string atlasname = item->icon.substr(0, index);
|
||||
Atlas* atlas = assets->getAtlas(atlasname);
|
||||
if (atlas && atlas->has(name)) {
|
||||
region = atlas->get(name);
|
||||
batch->texture(atlas->getTexture());
|
||||
}
|
||||
}
|
||||
batch->rect(x, y, 48, 48, 0, 0, 0, region, false, true, glm::vec4(1.0f));
|
||||
batch->render();
|
||||
break;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
uiShader->use();
|
||||
}
|
||||
|
||||
void InventoryView::setSelected(int index) {
|
||||
for (int i = 0; i < int(slots.size()); i++) {
|
||||
auto slot = slots[i];
|
||||
slot->setHighlighted(i == index);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -5,46 +5,150 @@
|
||||
#include <functional>
|
||||
#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"
|
||||
|
||||
class Batch2D;
|
||||
class Assets;
|
||||
class GfxContext;
|
||||
class Content;
|
||||
class ContentIndices;
|
||||
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 ContentIndices* indices;
|
||||
std::vector<itemid_t> items;
|
||||
slotconsumer consumer = nullptr;
|
||||
|
||||
std::shared_ptr<Inventory> inventory;
|
||||
std::unique_ptr<InventoryLayout> layout;
|
||||
LevelFrontend* frontend;
|
||||
InventoryInteraction* interaction;
|
||||
|
||||
std::vector<SlotView*> slots;
|
||||
|
||||
int scroll = 0;
|
||||
int columns;
|
||||
uint iconSize = 48;
|
||||
uint interval = 4;
|
||||
glm::ivec2 padding {interval, interval};
|
||||
glm::ivec2 position {0, 0};
|
||||
public:
|
||||
InventoryView(
|
||||
int columns,
|
||||
const Content* content,
|
||||
LevelFrontend* frontend,
|
||||
std::vector<itemid_t> items);
|
||||
InventoryInteraction* interaction,
|
||||
std::shared_ptr<Inventory> inventory,
|
||||
std::unique_ptr<InventoryLayout> layout);
|
||||
|
||||
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);
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
void setSlotConsumer(slotconsumer consumer);
|
||||
void setInventory(std::shared_ptr<Inventory> inventory);
|
||||
|
||||
virtual void setCoord(glm::vec2 coord) override;
|
||||
|
||||
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_
|
||||
|
||||
@ -28,6 +28,8 @@
|
||||
#include "../settings.h"
|
||||
#include "../engine.h"
|
||||
#include "../items/ItemDef.h"
|
||||
#include "../items/ItemStack.h"
|
||||
#include "../items/Inventory.h"
|
||||
#include "LevelFrontend.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->uniform1i("u_cubemap", 1);
|
||||
{
|
||||
itemid_t id = level->player->getChosenItem();
|
||||
ItemDef* item = indices->getItemDef(id);
|
||||
auto player = level->player;
|
||||
auto inventory = player->getInventory();
|
||||
ItemStack& stack = inventory->getSlot(player->getChosenSlot());
|
||||
ItemDef* item = indices->getItemDef(stack.getItemId());
|
||||
assert(item != nullptr);
|
||||
float multiplier = 0.5f;
|
||||
shader->uniform3f("u_torchlightColor",
|
||||
|
||||
@ -40,7 +40,6 @@ PagesControl* GUI::getMenu() {
|
||||
}
|
||||
|
||||
void GUI::actMouse(float delta) {
|
||||
|
||||
auto hover = container->getAt(Events::cursor, nullptr);
|
||||
if (this->hover && this->hover != hover) {
|
||||
this->hover->hover(false);
|
||||
@ -53,7 +52,7 @@ void GUI::actMouse(float delta) {
|
||||
}
|
||||
this->hover = hover;
|
||||
|
||||
if (Events::jclicked(0)) {
|
||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||
if (pressed == nullptr && this->hover) {
|
||||
pressed = hover;
|
||||
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 = 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) {
|
||||
@ -100,13 +107,6 @@ void GUI::act(float delta) {
|
||||
if (Events::clicked(mousecode::BUTTON_1)) {
|
||||
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::vec4;
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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) {
|
||||
if (!interactive) {
|
||||
return nullptr;
|
||||
}
|
||||
return isInside(pos) ? self : nullptr;
|
||||
}
|
||||
|
||||
bool UINode::isInteractive() const {
|
||||
return interactive && visible();
|
||||
}
|
||||
|
||||
void UINode::setInteractive(bool flag) {
|
||||
interactive = flag;
|
||||
}
|
||||
|
||||
vec2 UINode::calcCoord() const {
|
||||
if (parent) {
|
||||
return coord + parent->calcCoord() + parent->contentOffset();
|
||||
|
||||
@ -30,6 +30,7 @@ namespace gui {
|
||||
bool hover_ = false;
|
||||
bool pressed_ = false;
|
||||
bool focused_ = false;
|
||||
bool interactive = true;
|
||||
Align align_ = Align::left;
|
||||
UINode* parent = nullptr;
|
||||
UINode(glm::vec2 coord, glm::vec2 size);
|
||||
@ -74,9 +75,12 @@ namespace gui {
|
||||
virtual bool isInside(glm::vec2 pos);
|
||||
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);};
|
||||
glm::vec2 calcCoord() const;
|
||||
void setCoord(glm::vec2 coord);
|
||||
virtual void setCoord(glm::vec2 coord);
|
||||
glm::vec2 size() const;
|
||||
virtual 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));
|
||||
}
|
||||
|
||||
// ================================= 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(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);
|
||||
scrollable(false);
|
||||
}
|
||||
@ -100,6 +113,11 @@ Button* Button::textSupplier(wstringsupplier supplier) {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void Button::setHoverColor(glm::vec4 color) {
|
||||
hoverColor = color;
|
||||
}
|
||||
|
||||
void Button::drawBackground(Batch2D* batch, Assets* assets) {
|
||||
vec2 coord = calcCoord();
|
||||
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(wstring placeholder, vec4 padding)
|
||||
: Panel(vec2(200,32), padding, 0, false),
|
||||
|
||||
@ -43,6 +43,15 @@ namespace gui {
|
||||
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 {
|
||||
protected:
|
||||
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 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;
|
||||
|
||||
@ -68,6 +77,24 @@ namespace gui {
|
||||
virtual std::wstring text() const;
|
||||
|
||||
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 {
|
||||
|
||||
@ -18,6 +18,9 @@ Container::Container(vec2 coord, vec2 size) : UINode(coord, size) {
|
||||
}
|
||||
|
||||
shared_ptr<UINode> Container::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||
if (!interactive) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isInside(pos)) return nullptr;
|
||||
for (auto node : nodes) {
|
||||
if (!node->visible())
|
||||
@ -58,7 +61,7 @@ void Container::act(float delta) {
|
||||
void Container::scrolled(int value) {
|
||||
int diff = (actualLength-size().y);
|
||||
if (diff > 0 && scrollable_) {
|
||||
scroll += value * 20;
|
||||
scroll += value * 40;
|
||||
if (scroll > 0)
|
||||
scroll = 0;
|
||||
if (-scroll > diff) {
|
||||
@ -98,6 +101,11 @@ void Container::add(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) {
|
||||
selected->setParent(nullptr);
|
||||
nodes.erase(std::remove_if(nodes.begin(), nodes.end(),
|
||||
@ -190,15 +198,12 @@ void Panel::refresh() {
|
||||
node->refresh();
|
||||
maxh = fmax(maxh, y+margin.y+node->size().y+margin.w+padding.w);
|
||||
}
|
||||
bool increased = maxh > size.y;
|
||||
if (resizing_) {
|
||||
if (maxLength_)
|
||||
this->size(vec2(glm::min(maxLength_, (int)(x+padding.z)), size.y));
|
||||
else
|
||||
this->size(vec2(x+padding.z, size.y));
|
||||
}
|
||||
if (increased)
|
||||
refresh();
|
||||
actualLength = size.y;
|
||||
}
|
||||
}
|
||||
@ -273,4 +278,4 @@ void PagesControl::reset() {
|
||||
Container::remove(current_.panel);
|
||||
current_ = Page{nullptr};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ namespace gui {
|
||||
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(UINode* node);
|
||||
virtual void add(std::shared_ptr<UINode> node, glm::vec2 coord);
|
||||
virtual void remove(std::shared_ptr<UINode> node);
|
||||
virtual void scrolled(int value) override;
|
||||
virtual void scrollable(bool flag);
|
||||
|
||||
@ -44,6 +44,7 @@
|
||||
#include "../engine.h"
|
||||
#include "../core_defs.h"
|
||||
#include "../items/ItemDef.h"
|
||||
#include "../items/Inventory.h"
|
||||
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
@ -163,26 +164,142 @@ void HudRenderer::createDebugPanel(Engine* engine) {
|
||||
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)
|
||||
: assets(engine->getAssets()),
|
||||
gui(engine->getGUI()),
|
||||
frontend(frontend) {
|
||||
|
||||
auto level = frontend->getLevel();
|
||||
frontend(frontend)
|
||||
{
|
||||
auto menu = gui->getMenu();
|
||||
auto content = level->content;
|
||||
auto indices = content->getIndices();
|
||||
|
||||
std::vector<itemid_t> items;
|
||||
for (itemid_t id = 1; id < indices->countItemDefs(); id++) {
|
||||
items.push_back(id);
|
||||
}
|
||||
contentAccess.reset(new InventoryView(8, content, frontend, items));
|
||||
contentAccess->setSlotConsumer([=](blockid_t id) {
|
||||
level->player->setChosenItem(id);
|
||||
});
|
||||
interaction = std::make_unique<InventoryInteraction>();
|
||||
grabbedItemView = std::make_shared<SlotView>(
|
||||
interaction->getGrabbedItem(),
|
||||
frontend,
|
||||
interaction.get(),
|
||||
frontend->getLevel()->content,
|
||||
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->perspective = false;
|
||||
@ -191,10 +308,18 @@ HudRenderer::HudRenderer(Engine* engine, LevelFrontend* frontend)
|
||||
createDebugPanel(engine);
|
||||
menu->reset();
|
||||
|
||||
gui->add(this->debugPanel);
|
||||
gui->add(debugPanel);
|
||||
gui->add(contentAccessPanel);
|
||||
gui->add(hotbarView);
|
||||
gui->add(inventoryView);
|
||||
gui->add(grabbedItemView);
|
||||
}
|
||||
|
||||
HudRenderer::~HudRenderer() {
|
||||
gui->remove(grabbedItemView);
|
||||
gui->remove(inventoryView);
|
||||
gui->remove(hotbarView);
|
||||
gui->remove(contentAccessPanel);
|
||||
gui->remove(debugPanel);
|
||||
delete uicamera;
|
||||
}
|
||||
@ -206,7 +331,12 @@ void HudRenderer::drawDebug(int fps){
|
||||
}
|
||||
|
||||
void HudRenderer::update(bool visible) {
|
||||
auto level = frontend->getLevel();
|
||||
auto player = level->player;
|
||||
auto menu = gui->getMenu();
|
||||
|
||||
menu->visible(pause);
|
||||
|
||||
if (!visible && inventoryOpen) {
|
||||
inventoryOpen = false;
|
||||
}
|
||||
@ -232,13 +362,35 @@ void HudRenderer::update(bool visible) {
|
||||
if ((pause || inventoryOpen) == Events::_cursor_locked) {
|
||||
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) {
|
||||
if (pause) {
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||
|
||||
const Viewport& viewport = ctx.getViewport();
|
||||
const uint width = viewport.getWidth();
|
||||
@ -271,12 +423,11 @@ void HudRenderer::draw(const GfxContext& ctx){
|
||||
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||
|
||||
// Draw selected item preview
|
||||
hotbarView->setPosition(width-60, height-60);
|
||||
hotbarView->setItems({player->getChosenItem()});
|
||||
hotbarView->actAndDraw(&ctx);
|
||||
hotbarView->setCoord(glm::vec2(width/2, height-65));
|
||||
hotbarView->setSelected(player->getChosenSlot());
|
||||
|
||||
// Crosshair
|
||||
batch->begin();
|
||||
@ -289,10 +440,20 @@ void HudRenderer::draw(const GfxContext& ctx){
|
||||
}
|
||||
|
||||
if (inventoryOpen) {
|
||||
// draw content access panel (all available items)
|
||||
contentAccess->setPosition(viewport.getWidth()-contentAccess->getWidth(), 0);
|
||||
contentAccess->actAndDraw(&ctx);
|
||||
auto caLayout = contentAccess->getLayout();
|
||||
auto invLayout = inventoryView->getLayout();
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@ -15,12 +15,15 @@ class Assets;
|
||||
class Player;
|
||||
class Level;
|
||||
class Engine;
|
||||
class SlotView;
|
||||
class InventoryView;
|
||||
class LevelFrontend;
|
||||
class InventoryInteraction;
|
||||
|
||||
namespace gui {
|
||||
class GUI;
|
||||
class UINode;
|
||||
class Panel;
|
||||
}
|
||||
|
||||
class HudRenderer {
|
||||
@ -34,13 +37,21 @@ class HudRenderer {
|
||||
bool inventoryOpen = false;
|
||||
bool pause = false;
|
||||
|
||||
std::unique_ptr<InventoryView> contentAccess;
|
||||
std::unique_ptr<InventoryView> hotbarView;
|
||||
std::shared_ptr<gui::Panel> contentAccessPanel;
|
||||
std::shared_ptr<InventoryView> contentAccess;
|
||||
std::shared_ptr<InventoryView> hotbarView;
|
||||
std::shared_ptr<InventoryView> inventoryView;
|
||||
std::shared_ptr<gui::UINode> debugPanel;
|
||||
std::unique_ptr<InventoryInteraction> interaction;
|
||||
std::shared_ptr<SlotView> grabbedItemView;
|
||||
gui::GUI* gui;
|
||||
LevelFrontend* frontend;
|
||||
|
||||
void createDebugPanel(Engine* engine);
|
||||
|
||||
std::shared_ptr<InventoryView> createContentAccess();
|
||||
std::shared_ptr<InventoryView> createHotbar();
|
||||
std::shared_ptr<InventoryView> createInventory();
|
||||
public:
|
||||
HudRenderer(Engine* engine, LevelFrontend* frontend);
|
||||
~HudRenderer();
|
||||
|
||||
@ -195,13 +195,40 @@ Panel* create_worlds_panel(Engine* engine) {
|
||||
if (!entry.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
auto name = entry.path().filename().u8string();
|
||||
auto btn = new Button(util::str2wstr_utf8(name),
|
||||
vec4(10.0f, 8.0f, 10.0f, 8.0f));
|
||||
auto folder = entry.path();
|
||||
auto name = folder.filename().u8string();
|
||||
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->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*) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ void MenuScreen::draw(float delta) {
|
||||
uint height = Window::height;
|
||||
|
||||
batch->begin();
|
||||
batch->texture(engine->getAssets()->getTexture("menubg"));
|
||||
batch->texture(engine->getAssets()->getTexture("gui/menubg"));
|
||||
batch->rect(0, 0,
|
||||
width, height, 0, 0, 0,
|
||||
UVRegion(0, 0, width/64, height/64),
|
||||
|
||||
74
src/items/Inventory.cpp
Normal file
74
src/items/Inventory.cpp
Normal file
@ -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;
|
||||
41
src/items/Inventory.h
Normal file
41
src/items/Inventory.h
Normal file
@ -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:
|
||||
std::string const name;
|
||||
|
||||
itemcount_t stackSize = 64;
|
||||
bool generated = false;
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
|
||||
@ -29,6 +30,7 @@ public:
|
||||
std::string icon = "blocks:notfound";
|
||||
|
||||
std::string placingBlock = "core:air";
|
||||
std::string scriptName = name.substr(name.find(':')+1);
|
||||
|
||||
struct {
|
||||
itemid_t id;
|
||||
|
||||
40
src/items/ItemStack.cpp
Normal file
40
src/items/ItemStack.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
40
src/items/ItemStack.h
Normal file
40
src/items/ItemStack.h
Normal file
@ -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/Block.h"
|
||||
#include "../constants.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
Lighting::Lighting(const Content* content, Chunks* chunks)
|
||||
: content(content), chunks(chunks) {
|
||||
auto indices = content->getIndices();
|
||||
@ -31,7 +30,7 @@ Lighting::~Lighting(){
|
||||
|
||||
void Lighting::clear(){
|
||||
for (unsigned int index = 0; index < chunks->volume; index++){
|
||||
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||
auto chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Lightmap* lightmap = chunk->lightmap;
|
||||
@ -98,10 +97,10 @@ void Lighting::onChunkLoaded(int cx, int cz){
|
||||
const Block* const* blockDefs = content->getIndices()->getBlockDefs();
|
||||
const Chunk* chunk = chunks->getChunk(cx, cz);
|
||||
|
||||
for (unsigned int y = 0; y < CHUNK_H; y++){
|
||||
for (unsigned int z = 0; z < CHUNK_D; z++){
|
||||
for (unsigned int x = 0; x < CHUNK_W; x++){
|
||||
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
for (uint y = 0; y < CHUNK_H; y++){
|
||||
for (uint z = 0; z < CHUNK_D; z++){
|
||||
for (uint x = 0; x < CHUNK_W; x++){
|
||||
voxel& vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
||||
const Block* block = blockDefs[vox.id];
|
||||
int gx = x + cx * CHUNK_W;
|
||||
int gz = z + cz * CHUNK_D;
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "../content/Content.h"
|
||||
#include "../lighting/Lighting.h"
|
||||
#include "../util/timeutil.h"
|
||||
#include "../maths/fastmaths.h"
|
||||
|
||||
#include "scripting/scripting.h"
|
||||
|
||||
@ -89,7 +90,10 @@ void BlocksController::randomTick(int tickid, int parts) {
|
||||
// timeutil::ScopeLogTimer timer(5000+tickid);
|
||||
const int w = chunks->w;
|
||||
const int d = chunks->d;
|
||||
int segments = 4;
|
||||
int segheight = CHUNK_H / segments;
|
||||
auto indices = level->content->getIndices();
|
||||
|
||||
for (uint z = padding; z < d-padding; z++){
|
||||
for (uint x = padding; x < w-padding; 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];
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
continue;
|
||||
int segments = 4;
|
||||
int segheight = CHUNK_H / segments;
|
||||
for (int s = 0; s < segments; s++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int bx = rand() % CHUNK_W;
|
||||
int by = rand() % segheight + s * segheight;
|
||||
int bz = rand() % CHUNK_D;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int bx = fastmaths::rand() % CHUNK_W;
|
||||
int by = fastmaths::rand() % segheight + s * segheight;
|
||||
int bz = fastmaths::rand() % CHUNK_D;
|
||||
const voxel& vox = chunk->voxels[(by * CHUNK_D + bz) * CHUNK_W + bx];
|
||||
Block* block = indices->getBlockDef(vox.id);
|
||||
if (block->rt.funcsset.randupdate) {
|
||||
|
||||
@ -40,11 +40,11 @@ void ChunksController::update(int64_t maxDuration) {
|
||||
timeutil::Timer timer;
|
||||
if (loadVisible()) {
|
||||
int64_t mcs = timer.stop();
|
||||
avgDurationMcs = mcs * 0.2 + avgDurationMcs * 0.8;
|
||||
if (mcstotal + max(avgDurationMcs, mcs) * 2 < maxDuration * 1000) {
|
||||
if (mcstotal + mcs * 2 < maxDuration * 1000) {
|
||||
mcstotal += mcs;
|
||||
continue;
|
||||
}
|
||||
mcstotal += mcs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -74,8 +74,8 @@ bool ChunksController::loadVisible(){
|
||||
if (surrounding == MIN_SURROUNDING && !chunk->isLighted()) {
|
||||
if (!chunk->isLoadedLights()) {
|
||||
lighting->buildSkyLight(chunk->x, chunk->z);
|
||||
}
|
||||
lighting->onChunkLoaded(chunk->x, chunk->z);
|
||||
}
|
||||
lighting->onChunkLoaded(chunk->x, chunk->z);
|
||||
chunk->setLighted(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
#include "../window/Events.h"
|
||||
#include "../window/input.h"
|
||||
#include "../items/ItemDef.h"
|
||||
#include "../items/ItemStack.h"
|
||||
#include "../items/Inventory.h"
|
||||
#include "scripting/scripting.h"
|
||||
#include "BlocksController.h"
|
||||
|
||||
@ -239,7 +241,9 @@ void PlayerController::updateInteraction(){
|
||||
int z = iend.z;
|
||||
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);
|
||||
if (def && def->rotatable){
|
||||
const std::string& name = def->rotations.name;
|
||||
@ -285,7 +289,7 @@ void PlayerController::updateInteraction(){
|
||||
scripting::on_block_interact(player, target, x, y, z);
|
||||
return;
|
||||
}
|
||||
if (target->model != BlockModel::xsprite){
|
||||
if (!target->replaceable){
|
||||
x = (iend.x)+(norm.x);
|
||||
y = (iend.y)+(norm.y);
|
||||
z = (iend.z)+(norm.z);
|
||||
@ -311,7 +315,18 @@ void PlayerController::updateInteraction(){
|
||||
}
|
||||
if (Events::jactive(BIND_PLAYER_PICK)){
|
||||
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 {
|
||||
selectedBlockId = -1;
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "../../voxels/voxel.h"
|
||||
#include "../../lighting/Lighting.h"
|
||||
#include "../../logic/BlocksController.h"
|
||||
#include "../../engine.h"
|
||||
|
||||
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* == 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) {
|
||||
lua_pushnumber(L, scripting::level->world->daytime);
|
||||
return 1;
|
||||
@ -266,6 +285,7 @@ static int l_is_replaceable_at(lua_State* L) {
|
||||
lua_setglobal(L, NAME))
|
||||
|
||||
void apilua::create_funcs(lua_State* L) {
|
||||
luaL_openlib(L, "pack", packlib, 0);
|
||||
luaL_openlib(L, "world", worldlib, 0);
|
||||
luaL_openlib(L, "player", playerlib, 0);
|
||||
|
||||
|
||||
@ -11,19 +11,19 @@
|
||||
#include "../../voxels/Block.h"
|
||||
#include "../../items/ItemDef.h"
|
||||
#include "../../logic/BlocksController.h"
|
||||
#include "../../engine.h"
|
||||
#include "api_lua.h"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
namespace scripting {
|
||||
extern lua_State* L;
|
||||
extern EnginePaths* paths;
|
||||
}
|
||||
|
||||
Engine* scripting::engine = nullptr;
|
||||
lua_State* scripting::L = nullptr;
|
||||
Level* scripting::level = nullptr;
|
||||
const Content* scripting::content = nullptr;
|
||||
EnginePaths* scripting::paths = nullptr;
|
||||
BlocksController* scripting::blocks = nullptr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void scripting::initialize(EnginePaths* paths) {
|
||||
scripting::paths = paths;
|
||||
void scripting::initialize(Engine* engine) {
|
||||
scripting::engine = engine;
|
||||
|
||||
L = luaL_newstate();
|
||||
if (L == nullptr) {
|
||||
@ -87,7 +87,7 @@ void scripting::on_world_load(Level* level, BlocksController* blocks) {
|
||||
scripting::level = level;
|
||||
scripting::content = level->content;
|
||||
scripting::blocks = blocks;
|
||||
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path file = paths->getResources()/fs::path("scripts/world.lua");
|
||||
std::string src = files::read_string(file);
|
||||
luaL_loadbuffer(L, src.c_str(), src.length(), file.string().c_str());
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class EnginePaths;
|
||||
class Engine;
|
||||
class Content;
|
||||
class Level;
|
||||
class Block;
|
||||
@ -14,11 +14,12 @@ struct item_funcs_set;
|
||||
class BlocksController;
|
||||
|
||||
namespace scripting {
|
||||
extern Engine* engine;
|
||||
extern const Content* content;
|
||||
extern Level* level;
|
||||
extern BlocksController* blocks;
|
||||
|
||||
void initialize(EnginePaths* paths);
|
||||
void initialize(Engine* engine);
|
||||
void on_world_load(Level* level, BlocksController* blocks);
|
||||
void on_world_quit();
|
||||
void update_block(const Block* block, int x, int y, int z);
|
||||
|
||||
17
src/maths/fastmaths.h
Normal file
17
src/maths/fastmaths.h
Normal file
@ -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_
|
||||
@ -5,6 +5,7 @@
|
||||
#include "../world/Level.h"
|
||||
#include "../window/Events.h"
|
||||
#include "../window/Camera.h"
|
||||
#include "../items/Inventory.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
@ -18,12 +19,16 @@ const float JUMP_FORCE = 8.0f;
|
||||
|
||||
Player::Player(glm::vec3 position, float speed) :
|
||||
speed(speed),
|
||||
chosenItem(0),
|
||||
chosenSlot(0),
|
||||
camera(new Camera(position, glm::radians(90.0f))),
|
||||
spCamera(new Camera(position, glm::radians(90.0f))),
|
||||
tpCamera(new Camera(position, glm::radians(90.0f))),
|
||||
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(
|
||||
@ -118,14 +123,18 @@ void Player::teleport(glm::vec3 position) {
|
||||
hitbox->position = position;
|
||||
}
|
||||
|
||||
void Player::setChosenItem(itemid_t id) {
|
||||
chosenItem = id;
|
||||
void Player::setChosenSlot(int index) {
|
||||
chosenSlot = index;
|
||||
}
|
||||
|
||||
itemid_t Player::getChosenItem() const {
|
||||
return chosenItem;
|
||||
int Player::getChosenSlot() const {
|
||||
return chosenSlot;
|
||||
}
|
||||
|
||||
float Player::getSpeed() const {
|
||||
return speed;
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Player::getInventory() const {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
class Camera;
|
||||
class Hitbox;
|
||||
class Inventory;
|
||||
class PhysicsSolver;
|
||||
class Chunks;
|
||||
class Level;
|
||||
@ -30,11 +31,12 @@ struct PlayerInput {
|
||||
|
||||
class Player {
|
||||
float speed;
|
||||
itemid_t chosenItem;
|
||||
int chosenSlot;
|
||||
public:
|
||||
std::shared_ptr<Camera> camera, spCamera, tpCamera;
|
||||
std::shared_ptr<Camera> currentCamera;
|
||||
std::unique_ptr<Hitbox> hitbox;
|
||||
std::shared_ptr<Inventory> inventory;
|
||||
bool flight = false;
|
||||
bool noclip = false;
|
||||
bool debug = false;
|
||||
@ -43,15 +45,17 @@ public:
|
||||
glm::vec2 cam = {};
|
||||
|
||||
Player(glm::vec3 position, float speed);
|
||||
~Player() = default;
|
||||
~Player();
|
||||
|
||||
void teleport(glm::vec3 position);
|
||||
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;
|
||||
|
||||
std::shared_ptr<Inventory> getInventory() const;
|
||||
};
|
||||
|
||||
#endif /* SRC_OBJECTS_PLAYER_H_ */
|
||||
|
||||
@ -81,7 +81,7 @@ public:
|
||||
std::vector<glm::vec3> modelExtraPoints = {}; //initially made for tetragons
|
||||
std::vector<UVRegion> modelUVs = {}; // boxes' tex-UVs also there
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
unsigned char drawGroup = 0;
|
||||
ubyte drawGroup = 0;
|
||||
BlockModel model = BlockModel::block;
|
||||
bool lightPassing = false;
|
||||
bool skyLightPassing = false;
|
||||
@ -95,6 +95,7 @@ public:
|
||||
AABB hitbox;
|
||||
BlockRotProfile rotations;
|
||||
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
||||
std::string scriptName = name.substr(name.find(':')+1);
|
||||
|
||||
struct {
|
||||
blockid_t id;
|
||||
|
||||
14
vcpkg.json
Normal file
14
vcpkg.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "voxelengine",
|
||||
"version-string": "1.0.0",
|
||||
"dependencies": [
|
||||
"opengl",
|
||||
"openal-soft",
|
||||
"glfw3",
|
||||
"glew",
|
||||
"glm",
|
||||
"libspng",
|
||||
"zlib",
|
||||
"luajit"
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user