diff --git a/CMakeLists.txt b/CMakeLists.txt index ff414c0..beec18c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,13 @@ function(assign_source_group) endforeach() endfunction(assign_source_group) +function(add_bigobj_flag target) + if(MSVC) + # MSVC requires the /bigobj flag if the number of sections gets too big. + target_compile_options(${target} PRIVATE /bigobj) + endif() +endfunction() + # Set output directories set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) @@ -100,6 +107,7 @@ endif() # Automatically search for source files. include_directories("${CMAKE_SOURCE_DIR}/src") +include_directories(graphqlschema ${CMAKE_CURRENT_BINARY_DIR}/src) file(GLOB_RECURSE source_files "src/*.hpp" "src/*.cpp" @@ -143,12 +151,39 @@ message(STATUS "STATIC_IMAGE_RESOURCES: ${STATIC_IMAGE_RESOURCES}") message(STATUS "STATIC_FONT_RESOURCES: ${STATIC_FONT_RESOURCES}") message(STATUS "STATIC_TYPE_SYSTEM_RESOURCES: ${STATIC_TYPE_SYSTEM_RESOURCES}") +# If really needed: here you can enable generating the graphql API (stubs) +# afterwards you will need to implement functionality for each stub. + +option(REGENERATE_GRAPHQL_API_STUBS "Replace the GraphQL API implementation with new stubs." OFF) +# if(REGENERATE_GRAPHQL_API_STUBS) + find_program (SCHEMAGEN schemagen PATHS ${CONAN_BIN_DIRS_CPPGRAPHQLGEN}) + + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src/graphql) + add_custom_command( + OUTPUT + src/graphql/EntitiesSchema.cpp + src/graphql/EntitiesSchema.h + COMMAND ${SCHEMAGEN} --schema="${CMAKE_CURRENT_SOURCE_DIR}/src/graphql/schema.entities.graphql" --prefix="Entities" --namespace="entities" + DEPENDS ${SCHEMAGEN} src/graphql/schema.entities.graphql + WORKING_DIRECTORY src/graphql + COMMENT "Generating mock GraphQL Schema files" + ) + + # force the generation of samples on the default build target + add_custom_target(regenerate_graphql_schema ALL + DEPENDS + src/graphql/EntitiesSchema.cpp + ) +# endif(REGENERATE_GRAPHQL_API_STUBS) + +list(REMOVE_ITEM LIBRARY_SOURCE_FILES "src/graphql/EntitiesSchema.cpp") +add_library(graphqlschema STATIC src/graphql/EntitiesSchema.cpp) +target_include_directories(graphqlschema PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/src/graphql) +add_bigobj_flag(graphqlschema) + # Entity-system library add_library(inexor-entity-system-lib ${LIBRARY_SOURCE_FILES}) -target_link_libraries(inexor-entity-system-lib ${CONAN_LIBS}) -#if(APPLE) <- Fohlen, can you verify this is not needed? - # target_link_libraries(inexor-entity-system-lib "-framework CoreFoundation") -#endif() +target_link_libraries(inexor-entity-system-lib graphqlschema ${CONAN_LIBS}) # Inexor standalone application. add_executable(inexor-standalone @@ -157,7 +192,7 @@ add_executable(inexor-standalone ${STATIC_IMAGE_RESOURCES} ${STATIC_FONT_RESOURCES} ${STATIC_TYPE_SYSTEM_RESOURCES}) -target_link_libraries(inexor-standalone PUBLIC inexor-entity-system-lib) +target_link_libraries(inexor-standalone PUBLIC graphqlschema inexor-entity-system-lib) target_link_libraries(inexor-standalone PUBLIC ${CONAN_LIBS}) target_link_libraries(inexor-standalone PRIVATE Corrade::Utility) if(APPLE) diff --git a/README.md b/README.md index bd82219..fb3e677 100644 --- a/README.md +++ b/README.md @@ -6,25 +6,6 @@ In contrast to Sauerbraten, Inexor adds a lot of functionality and strives to st The goal of this project is to be more flexible and create an environment where development is easy, fast and where creativity can prosper. -## How is Inexor organized? - -We are a non-hierarchical organization. This means we are simply a group of people with different ideas working together without a leader making all the decisions. Anyone of us is free to work on the particular things they want to. -For this organization to work properly we rely on good communication. We are on Telegram and Mumble pretty much everyday. Every so often we organize official Mumble meetings to discuss our roadmap and strategies. - -We are open for new people! - -## Where are we headed? - -Our goal is to make the game as moddable and developer-friendly as possible. -Even though we might have refactored most of the code at some point, Inexor should always feel like Sauerbraten gameplay wise. - -A popular stance among the Sauerbraten community is "that's impossible", and this is what we want to prove wrong. Our answer to remarks like "things are best like they are" is: standing still means falling behind. - -## The entity-system - -The entity-system will lay the basis on the other systems of the game will be built on. -For more information take a look at the [wiki](https://inexor.org/wiki/features/Entity-System.html). - ## Build process Building the `entity-system` is quite straightforward: @@ -33,7 +14,11 @@ Building the `entity-system` is quite straightforward: To build the entity-system one needs: -- a compiler of choice (`gcc`, `clang`, `MSVC`) +- a compiler of choice + - Clang/LLVM >= 5 + - Visual C++ >= 15.3 / Visual Studio >= 2017 + - Xcode >= 10.2 + - GCC >= 9 - `cmake` - [`conan`](https://conan.io) @@ -54,6 +39,25 @@ Once installed invoke `doxygen` from the `entity-system` directoy like so: `doxygen` +## How is Inexor organized? + +We are a non-hierarchical organization. This means we are simply a group of people with different ideas working together without a leader making all the decisions. Anyone of us is free to work on the particular things they want to. +For this organization to work properly we rely on good communication. We are on Telegram and Mumble pretty much everyday. Every so often we organize official Mumble meetings to discuss our roadmap and strategies. + +We are open for new people! + +## Where are we headed? + +Our goal is to make the game as moddable and developer-friendly as possible. +Even though we might have refactored most of the code at some point, Inexor should always feel like Sauerbraten gameplay wise. + +A popular stance among the Sauerbraten community is "that's impossible", and this is what we want to prove wrong. Our answer to remarks like "things are best like they are" is: standing still means falling behind. + +## The entity-system + +The entity-system will lay the basis on the other systems of the game will be built on. +For more information take a look at the [wiki](https://inexor.org/wiki/features/Entity-System.html). + ## Join us You have already accomplished the first step by reading this readme. Congratz! diff --git a/conanfile.py b/conanfile.py index 29b3f54..08e8316 100644 --- a/conanfile.py +++ b/conanfile.py @@ -11,27 +11,25 @@ class InexorConan(ConanFile): requires = ( "benchmark/1.5.0", - "glm/0.9.9.5", - "gtest/1.8.1", - "spdlog/1.4.2", - "boost_property_tree/1.69.0@bincrafters/stable", "boost_signals2/1.69.0@bincrafters/stable", "boost_range/1.69.0@bincrafters/stable", - "freetype/2.9.1@bincrafters/stable", - "openal/1.19.0@bincrafters/stable", - - "magic_enum/0.6.3@neargye/stable", - - "jsonformoderncpp/3.7.0@vthiery/stable", - "boost-di/1.1.0@inexorgame/stable", "boost-te/19.Jan.19@inexorgame/stable", - "cpp.react/legacy1@inexorgame/stable", - "crossguid/06-03-19@inexorgame/testing", + "cppgraphqlgen/3.0.4@inexorgame/testing", + "cpp.react/legacy1@inexorgame/stable", + "freetype/2.9.1@bincrafters/stable", + "glm/0.9.9.5", + "gtest/1.8.1", + "jsonformoderncpp/3.7.0@vthiery/stable", + "magic_enum/0.6.3@neargye/stable", "magnum/2019.01@inexorgame/testing", - "magnum_plugins/2019.01@inexorgame/testing" + "magnum_plugins/2019.01@inexorgame/testing", + "openal/1.19.0@bincrafters/stable", + "restinio/0.6.0.1@inexorgame/testing", + "spdlog/1.4.2", + "fmt/6.0.0" ) generators = "cmake" @@ -52,7 +50,7 @@ class InexorConan(ConanFile): "magnum_plugins:with_stbtruetypefont": True, "magnum_plugins:with_freetypefont": True, "magnum_plugins:build_plugins_static": True, - "TBB:shared": True, + "TBB:shared": True } def imports(self): diff --git a/schema/entities.gql b/schema/entities.gql deleted file mode 100644 index f42ee23..0000000 --- a/schema/entities.gql +++ /dev/null @@ -1,47 +0,0 @@ -type entity_type { - entity_type_uuid: ID - name: String - attributes: [attribute] -} - -type attribute { - attribute_uuid: ID - name: String - datatype: String - value: any -} - -type entity_instance { - entity_instance_uuid: ID - entity_type: [entity_type] - attributes: [attribute] -} - -type relationship_instance { - relationship_instance_uuid: ID - start_node_entity: entity_instance - end_node_entity: entity_instance - attributes: [attribute] -} - -type relationship_type { - relationship_type_uuid: ID - name: String - start_node_entity_type: entity_type - end_node_entity_type: entity_type - attributes: [attribute] -} - -scalar any - -type Query { - entity_types: [entity_type] - attributes: [attribute] - entity_instances: [entity_instance] - relationship_instances: [relationship_instance] - relationship_types: [relationship_type] -} - -schema { - query: Query -} \ No newline at end of file diff --git a/src/InexorApplication.cpp b/src/InexorApplication.cpp index fc35c29..113811a 100644 --- a/src/InexorApplication.cpp +++ b/src/InexorApplication.cpp @@ -1,16 +1,20 @@ #include "InexorApplication.hpp" +#include #include #include "spdlog/spdlog.h" +#include "restinio/all.hpp" +#include + namespace inexor { // Static instances of the Inexor application(s) std::vector InexorApplication::instances; InexorApplication::InexorApplication(EntitySystemModulePtr entity_system_module, TypeSystemModulePtr type_system_module, ConfigurationModulePtr configuration_module, EntitySystemDebuggerPtr entity_system_debugger, - VisualScriptingSystemModulePtr visual_scripting_system_module, CommandModulePtr command_module, ClientModulePtr client_module, LogManagerPtr log_manager) + VisualScriptingSystemModulePtr visual_scripting_system_module, CommandModulePtr command_module, ClientModulePtr client_module, QueryPtr query, LogManagerPtr log_manager) { this->entity_system_module = std::move(entity_system_module); this->type_system_module = std::move(type_system_module); @@ -20,6 +24,7 @@ InexorApplication::InexorApplication(EntitySystemModulePtr entity_system_module, this->command_module = std::move(command_module); this->client_module = std::move(client_module); this->log_manager = std::move(log_manager); + this->query = std::move(query); this->running = false; } @@ -65,6 +70,16 @@ void InexorApplication::pre_init(int argc, char *argv[]) } +void replaceAll(std::string& str, const std::string& from, const std::string& to) { + if(from.empty()) + return; + size_t start_pos = 0; + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } +} + void InexorApplication::init() { spdlog::get(LOGGER_NAME)->info("Starting Inexor..."); @@ -77,6 +92,99 @@ void InexorApplication::init() // Initialize the rendering. client_module->init_components(); + + + +// restinio::run( +// restinio::on_this_thread() +// .port(8080) +// .address("localhost") +// .request_handler([](auto req) { +// return req->create_response().set_body("Hello, World!").done(); +// })); + // TODO: Move the GraphQL to it's own component + + std::thread restinio_thread([this]() { + auto service = std::make_shared(query); + restinio::run(restinio::on_this_thread() + .port(31415) + .address("192.168.255.206") + .request_handler([service] (auto req) { + if (restinio::http_method_post() == req->header().method()) { + spdlog::get(LOGGER_NAME)->info("POST"); + try + { + std::string req_body = req->body(); + spdlog::get(LOGGER_NAME)->info(req_body); + using json = nlohmann::json; +// spdlog::get(LOGGER_NAME)->info("1"); +// auto test = json::parse("{\n" +// "\"operationName\": null,\n" +// "\"variables\": {},\n" +// "\"query\": \"{ entity_types { name attributes { uuid } } }\"\n" +// "}"); + spdlog::get(LOGGER_NAME)->info("1"); + req_body.erase(std::remove(req_body.begin(), req_body.end(), '\n'), req_body.end()); + spdlog::get(LOGGER_NAME)->info("2"); + auto req_body_json = json::parse(req_body); + spdlog::get(LOGGER_NAME)->info(req_body_json); + auto req_query_json = req_body_json["query"]; + std::string query_string = req_query_json.dump(); + query_string = query_string.substr(1, query_string.size() - 2); + // TODO: unescape all "invalid" characters + replaceAll(query_string, "\\n", ""); + spdlog::get(LOGGER_NAME)->info(query_string); + + // std::string query_string = "{"operationName":null,"variables":{},"query":"{ entity_types { name attributes { uuid } } }"; + spdlog::get(LOGGER_NAME)->info("GraphQL query string: {}", query_string); + graphql::peg::ast graphql_query = graphql::peg::parseString(std::move(query_string)); + if (!graphql_query.root) + { + throw std::runtime_error("Unknown error: No query root"); + } + spdlog::get(LOGGER_NAME)->info("Executing GraphQL query..."); + + auto result = graphql::response::toJSON(service->resolve(nullptr, *graphql_query.root, "", graphql::response::Value(graphql::response::Type::Map)).get()); + spdlog::get(LOGGER_NAME)->info("GraphQL response: {}", result); + + return req->create_response().append_header("Access-Control-Allow-Origin", "*").set_body(result).done(); + } catch (const std::runtime_error &ex) + { + spdlog::get(LOGGER_NAME)->error("GraphQL query failed: {}", ex.what()); + return req->create_response(restinio::status_internal_server_error()) + .append_header(restinio::http_field::server, "Inexor GraphQL") + .append_header(restinio::http_field::access_control_allow_origin, "*") + .append_header(restinio::http_field::access_control_allow_headers, "*") + .set_body("error") + .done(); + } + } else if (restinio::http_method_options() == req->header().method()) { + spdlog::get(LOGGER_NAME)->info("HTTP OPTIONS"); + return req->create_response() + .append_header(restinio::http_field::server, "Inexor GraphQL") + .append_header(restinio::http_field::access_control_allow_origin, "*") + .append_header(restinio::http_field::access_control_allow_headers, "*") + .append_header_date_field() + // .append_header(restinio::http_field::content_type, "text/plain; charset=utf-8") + .set_body("") + .done(); + } else { + spdlog::get(LOGGER_NAME)->error("Unknown http method {}", req->header().method()); + return req->create_response(restinio::status_internal_server_error()) + .append_header(restinio::http_field::server, "Inexor GraphQL") + .append_header(restinio::http_field::access_control_allow_origin, "*") + .append_header(restinio::http_field::access_control_allow_headers, "*") + .set_body("Unknown http method") + .done(); + + } + }) + ); + }); + restinio_thread.detach(); + + + } void InexorApplication::run() diff --git a/src/InexorApplication.hpp b/src/InexorApplication.hpp index fc187c5..64a7a03 100644 --- a/src/InexorApplication.hpp +++ b/src/InexorApplication.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "entity-system/EntitySystemModule.hpp" #include "entity-system/debugger/EntitySystemDebugger.hpp" @@ -34,6 +36,7 @@ using EntitySystemDebuggerPtr = std::shared_ptr; using CommandModulePtr = std::shared_ptr; using ClientModulePtr = std::shared_ptr; +using QueryPtr = std::shared_ptr; using LogManagerPtr = std::shared_ptr; /// @class Inexor @@ -53,7 +56,7 @@ class InexorApplication /// @param command_module The command module. /// @param audio_module The audio module. InexorApplication(EntitySystemModulePtr entity_system_module, TypeSystemModulePtr type_system_module, ConfigurationModulePtr configuration_module, EntitySystemDebuggerPtr entity_system_debugger, - VisualScriptingSystemModulePtr visual_scripting_system_module, CommandModulePtr command_module, ClientModulePtr client_module, LogManagerPtr log_manager); + VisualScriptingSystemModulePtr visual_scripting_system_module, CommandModulePtr command_module, ClientModulePtr client_module, QueryPtr query, LogManagerPtr log_manager); /// Destructor. ~InexorApplication(); @@ -101,6 +104,8 @@ class InexorApplication /// The client module. ClientModulePtr client_module; + std::shared_ptr query; + /// The log manager. LogManagerPtr log_manager; diff --git a/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.cpp b/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.cpp index bcda2c5..efe6fb5 100644 --- a/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.cpp +++ b/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.cpp @@ -91,6 +91,11 @@ std::size_t EntityTypeManager::get_entity_type_count() const return get_type_count(); } +std::vector EntityTypeManager::get_all_entity_types() const +{ + return get_all_types(); +} + EntityTypePtrOpt EntityTypeManager::get_entity_type(const xg::Guid &type_GUID) { if (does_type_exist(type_GUID)) diff --git a/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.hpp b/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.hpp index 24082d5..eed09b3 100644 --- a/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.hpp +++ b/src/entity-system/managers/entities/entity-type-manager/EntityTypeManager.hpp @@ -57,6 +57,9 @@ class EntityTypeManager : public TypeManagerTemplate /// @return The number of existing entity types. std::size_t get_entity_type_count() const; + /// @brief Returns all entity types (no copy). + std::vector get_all_entity_types() const; + /// @brief Returns an entity type. /// @param type_GUID The GUID of the entity type. /// @return A std::optional of the entity type. diff --git a/src/entity-system/managers/manager-templates/TypeManagerTemplate.hpp b/src/entity-system/managers/manager-templates/TypeManagerTemplate.hpp index 0ca76e1..460bd8d 100644 --- a/src/entity-system/managers/manager-templates/TypeManagerTemplate.hpp +++ b/src/entity-system/managers/manager-templates/TypeManagerTemplate.hpp @@ -138,6 +138,16 @@ template class TypeManagerTemplate return stored_types.size(); } + std::vector> get_all_types() const + { + std::vector> all_types; + // TODO: performance: std::for_each + for (const auto& tuple : stored_types) { + all_types.emplace_back(tuple.second); + } + return all_types; + } + /// @brief Deletes a specific type. /// @param type_name The name of the type which will be deleted. /// @return The number of deleted types. diff --git a/src/graphql/.graphqlconfig b/src/graphql/.graphqlconfig new file mode 100644 index 0000000..656d7c5 --- /dev/null +++ b/src/graphql/.graphqlconfig @@ -0,0 +1,15 @@ +{ + "name": "Inexor Entity System GraphQL Schema", + "schemaPath": "schema.entities.graphql", + "extensions": { + "endpoints": { + "Default GraphQL Endpoint": { + "url": "http://localhost:31415/graphql", + "headers": { + "user-agent": "JS GraphQL" + }, + "introspect": false + } + } + } +} diff --git a/src/graphql/EntitiesApi.cpp b/src/graphql/EntitiesApi.cpp new file mode 100644 index 0000000..bf616b5 --- /dev/null +++ b/src/graphql/EntitiesApi.cpp @@ -0,0 +1,52 @@ +#include "EntitiesApi.h" + +#include + +#include + +namespace graphql::entities { + +EntityTypeVisitor::EntityTypeVisitor(EntityTypeVisitor::EntityTypePtr internal_ent_type) : internal_ent_type(std::move(internal_ent_type)) +{ +} + +EntityTypeVisitor::IdFieldResult EntityTypeVisitor::getUuid(service::FieldParams &¶ms) const +{ + const auto &uuid_str = internal_ent_type->get_GUID().str(); + std::vector id(uuid_str.begin(), uuid_str.end()); + return response::IdType(id); +} + +EntityTypeVisitor::StringFieldResult EntityTypeVisitor::getName(service::FieldParams &¶ms) const +{ + return internal_ent_type->get_type_name(); +} + +EntityTypeVisitor::EntityAttributeTypeFieldResult EntityTypeVisitor::getAttributes(service::FieldParams &¶ms) const +{ + auto internal_attr_types = internal_ent_type->get_linked_attribute_types(); + // TODO: make object::EntityAttributeType i.e. implement a visitor + // for it (including the constructor with the link to the internal store) + return std::nullopt; +} + +Query::OptionalResult Query::getEntity_types(service::FieldParams &¶ms) const +{ + std::vector internal_ent_types = entity_type_manager->get_all_entity_types(); + // TODO: make object::EntityType i.e. implement a visitor + // for it (including the constructor with the link to the internal store) + SerializableEntityTypes serializable_entity_types; + for (const EntityTypePtr& ent_type : internal_ent_types) { + serializable_entity_types.push_back(std::make_shared(ent_type)); + } + return serializable_entity_types; + + // Q; do we need a future??? or is it just because they resolve everything async? + // A: No. FieldResult is a wrapper for either the raw result or a future of the result + + // std::promise promise; + // promise.set_value(std::move(serializable_entity_types)); + + // return promise.get_future(); +} +} /* namespace graphql::entities */ diff --git a/src/graphql/EntitiesApi.h b/src/graphql/EntitiesApi.h new file mode 100644 index 0000000..e974b79 --- /dev/null +++ b/src/graphql/EntitiesApi.h @@ -0,0 +1,72 @@ +#pragma once +/// This file implements the stub generated from the schema.entities.graphql into the EntitiesSchema.h|.cpp +/// (generated into the build folder) in order to implement response functions to various GraphQL queries from +/// some client. + +#include "graphql/EntitiesSchema.h" +#include +#include + +namespace inexor::entity_system { + class EntityTypeManager; + class EntityType; + +} + +namespace graphql::entities { + +/// Implements the visitor getters of the individual fields for the GraphQL schema. +/// @see object::EntityType for the generated schema stub implemented here +class EntityTypeVisitor : public object::EntityType +{ + using EntityTypePtr = std::shared_ptr; + using IdFieldResult = service::FieldResult>; + using StringFieldResult = service::FieldResult>; + using EntityAttributeTypeFieldResult = service::FieldResult>>>; + + + public: + /// Constructs the visitor with a link to the EntityType in the entity-system. + /// @see inexor::entity_system::EntityType + explicit EntityTypeVisitor(EntityTypePtr internal_ent_type); + + IdFieldResult getUuid(service::FieldParams&& params) const override; + + StringFieldResult getName(service::FieldParams&& params) const override; + + EntityAttributeTypeFieldResult getAttributes(service::FieldParams&& params) const override; + + private: + /// The entity type within the entity system to be used in the getters of + EntityTypePtr internal_ent_type; + +}; + +class Query : public object::Query +{ + using EntityTypePtr = std::shared_ptr; + using EntityTypeManagerPtr = std::shared_ptr; + using SerializableEntityTypes = std::vector>; + + template + using OptionalResult = service::FieldResult>; + + public: + + explicit Query(EntityTypeManagerPtr entity_type_manager) : entity_type_manager(std::move(entity_type_manager)) { + } + + OptionalResult getEntity_types(service::FieldParams&& params) const override; + + // TODO: implement the other GraphQL queries: + +// service::FieldResult>>> getEntity_instances(service::FieldParams&& params) const override; +// service::FieldResult>>> getRelation_types(service::FieldParams&& params) const override; +// service::FieldResult>>> getRelation_instances(service::FieldParams&& params) const override; + + private: + + EntityTypeManagerPtr entity_type_manager; +}; + +} /* namespace graphql::entities */ diff --git a/src/graphql/schema.entities.graphql b/src/graphql/schema.entities.graphql new file mode 100644 index 0000000..27813fa --- /dev/null +++ b/src/graphql/schema.entities.graphql @@ -0,0 +1,87 @@ +enum DataType { + BOOL + INT + BIG_INT + DOUBLE + FLOAT + STRING +} + +scalar any + +type EntityType { + uuid: ID! + name: String + attributes: [EntityAttributeType] + entity_instances: [EntityInstance] + outgoing_relation_types: [RelationType] + incoming_relation_types: [RelationType] +} + +type EntityAttributeType { + uuid: ID! + datatype: DataType! + name: String +} + +type EntityInstance { + uuid: ID! + entity_type: [EntityType] + attributes: [EntityAttributeInstance] + outgoing_relation_instances: [RelationInstance] + incoming_relation_instances: [RelationInstance] +} + +type EntityAttributeInstance { + uuid: ID! + type: EntityAttributeType! + value: any + incoming_connections: [Connector] + outgoing_connections: [Connector] +} + +type RelationType { + uuid: ID! + name: String + start_type: EntityType! + end_type: EntityType! + attributes: [RelationAttributeType] + +} + +type RelationAttributeType { + uuid: ID! + datatype: DataType! + name: String +} + +type RelationInstance { + uuid: ID! + start_node: EntityInstance! + end_node: EntityInstance! + attributes: [RelationAttributeInstance] +} + +type RelationAttributeInstance { + uuid: ID! + type: RelationAttributeType! + value: any +} + +type Connector { + output_uuid: String! + input_uuid: String! + output_attribute: EntityAttributeInstance + input_attribute: EntityAttributeInstance +} + +type Query { + entity_types: [EntityType] + entity_instances: [EntityInstance] + relation_types: [RelationType] + relation_instances: [RelationInstance] +} + +schema { + query: Query +} diff --git a/src/main.cpp b/src/main.cpp index af87a1d..c68ca53 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #include -#include "spdlog/spdlog.h" #include "InexorApplication.hpp" int main(int argc, char* argv[]) diff --git a/src/ui/managers/WindowManager.cpp b/src/ui/managers/WindowManager.cpp index 585452b..4bb3acd 100644 --- a/src/ui/managers/WindowManager.cpp +++ b/src/ui/managers/WindowManager.cpp @@ -104,9 +104,9 @@ EntityInstancePtr WindowManager::create_window(const std::string &title, int x, // Unlike SDL2, GLFW requires at least version 3.2 to be able to request a core profile. - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Set the initial states of the newly created window glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);