Compare commits
No commits in common. "master" and "feature/studio-tools" have entirely different histories.
master
...
feature/st
17
.gitignore
vendored
17
.gitignore
vendored
|
@ -1,14 +1,19 @@
|
|||
/bin/
|
||||
/lib/
|
||||
/build/
|
||||
bin/
|
||||
lib/
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
|
||||
# Qt
|
||||
/*.pro.user*
|
||||
/CMakeLists.txt.user*
|
||||
.lupdate/
|
||||
*.pro.user*
|
||||
CMakeLists.txt.user*
|
||||
*_autogen/
|
||||
|
||||
# Clangd
|
||||
/compile_commands.json
|
||||
/.cache
|
||||
|
||||
# Gdb
|
||||
/.gdb_history
|
||||
.gdb_history
|
|
@ -1,19 +1,14 @@
|
|||
cmake_minimum_required(VERSION 3.30.0)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
cmake_minimum_required(VERSION 3.5.0)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
project(openblocks VERSION 0.1.0)
|
||||
set(OpenGL_GL_PREFERENCE "GLVND")
|
||||
|
||||
set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" )
|
||||
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib )
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(client)
|
||||
add_subdirectory(editor)
|
||||
|
||||
|
||||
install(FILES $<TARGET_RUNTIME_DLLS:editor> TYPE BIN)
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "vcpkg",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"inherits": "vcpkg",
|
||||
"environment": {
|
||||
"VCPKG_ROOT": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\vcpkg\\vcpkg.exe"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -53,7 +53,6 @@ uniform int numPointLights;
|
|||
uniform DirLight sunLight;
|
||||
uniform Material material;
|
||||
uniform sampler2DArray studs;
|
||||
uniform float transparency;
|
||||
|
||||
// Functions
|
||||
|
||||
|
@ -73,7 +72,7 @@ void main() {
|
|||
}
|
||||
|
||||
vec4 studPx = texture(studs, vec3(vTexCoords, vSurfaceZ));
|
||||
FragColor = vec4(mix(result, vec3(studPx), studPx.w), 1) * (1-transparency);
|
||||
FragColor = vec4(mix(result, vec3(studPx), studPx.w), 1);
|
||||
}
|
||||
|
||||
vec3 calculateDirectionalLight(DirLight light) {
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
find_package(SDL2 REQUIRED)
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
|
||||
find_package(glfw3 REQUIRED)
|
||||
|
||||
add_executable(client "src/main.cpp")
|
||||
target_link_libraries(client PRIVATE ${SDL2_LIBRARIES} openblocks glfw)
|
||||
target_link_libraries(client PRIVATE openblocks glfw)
|
|
@ -1,30 +0,0 @@
|
|||
# Distributed under the OSI-approved BSD 3-Clause License.
|
||||
# Copyright Stefano Sinigardi
|
||||
|
||||
#.rst:
|
||||
# FindStb
|
||||
# ------------
|
||||
#
|
||||
# Find the Stb include headers.
|
||||
#
|
||||
# Result Variables
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# This module defines the following variables:
|
||||
#
|
||||
# ``Stb_FOUND``
|
||||
# True if Stb library found
|
||||
#
|
||||
# ``Stb_INCLUDE_DIR``
|
||||
# Location of Stb headers
|
||||
#
|
||||
|
||||
include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
|
||||
include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake)
|
||||
|
||||
if(NOT Stb_INCLUDE_DIR)
|
||||
find_path(Stb_INCLUDE_DIR NAMES stb_image.h PATHS ${Stb_DIR} PATH_SUFFIXES include stb include/stb)
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(Stb DEFAULT_MSG Stb_INCLUDE_DIR)
|
||||
mark_as_advanced(Stb_INCLUDE_DIR)
|
|
@ -1,18 +1,24 @@
|
|||
find_package(OpenGL REQUIRED COMPONENTS OpenGL)
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
|
||||
find_package(GLEW REQUIRED)
|
||||
include_directories(${GLEW_INCLUDE_DIRS})
|
||||
|
||||
find_package(GLUT REQUIRED)
|
||||
include_directories(${GLUT_INCLUDE_DIRS})
|
||||
|
||||
find_package(OpenGL)
|
||||
find_package(glm CONFIG REQUIRED)
|
||||
# find_package(assimp REQUIRED)
|
||||
find_package(ReactPhysics3D REQUIRED)
|
||||
find_package(pugixml 1.15 REQUIRED)
|
||||
find_package(pugixml REQUIRED)
|
||||
|
||||
find_package(Stb REQUIRED)
|
||||
include_directories(${Stb_INCLUDE_DIR})
|
||||
file(MAKE_DIRECTORY bin)
|
||||
|
||||
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
|
||||
add_library(openblocks STATIC ${SOURCES})
|
||||
add_library(openblocks ${SOURCES})
|
||||
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
|
||||
target_link_libraries(openblocks ${GLEW_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml)
|
||||
target_link_libraries(openblocks ${SDL2_LIBRARIES} ${GLEW_LIBRARIES} ${GLUT_LIBRARIES} OpenGL::GL OpenGL::GLU ReactPhysics3D::ReactPhysics3D pugixml::pugixml)
|
||||
target_include_directories(openblocks PUBLIC "src" "../include")
|
|
@ -4,7 +4,7 @@
|
|||
#define IMPL_WRAPPER_CLASS(CLASS_NAME, WRAPPED_TYPE, TYPE_NAME) Data::CLASS_NAME::CLASS_NAME(WRAPPED_TYPE in) : value(in) {} \
|
||||
Data::CLASS_NAME::~CLASS_NAME() = default; \
|
||||
Data::CLASS_NAME::operator const WRAPPED_TYPE() const { return value; } \
|
||||
const Data::TypeInfo Data::CLASS_NAME::TYPE = { .name = TYPE_NAME, .deserializer = &Data::CLASS_NAME::Deserialize, .fromString = &Data::CLASS_NAME::FromString }; \
|
||||
const Data::TypeInfo Data::CLASS_NAME::TYPE = { .name = TYPE_NAME, .deserializer = &Data::CLASS_NAME::Deserialize }; \
|
||||
const Data::TypeInfo& Data::CLASS_NAME::GetType() const { return Data::CLASS_NAME::TYPE; }; \
|
||||
void Data::CLASS_NAME::Serialize(pugi::xml_node* node) const { node->text().set(std::string(this->ToString())); }
|
||||
|
||||
|
@ -45,11 +45,6 @@ Data::Variant Data::Bool::Deserialize(pugi::xml_node* node) {
|
|||
return Data::Bool(node->text().as_bool());
|
||||
}
|
||||
|
||||
Data::Variant Data::Bool::FromString(std::string string) {
|
||||
return Data::Bool(string[0] == 't' || string[0] == 'T' || string[0] == '1' || string[0] == 'y' || string[0] == 'Y');
|
||||
}
|
||||
|
||||
|
||||
const Data::String Data::Int::ToString() const {
|
||||
return Data::String(std::to_string(value));
|
||||
}
|
||||
|
@ -58,11 +53,6 @@ Data::Variant Data::Int::Deserialize(pugi::xml_node* node) {
|
|||
return Data::Int(node->text().as_int());
|
||||
}
|
||||
|
||||
Data::Variant Data::Int::FromString(std::string string) {
|
||||
return Data::Int(std::stoi(string));
|
||||
}
|
||||
|
||||
|
||||
const Data::String Data::Float::ToString() const {
|
||||
return Data::String(std::to_string(value));
|
||||
}
|
||||
|
@ -71,11 +61,6 @@ Data::Variant Data::Float::Deserialize(pugi::xml_node* node) {
|
|||
return Data::Float(node->text().as_float());
|
||||
}
|
||||
|
||||
Data::Variant Data::Float::FromString(std::string string) {
|
||||
return Data::Float(std::stof(string));
|
||||
}
|
||||
|
||||
|
||||
const Data::String Data::String::ToString() const {
|
||||
return *this;
|
||||
}
|
||||
|
@ -83,7 +68,3 @@ const Data::String Data::String::ToString() const {
|
|||
Data::Variant Data::String::Deserialize(pugi::xml_node* node) {
|
||||
return Data::String(node->text().as_string());
|
||||
}
|
||||
|
||||
Data::Variant Data::String::FromString(std::string string) {
|
||||
return Data::String(string);
|
||||
}
|
|
@ -16,18 +16,16 @@ public: \
|
|||
virtual const Data::String ToString() const override; \
|
||||
virtual void Serialize(pugi::xml_node* node) const override; \
|
||||
static Data::Variant Deserialize(pugi::xml_node* node); \
|
||||
static Data::Variant FromString(std::string); \
|
||||
};
|
||||
|
||||
namespace Data {
|
||||
class Variant;
|
||||
typedef std::function<Data::Variant(pugi::xml_node*)> Deserializer;
|
||||
typedef std::function<Data::Variant(std::string)> FromString;
|
||||
|
||||
struct TypeInfo {
|
||||
std::string name;
|
||||
Deserializer deserializer;
|
||||
FromString fromString;
|
||||
TypeInfo(const TypeInfo&) = delete;
|
||||
};
|
||||
|
||||
class String;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
// #include "meta.h" // IWYU pragma: keep
|
||||
|
||||
const Data::CFrame Data::CFrame::IDENTITY(glm::vec3(0, 0, 0), glm::mat3(1.f));
|
||||
const Data::CFrame Data::CFrame::YToZ(glm::vec3(0, 0, 0), glm::mat3(glm::vec3(1, 0, 0), glm::vec3(0, 0, 1), glm::vec3(0, 1, 0)));
|
||||
|
||||
Data::CFrame::CFrame(float x, float y, float z, float R00, float R01, float R02, float R10, float R11, float R12, float R20, float R21, float R22)
|
||||
: translation(x, y, z)
|
||||
|
|
|
@ -31,7 +31,6 @@ namespace Data {
|
|||
~CFrame();
|
||||
|
||||
static const CFrame IDENTITY;
|
||||
static const CFrame YToZ;
|
||||
|
||||
virtual const TypeInfo& GetType() const override;
|
||||
static const TypeInfo TYPE;
|
||||
|
|
|
@ -67,9 +67,8 @@ std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
|
|||
for (HandleFace face : HandleFace::Faces) {
|
||||
Data::CFrame cframe = GetCFrameOfHandle(face);
|
||||
// Implement manual detection via boxes instead of... this shit
|
||||
// This code also hardly works, and is not good at all... Hooo nope.
|
||||
rp3d::RigidBody* body = world->createRigidBody(Data::CFrame::IDENTITY + cframe.Position());
|
||||
body->addCollider(common.createBoxShape(cframe.Rotation() * Data::Vector3(HandleSize(face) / 2.f)), rp3d::Transform::identity());
|
||||
rp3d::RigidBody* body = world->createRigidBody(cframe);
|
||||
body->addCollider(common.createBoxShape(Data::Vector3(.5, .5, .5)), rp3d::Transform::identity());
|
||||
|
||||
rp3d::RaycastInfo info;
|
||||
if (body->raycast(ray, info)) {
|
||||
|
@ -82,9 +81,3 @@ std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
|
|||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Data::Vector3 Handles::HandleSize(HandleFace face) {
|
||||
if (handlesType == HandlesType::MoveHandles)
|
||||
return glm::vec3(0.5f, 0.5f, 2.f);
|
||||
return glm::vec3(1,1,1);
|
||||
}
|
|
@ -24,20 +24,12 @@ class HandleFace {
|
|||
static std::array<HandleFace, 6> Faces;
|
||||
};
|
||||
|
||||
enum HandlesType {
|
||||
MoveHandles,
|
||||
ScaleHandles,
|
||||
RotateHandles,
|
||||
};
|
||||
|
||||
class Handles : public Instance {
|
||||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
||||
bool active;
|
||||
std::optional<std::weak_ptr<Part>> adornee;
|
||||
HandlesType handlesType;
|
||||
|
||||
// inline std::optional<std::weak_ptr<Part>> GetAdornee() { return adornee; }
|
||||
// inline void SetAdornee(std::optional<std::weak_ptr<Part>> newAdornee) { this->adornee = newAdornee; updateAdornee(); };
|
||||
|
||||
|
@ -47,7 +39,6 @@ public:
|
|||
bool worldMode = false;
|
||||
Data::CFrame GetCFrameOfHandle(HandleFace face);
|
||||
Data::CFrame PartCFrameFromHandlePos(HandleFace face, Data::Vector3 newPos);
|
||||
Data::Vector3 HandleSize(HandleFace face);
|
||||
std::optional<HandleFace> RaycastHandle(rp3d::Ray ray);
|
||||
|
||||
static inline std::shared_ptr<Handles> New() { return std::make_shared<Handles>(); };
|
||||
|
|
|
@ -95,10 +95,6 @@ Part::Part(PartConstructParams params): Instance(&TYPE), cframe(Data::CFrame(par
|
|||
.backingField = &color,
|
||||
.type = &Data::Color3::TYPE,
|
||||
.codec = fieldCodecOf<Data::Color3>(),
|
||||
}}, { "Transparency", {
|
||||
.backingField = &transparency,
|
||||
.type = &Data::Float::TYPE,
|
||||
.codec = fieldCodecOf<Data::Float, float>(),
|
||||
} }
|
||||
}
|
||||
});
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
Data::CFrame cframe;
|
||||
glm::vec3 size;
|
||||
Data::Color3 color;
|
||||
float transparency = 0.f;
|
||||
bool selected = false;
|
||||
|
||||
bool anchored = false;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -67,11 +67,6 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
|||
|
||||
void renderParts() {
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CW);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Use shader
|
||||
shader->use();
|
||||
|
@ -116,17 +111,12 @@ void renderParts() {
|
|||
// Pass in the camera position
|
||||
shader->set("viewPos", camera.cameraPos);
|
||||
|
||||
// Sort by nearest
|
||||
std::map<float, std::shared_ptr<Part>> sorted;
|
||||
// TODO: Same as todo in src/physics/simulation.cpp
|
||||
for (InstanceRef inst : workspace()->GetChildren()) {
|
||||
if (inst->GetClass()->className != "Part") continue;
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
|
||||
if (part->transparency > 0.00001) {
|
||||
float distance = glm::length(glm::vec3(Data::Vector3(camera.cameraPos) - part->position()));
|
||||
sorted[distance] = part;
|
||||
} else {
|
||||
glm::mat4 model = part->cframe;
|
||||
if (part->name == "camera") model = camera.getLookAt();
|
||||
if (inst->name == "camera") model = camera.getLookAt();
|
||||
model = glm::scale(model, part->size);
|
||||
shader->set("model", model);
|
||||
shader->set("material", Material {
|
||||
|
@ -137,39 +127,14 @@ void renderParts() {
|
|||
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
|
||||
shader->set("normalMatrix", normalMatrix);
|
||||
shader->set("texScale", part->size);
|
||||
shader->set("transparency", part->transparency);
|
||||
|
||||
CUBE_MESH->bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, CUBE_MESH->vertexCount);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Same as todo in src/physics/simulation.cpp
|
||||
// According to LearnOpenGL, std::map automatically sorts its contents.
|
||||
for (std::map<float, std::shared_ptr<Part>>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); it++) {
|
||||
std::shared_ptr<Part> part = it->second;
|
||||
glm::mat4 model = part->cframe;
|
||||
if (part->name == "camera") model = camera.getLookAt();
|
||||
model = glm::scale(model, part->size);
|
||||
shader->set("model", model);
|
||||
shader->set("material", Material {
|
||||
.diffuse = part->color,
|
||||
.specular = glm::vec3(0.5f, 0.5f, 0.5f),
|
||||
.shininess = 16.0f,
|
||||
});
|
||||
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
|
||||
shader->set("normalMatrix", normalMatrix);
|
||||
shader->set("texScale", part->size);
|
||||
shader->set("transparency", part->transparency);
|
||||
|
||||
CUBE_MESH->bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, CUBE_MESH->vertexCount);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
}
|
||||
}
|
||||
|
||||
void renderSkyBox() {
|
||||
glDepthMask(GL_FALSE);
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
skyboxShader->use();
|
||||
|
||||
|
@ -190,7 +155,6 @@ void renderHandles() {
|
|||
if (!editorToolHandles->adornee.has_value() || !editorToolHandles->active) return;
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// Use shader
|
||||
handleShader->use();
|
||||
|
@ -213,7 +177,7 @@ void renderHandles() {
|
|||
|
||||
for (auto face : HandleFace::Faces) {
|
||||
glm::mat4 model = editorToolHandles->GetCFrameOfHandle(face);
|
||||
model = glm::scale(model, (glm::vec3)editorToolHandles->HandleSize(face));
|
||||
model = glm::scale(model, glm::vec3(1,1,1));
|
||||
handleShader->set("model", model);
|
||||
handleShader->set("material", Material {
|
||||
.diffuse = glm::abs(face.normal),
|
||||
|
@ -223,18 +187,11 @@ void renderHandles() {
|
|||
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
|
||||
handleShader->set("normalMatrix", normalMatrix);
|
||||
|
||||
if (editorToolHandles->handlesType == HandlesType::MoveHandles) {
|
||||
ARROW_MESH->bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, ARROW_MESH->vertexCount);
|
||||
} else {
|
||||
SPHERE_MESH->bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, SPHERE_MESH->vertexCount);
|
||||
}
|
||||
}
|
||||
|
||||
// 2d square overlay
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
identityShader->use();
|
||||
identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f));
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <stb_image.h>
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
#include "skybox.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <stb_image.h>
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
Texture::Texture(const char* texturePath, unsigned int format, bool noMipMaps) {
|
||||
glGenTextures(1, &this->ID);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <stb_image.h>
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
Texture3D::Texture3D(const char* texturePath, unsigned int tileWidth, unsigned int tileHeight, unsigned int tileCount, unsigned int format) {
|
||||
glGenTextures(1, &this->ID);
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
#include <stb/stb_image.h>
|
9
deps.txt
9
deps.txt
|
@ -1,9 +1,10 @@
|
|||
opengl (Linux: glvnd, Windows: [built-in/none])
|
||||
glfw
|
||||
glew
|
||||
glm
|
||||
opengl
|
||||
assimp
|
||||
sdl2
|
||||
stb
|
||||
glfw
|
||||
glut
|
||||
glew
|
||||
qt6
|
||||
reactphysics3d
|
||||
pugixml
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.30.0)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(editor VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
|
@ -6,7 +6,7 @@ set(CMAKE_AUTOUIC ON)
|
|||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
@ -14,7 +14,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets LinguistTools)
|
||||
|
||||
|
||||
set(TS_FILES editor_en_US.ts)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
|
@ -66,42 +65,6 @@ endif()
|
|||
target_include_directories(editor PUBLIC "../core/src" "../include")
|
||||
target_link_libraries(editor PRIVATE openblocks Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
|
||||
# Qt6 does not include QOpenGLWidgets as part of Widgets base anymore, so
|
||||
# we have to include it manually
|
||||
if (${QT_VERSION} GREATER_EQUAL 6)
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS OpenGL OpenGLWidgets)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS OpenGL OpenGLWidgets)
|
||||
|
||||
target_include_directories(editor PUBLIC Qt6::OpenGL Qt6::OpenGLWidgets)
|
||||
target_link_libraries(editor PRIVATE Qt6::OpenGL Qt6::OpenGLWidgets)
|
||||
endif()
|
||||
|
||||
# Copy assets
|
||||
add_custom_command(
|
||||
TARGET editor POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/assets
|
||||
$<TARGET_FILE_DIR:editor>/assets)
|
||||
|
||||
# Copy Qt files
|
||||
if (WIN32)
|
||||
#include("${QT_DEPLOY_SUPPORT}")
|
||||
|
||||
# TODO: Add other translations
|
||||
add_custom_command(
|
||||
TARGET editor POST_BUILD
|
||||
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:editor> --translations en --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --plugindir $<TARGET_FILE_DIR:editor>/qtplugins
|
||||
)
|
||||
# No sense adding opengl-sw given that hardware acceleration is necessary, anyway
|
||||
# Also don't want to clutter with plugins, add only needed ones
|
||||
|
||||
# Copy qt.conf to override default plugins location
|
||||
add_custom_command(
|
||||
TARGET editor POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qt.conf $<TARGET_FILE_DIR:editor>/qt.conf
|
||||
)
|
||||
endif ()
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
|
@ -123,8 +86,6 @@ install(TARGETS editor
|
|||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
install(FILES $<TARGET_RUNTIME_DLLS:editor> TYPE BIN)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt_finalize_executable(editor)
|
||||
endif()
|
|
@ -138,9 +138,7 @@ void MainGLWidget::handleHandleDrag(QMouseEvent* evt) {
|
|||
|
||||
// Apply snapping in the current frame
|
||||
glm::vec3 diff = centerPoint - (glm::vec3)editorToolHandles->adornee->lock()->position();
|
||||
// printf("\n=======\nPre-snap: (%f, %f, %f)\n", diff.x, diff.y, diff.z);
|
||||
if (snappingFactor()) diff = frame.Rotation() * (glm::round(glm::vec3(frame.Inverse().Rotation() * diff) / snappingFactor()) * snappingFactor());
|
||||
// printf("Post-snap: (%f, %f, %f)\n", diff.x, diff.y, diff.z);
|
||||
if (snappingFactor()) diff = frame * (glm::round(glm::vec3(frame.Inverse() * diff) / snappingFactor()) * snappingFactor());
|
||||
|
||||
switch (mainWindow()->selectedTool) {
|
||||
case SelectedTool::SELECT: break;
|
||||
|
|
|
@ -12,20 +12,15 @@
|
|||
#include <QAbstractItemView>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <qglobal.h>
|
||||
#include <qwindowdefs.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "common.h"
|
||||
#include "editorcommon.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/datamodel.h"
|
||||
#include "objects/handles.h"
|
||||
#include "physics/simulation.h"
|
||||
#include "objects/part.h"
|
||||
#include "qfiledialog.h"
|
||||
#include "qclipboard.h"
|
||||
#include "qmimedata.h"
|
||||
#include "qitemselectionmodel.h"
|
||||
#include "qobject.h"
|
||||
#include "qsysinfo.h"
|
||||
|
||||
|
@ -41,7 +36,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
timer.start(33, this);
|
||||
setMouseTracking(true);
|
||||
|
||||
ui->explorerView->buildContextMenu();
|
||||
ConnectSelectionChangeHandler();
|
||||
|
||||
connect(ui->actionToolSelect, &QAction::triggered, this, [&]() { selectedTool = SelectedTool::SELECT; updateToolbars(); });
|
||||
connect(ui->actionToolMove, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::MOVE : SelectedTool::SELECT; updateToolbars(); });
|
||||
|
@ -72,124 +67,21 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
connect(ui->actionSave, &QAction::triggered, this, [&]() {
|
||||
std::optional<std::string> path;
|
||||
if (!dataModel->HasFile())
|
||||
path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + dataModel->name));
|
||||
path = QFileDialog::getSaveFileName(this, QString::fromStdString("Save " + dataModel->name), "", "*.obl").toStdString();
|
||||
if (path == "") return;
|
||||
|
||||
dataModel->SaveToFile(path);
|
||||
});
|
||||
|
||||
connect(ui->actionOpen, &QAction::triggered, this, [&]() {
|
||||
std::optional<std::string> path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptOpen);
|
||||
if (!path) return;
|
||||
std::shared_ptr<DataModel> newModel = DataModel::LoadFromFile(path.value());
|
||||
std::string path = QFileDialog::getOpenFileName(this, "Load file", "", "*.obl").toStdString();
|
||||
if (path == "") return;
|
||||
std::shared_ptr<DataModel> newModel = DataModel::LoadFromFile(path);
|
||||
dataModel = newModel;
|
||||
ui->explorerView->updateRoot(newModel);
|
||||
});
|
||||
|
||||
connect(ui->actionDelete, &QAction::triggered, this, [&]() {
|
||||
for (InstanceRefWeak inst : getSelection()) {
|
||||
if (inst.expired()) continue;
|
||||
inst.lock()->SetParent(std::nullopt);
|
||||
}
|
||||
setSelection(std::vector<InstanceRefWeak> {});
|
||||
});
|
||||
|
||||
connect(ui->actionCopy, &QAction::triggered, this, [&]() {
|
||||
pugi::xml_document rootDoc;
|
||||
for (InstanceRefWeak inst : getSelection()) {
|
||||
if (inst.expired()) continue;
|
||||
inst.lock()->Serialize(&rootDoc);
|
||||
}
|
||||
|
||||
std::ostringstream encoded;
|
||||
rootDoc.save(encoded);
|
||||
|
||||
QMimeData* mimeData = new QMimeData;
|
||||
mimeData->setData("application/xml", QByteArray::fromStdString(encoded.str()));
|
||||
QApplication::clipboard()->setMimeData(mimeData);
|
||||
});
|
||||
connect(ui->actionCut, &QAction::triggered, this, [&]() {
|
||||
pugi::xml_document rootDoc;
|
||||
for (InstanceRefWeak inst : getSelection()) {
|
||||
if (inst.expired()) continue;
|
||||
inst.lock()->Serialize(&rootDoc);
|
||||
inst.lock()->SetParent(std::nullopt);
|
||||
}
|
||||
|
||||
std::ostringstream encoded;
|
||||
rootDoc.save(encoded);
|
||||
|
||||
QMimeData* mimeData = new QMimeData;
|
||||
mimeData->setData("application/xml", QByteArray::fromStdString(encoded.str()));
|
||||
QApplication::clipboard()->setMimeData(mimeData);
|
||||
});
|
||||
|
||||
connect(ui->actionPaste, &QAction::triggered, this, [&]() {
|
||||
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
|
||||
if (!mimeData || !mimeData->hasFormat("application/xml")) return;
|
||||
QByteArray bytes = mimeData->data("application/xml");
|
||||
std::string encoded = bytes.toStdString();
|
||||
|
||||
pugi::xml_document rootDoc;
|
||||
rootDoc.load_string(encoded.c_str());
|
||||
|
||||
for (pugi::xml_node instNode : rootDoc.children()) {
|
||||
InstanceRef inst = Instance::Deserialize(&instNode);
|
||||
workspace()->AddChild(inst);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->actionPasteInto, &QAction::triggered, this, [&]() {
|
||||
if (getSelection().size() != 1 || getSelection()[0].expired()) return;
|
||||
|
||||
InstanceRef selectedParent = getSelection()[0].lock();
|
||||
|
||||
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
|
||||
if (!mimeData || !mimeData->hasFormat("application/xml")) return;
|
||||
QByteArray bytes = mimeData->data("application/xml");
|
||||
std::string encoded = bytes.toStdString();
|
||||
|
||||
pugi::xml_document rootDoc;
|
||||
rootDoc.load_string(encoded.c_str());
|
||||
|
||||
for (pugi::xml_node instNode : rootDoc.children()) {
|
||||
InstanceRef inst = Instance::Deserialize(&instNode);
|
||||
selectedParent->AddChild(inst);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->actionSaveModel, &QAction::triggered, this, [&]() {
|
||||
std::optional<std::string> path = openFileDialog("Openblocks Model (*.obm)", ".obm", QFileDialog::AcceptSave);
|
||||
if (!path) return;
|
||||
std::ofstream outStream(path.value());
|
||||
|
||||
// Serialized XML for exporting
|
||||
pugi::xml_document modelDoc;
|
||||
pugi::xml_node modelRoot = modelDoc.append_child("openblocks");
|
||||
|
||||
for (InstanceRefWeak inst : getSelection()) {
|
||||
if (inst.expired()) continue;
|
||||
inst.lock()->Serialize(&modelRoot);
|
||||
}
|
||||
|
||||
modelDoc.save(outStream);
|
||||
});
|
||||
|
||||
connect(ui->actionInsertModel, &QAction::triggered, this, [&]() {
|
||||
if (getSelection().size() != 1 || getSelection()[0].expired()) return;
|
||||
InstanceRef selectedParent = getSelection()[0].lock();
|
||||
|
||||
std::optional<std::string> path = openFileDialog("Openblocks Model (*.obm)", ".obm", QFileDialog::AcceptOpen);
|
||||
if (!path) return;
|
||||
std::ifstream inStream(path.value());
|
||||
|
||||
pugi::xml_document modelDoc;
|
||||
modelDoc.load(inStream);
|
||||
|
||||
for (pugi::xml_node instNode : modelDoc.child("openblocks").children("Item")) {
|
||||
InstanceRef inst = Instance::Deserialize(&instNode);
|
||||
selectedParent->AddChild(inst);
|
||||
}
|
||||
delete ui->explorerView->selectionModel();
|
||||
ui->explorerView->reset();
|
||||
ui->explorerView->setModel(new ExplorerModel(dataModel));
|
||||
ConnectSelectionChangeHandler();
|
||||
});
|
||||
|
||||
// Update handles
|
||||
|
@ -234,6 +126,17 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
syncPartPhysics(ui->mainWidget->lastPart);
|
||||
}
|
||||
|
||||
void MainWindow::ConnectSelectionChangeHandler() {
|
||||
// connect(ui->explorerView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [&](const QItemSelection &selected, const QItemSelection &deselected) {
|
||||
// if (selected.count() == 0) return;
|
||||
|
||||
// std::optional<InstanceRef> inst = selected.count() == 0 ? std::nullopt
|
||||
// : std::make_optional(((Instance*)selected.indexes()[0].internalPointer())->shared_from_this());
|
||||
|
||||
// ui->propertiesView->setSelected(inst);
|
||||
// });
|
||||
}
|
||||
|
||||
static std::chrono::time_point lastTime = std::chrono::steady_clock::now();
|
||||
void MainWindow::timerEvent(QTimerEvent* evt) {
|
||||
if (evt->timerId() != timer.timerId()) {
|
||||
|
@ -264,23 +167,6 @@ void MainWindow::updateToolbars() {
|
|||
if (selectedTool == SelectedTool::MOVE) editorToolHandles->worldMode = true;
|
||||
if (selectedTool == SelectedTool::SCALE) editorToolHandles->worldMode = false;
|
||||
editorToolHandles->active = selectedTool != SelectedTool::SELECT;
|
||||
editorToolHandles->handlesType =
|
||||
selectedTool == SelectedTool::MOVE ? HandlesType::MoveHandles
|
||||
: selectedTool == SelectedTool::SCALE ? HandlesType::ScaleHandles
|
||||
: selectedTool == SelectedTool::ROTATE ? HandlesType::RotateHandles
|
||||
: HandlesType::ScaleHandles;
|
||||
}
|
||||
|
||||
std::optional<std::string> MainWindow::openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title) {
|
||||
QFileDialog dialog(this);
|
||||
if (title != "") dialog.setWindowTitle(title);
|
||||
dialog.setNameFilters(QStringList { filter, "All Files (*)" });
|
||||
dialog.setDefaultSuffix(defaultExtension);
|
||||
dialog.setAcceptMode(acceptMode);
|
||||
if (!dialog.exec())
|
||||
return std::nullopt;
|
||||
|
||||
return dialog.selectedFiles().front().toStdString();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "qmenu.h"
|
||||
#include <QMainWindow>
|
||||
#include <QLineEdit>
|
||||
#include <qfiledialog.h>
|
||||
|
||||
enum SelectedTool {
|
||||
SELECT,
|
||||
|
@ -45,7 +44,6 @@ private:
|
|||
|
||||
void updateToolbars();
|
||||
void timerEvent(QTimerEvent*) override;
|
||||
|
||||
std::optional<std::string> openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title = "");
|
||||
void ConnectSelectionChangeHandler();
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1027</width>
|
||||
<height>30</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
@ -115,12 +115,6 @@
|
|||
<addaction name="actionToolScale"/>
|
||||
<addaction name="actionToolRotate"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDelete"/>
|
||||
<addaction name="actionCopy"/>
|
||||
<addaction name="actionCut"/>
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="actionPasteInto"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionGridSnap1"/>
|
||||
<addaction name="actionGridSnap05"/>
|
||||
<addaction name="actionGridSnapOff"/>
|
||||
|
@ -321,113 +315,6 @@
|
|||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCopy">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-copy"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Copy objects to clipboard</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+C</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCut">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-cut"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cut</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Cut objects into clipboard</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+X</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPaste">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-paste"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Paste</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Paste objects from clipboard</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+V</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPasteInto">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-paste"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Paste Into</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Paste objects from clipboard into selected object</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+V</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-delete"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete Object</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Delete selected objects</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveModel">
|
||||
<property name="text">
|
||||
<string>Save Model to File</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Saves objects to file as XML model</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInsertModel">
|
||||
<property name="text">
|
||||
<string>Insert Model from File</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Insert model from XML file</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
|
|
@ -234,12 +234,6 @@ bool ExplorerModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i
|
|||
return true;
|
||||
}
|
||||
|
||||
void ExplorerModel::updateRoot(InstanceRef newRoot) {
|
||||
beginResetModel();
|
||||
rootItem = newRoot;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QMimeData* ExplorerModel::mimeData(const QModelIndexList& indexes) const {
|
||||
// application/x-openblocks-instance-pointers
|
||||
DragDropSlot* slot = new DragDropSlot();
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/part.h"
|
||||
#include "qabstractitemmodel.h"
|
||||
#include "qevent.h"
|
||||
#include "qmenu.h"
|
||||
#include "qnamespace.h"
|
||||
#include "qtreeview.h"
|
||||
#include <QOpenGLWidget>
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
|
||||
// #ifndef EXPLORERMODEL_H
|
||||
// #define EXPLORERMODEL_H
|
||||
|
||||
class ExplorerModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
@ -36,8 +42,6 @@ public:
|
|||
Qt::DropActions supportedDropActions() const override;
|
||||
InstanceRef fromIndex(const QModelIndex index) const;
|
||||
QModelIndex ObjectToIndex(InstanceRef item);
|
||||
|
||||
void updateRoot(InstanceRef newRoot);
|
||||
private:
|
||||
InstanceRef rootItem;
|
||||
QModelIndex toIndex(InstanceRef item);
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
#include "explorerview.h"
|
||||
#include "explorermodel.h"
|
||||
#include "mainwindow.h"
|
||||
#include "../ui_mainwindow.h"
|
||||
#include "common.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/workspace.h"
|
||||
#include "qabstractitemmodel.h"
|
||||
#include <qaction.h>
|
||||
#include <qnamespace.h>
|
||||
#include "qaction.h"
|
||||
#include "qnamespace.h"
|
||||
#include <qitemselectionmodel.h>
|
||||
|
||||
#define M_mainWindow dynamic_cast<MainWindow*>(window())
|
||||
|
||||
ExplorerView::ExplorerView(QWidget* parent):
|
||||
QTreeView(parent),
|
||||
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(dataModel))) {
|
||||
|
@ -60,6 +57,8 @@ ExplorerView::ExplorerView(QWidget* parent):
|
|||
this->selectionModel()->select(index, QItemSelectionModel::SelectionFlag::Select);
|
||||
}
|
||||
});
|
||||
|
||||
buildContextMenu();
|
||||
}
|
||||
|
||||
ExplorerView::~ExplorerView() {
|
||||
|
@ -68,23 +67,19 @@ ExplorerView::~ExplorerView() {
|
|||
void ExplorerView::keyPressEvent(QKeyEvent* event) {
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Delete:
|
||||
M_mainWindow->ui->actionDelete->trigger();
|
||||
actionDelete->trigger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ExplorerView::buildContextMenu() {
|
||||
contextMenu.addAction(M_mainWindow->ui->actionDelete);
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(M_mainWindow->ui->actionCopy);
|
||||
contextMenu.addAction(M_mainWindow->ui->actionCut);
|
||||
contextMenu.addAction(M_mainWindow->ui->actionPaste);
|
||||
contextMenu.addAction(M_mainWindow->ui->actionPasteInto);
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(M_mainWindow->ui->actionSaveModel);
|
||||
contextMenu.addAction(M_mainWindow->ui->actionInsertModel);
|
||||
}
|
||||
// This will leak memory. Anyway...
|
||||
contextMenu.addAction(this->actionDelete = new QAction(QIcon("assets/icons/editor/delete"), "Delete"));
|
||||
|
||||
void ExplorerView::updateRoot(InstanceRef newRoot) {
|
||||
model.updateRoot(newRoot);
|
||||
connect(actionDelete, &QAction::triggered, this, [&]() {
|
||||
QModelIndexList selectedIndexes = this->selectionModel()->selectedIndexes();
|
||||
for (QModelIndex index : selectedIndexes) {
|
||||
model.fromIndex(index)->SetParent(std::nullopt);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -20,10 +20,18 @@ public:
|
|||
|
||||
void keyPressEvent(QKeyEvent*) override;
|
||||
// void dropEvent(QDropEvent*) override;
|
||||
|
||||
void buildContextMenu();
|
||||
void updateRoot(InstanceRef newRoot);
|
||||
private:
|
||||
ExplorerModel model;
|
||||
QMenu contextMenu;
|
||||
|
||||
// TODO: Move these to a separate top-level namespace so these can be
|
||||
// accessed from multiple locations
|
||||
QAction* actionDelete;
|
||||
QAction* actionCopy;
|
||||
QAction* actionCut;
|
||||
QAction* actionPaste;
|
||||
QAction* actionPasteInto;
|
||||
QAction* actionSelectChildren;
|
||||
|
||||
void buildContextMenu();
|
||||
};
|
|
@ -56,10 +56,10 @@ bool PropertiesModel::setData(const QModelIndex &index, const QVariant &value, i
|
|||
|
||||
switch (role) {
|
||||
case Qt::EditRole:
|
||||
if (!meta.type->fromString)
|
||||
if (meta.type != &Data::String::TYPE)
|
||||
return false;
|
||||
|
||||
selectedItem->SetPropertyValue(propertyName, meta.type->fromString(value.toString().toStdString()));
|
||||
selectedItem->SetPropertyValue(propertyName, value.toString().toStdString());
|
||||
return true;
|
||||
case Qt::CheckStateRole:
|
||||
if (meta.type != &Data::Bool::TYPE)
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[Paths]
|
||||
Plugins = "qtplugins"
|
4
run.sh
4
run.sh
|
@ -1,9 +1,7 @@
|
|||
if [ $# -eq 0 ] || ([ "$1" != "editor" ] && [ "$1" != "client" ]); then echo "Argument missing, must be 'client' or 'editor'"; exit; fi
|
||||
|
||||
[ "$2" = "-debug" ] && CMAKE_OPTS=-DCMAKE_BUILD_TYPE=Debug
|
||||
[ "$2" = "-release" ] && CMAKE_OPTS=-DCMAKE_BUILD_TYPE=Release
|
||||
[ "$2" = "-reldbg" ] && CMAKE_OPTS=-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
|
||||
[ "$3" = "-gdb" ] && PRE_COMMAND="gdb -ex run "
|
||||
|
||||
cmake -Bbuild $CMAKE_OPTS . && (cd build; cmake --build .; cd ..) && $PRE_COMMAND ./build/bin/$1
|
||||
cmake $CMAKE_OPTS . && cmake --build . && $PRE_COMMAND ./bin/$1
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"default-registry": {
|
||||
"kind": "git",
|
||||
"baseline": "0c4cf19224a049cf82f4521e29e39f7bd680440c",
|
||||
"repository": "https://github.com/microsoft/vcpkg"
|
||||
},
|
||||
"registries": [
|
||||
{
|
||||
"kind": "artifact",
|
||||
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
|
||||
"name": "microsoft"
|
||||
}
|
||||
]
|
||||
}
|
10
vcpkg.json
10
vcpkg.json
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"dependencies": [
|
||||
"glew",
|
||||
"glfw3",
|
||||
"glm",
|
||||
{ "name": "pugixml", "version>=": "1.15" },
|
||||
"sdl2",
|
||||
"stb"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue