diff --git a/CMakeLists.txt b/CMakeLists.txt index f65151f..d79988f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,18 +32,18 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test QUIET) include(submodules/CMake/QuasarApp.cmake) updateGitVars() -set(ButterflyEngine_VERSION "0.${GIT_COMMIT_COUNT}.${GIT_COMMIT_HASH}") -set(ButterflyEngine_PACKAGE_ID "quasarapp.core.ButterflyEngine") +set(BUTTERFLY_ENGINE_VERSION "0.${GIT_COMMIT_COUNT}.${GIT_COMMIT_HASH}") +set(BUTTERFLY_ENGINE_PACKAGE_ID "quasarapp.core.ButterflyEngine") -option(ButterflyEngine_TESTS "This option disables or enables tests of the ${PROJECT_NAME} project" ON) -option(ButterflyEngine_EXAMPLE "This option disables or enables example app of the ${PROJECT_NAME} project" ON) +option(BUTTERFLY_ENGINE_TESTS "This option disables or enables tests of the ${PROJECT_NAME} project" ON) +option(BUTTERFLY_ENGINE_EXAMPLE "This option disables or enables example app of the ${PROJECT_NAME} project" ON) if (ANDROID OR IOS OR NOT QT_VERSION_MAJOR OR QA_WASM32) - set(ButterflyEngine_TESTS OFF CACHE BOOL "This option force disbled for ANDROID IOS QA_WASM32 and Not Qt projects" FORCE) + set(BUTTERFLY_ENGINE_TESTS OFF CACHE BOOL "This option force disbled for ANDROID IOS QA_WASM32 and Not Qt projects" FORCE) endif() if (NOT QT_VERSION_MAJOR) - set(ButterflyEngine_EXAMPLE OFF CACHE BOOL "This option force disbled for Not Qt projects" FORCE) + set(BUTTERFLY_ENGINE_EXAMPLE OFF CACHE BOOL "This option force disbled for Not Qt projects" FORCE) endif() make_directory(Distro) @@ -52,11 +52,11 @@ initAll() add_subdirectory(src/Library) -if (DEFINED ButterflyEngine_EXAMPLE) +if (DEFINED BUTTERFLY_ENGINE_EXAMPLE) add_subdirectory(src/Example) endif() -if (ButterflyEngine_TESTS) +if (BUTTERFLY_ENGINE_TESTS) add_subdirectory(tests) else() message("The ${PROJECT_NAME} tests is disabled.") diff --git a/doxygen.conf.in b/doxygen.conf.in index c5ef3af..b3bdd76 100644 --- a/doxygen.conf.in +++ b/doxygen.conf.in @@ -37,7 +37,7 @@ PROJECT_NAME = ButterflyEngine # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = @ButterflyEngine_VERSION@ +PROJECT_NUMBER = @BUTTERFLY_ENGINE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/init.sh b/init.sh deleted file mode 100755 index df6fb86..0000000 --- a/init.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -echo "Project name: $1" - -if [ $# -ne 1 ] -then - echo "You call this script wtth wrong arguments." - echo "Example for start script:" - echo "./init.sh MyCmakeProject" - exit 1 -fi - -REPLACESTRING="s+ButterflyEngine+$1+g" -echo $REPLACESTRING - -find . -not -path '*/\.*' -type f -exec sed -i $REPLACESTRING {} + -find . -not -path '*/\.*' -type f -exec sed -i $REPLACESTRING {} + - -find src -type d -name '*ButterflyEngine*' -exec sh -c 'x="{}"; NEWSTR=$(echo "$x" | sed "s/ButterflyEngine/'$1'/"); mv "$x" "$NEWSTR"' \; - -find src -type f -name '*ButterflyEngine*' -exec sh -c 'x="{}"; NEWSTR=$(echo "$x" | sed "s/ButterflyEngine/'$1'/"); mv "$x" "$NEWSTR"' \; -find Deploy -type f -name '*ButterflyEngine*' -exec sh -c 'x="{}"; NEWSTR=$(echo "$x" | sed "s/ButterflyEngine/'$1'/"); mv "$x" "$NEWSTR"' \; - -set -e - -git config -f .gitmodules --get-regexp '^submodule\..*\.path$' | - while read path_key path - do - url_key=$(echo $path_key | sed 's/\.path/.url/') - url=$(git config -f .gitmodules --get "$url_key") - git submodule add $url $path - done - - - diff --git a/src/Library/ButterflyEngine.qrc b/src/Library/ButterflyEngine.qrc deleted file mode 100644 index b504866..0000000 --- a/src/Library/ButterflyEngine.qrc +++ /dev/null @@ -1,9 +0,0 @@ - - - src/ButterflyEngineModule/qmldir - src/ButterflyEngineModule/ButterflyEngine.qml - - - languages/en.qm - - diff --git a/src/Library/src/ButterflyEngineModule/qmldir b/src/Library/src/ButterflyEngineModule/qmldir deleted file mode 100644 index d4358fe..0000000 --- a/src/Library/src/ButterflyEngineModule/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module ButterflyEngineModule -ButterflyEngine 1.0 ButterflyEngine.qml - diff --git a/src/engine/ButterflyEngine.qrc b/src/engine/ButterflyEngine.qrc new file mode 100644 index 0000000..b8f2469 --- /dev/null +++ b/src/engine/ButterflyEngine.qrc @@ -0,0 +1,33 @@ + + + CrawlModule/qmldir + CrawlModule/Crawl.qml + CrawlModule/GraphicItem.qml + CrawlModule/MainMenu.qml + CrawlModule/MainMenuButton.qml + CrawlModule/Metrix.qml + CrawlModule/PagePopUp.qml + CrawlModule/Scene.qml + CrawlModule/SettingsView.qml + CrawlModule/SnakeItem.qml + CrawlModule/DefaultMenu.qml + CrawlModule/AbstractMenuView.qml + CrawlModule/Light.qml + CrawlModule/DayLight.qml + CrawlModule/particles/ParticleEffect.qml + CrawlModule/particles/CrawlVectorDirection.qml + CrawlModule/particles/CrawlTargetDirection.qml + CrawlModule/particles/FireParticel.qml + CrawlCoreAssets/particles/fireColorTable.png + CrawlCoreAssets/particles/sphere.png + CrawlCoreAssets/particles/smokeSprite.png + CrawlModule/particles/Fire.qml + CrawlModule/particles/Wint.qml + CrawlModule/PreviewControl.qml + CrawlModule/StoreView.qml + CrawlModule/SelectLevelView.qml + + + languages/en.qm + + diff --git a/src/Library/CMakeLists.txt b/src/engine/CMakeLists.txt similarity index 96% rename from src/Library/CMakeLists.txt rename to src/engine/CMakeLists.txt index 841391c..726eab2 100644 --- a/src/Library/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.18) get_filename_component(CURRENT_PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR} NAME) set(CURRENT_PROJECT "${PROJECT_NAME}${CURRENT_PROJECT_DIR}") -add_definitions(-DButterflyEngine_LIBRARY) +add_definitions(-DBUTTERFLY_ENGINE_LIBRARY) file(GLOB_RECURSE SOURCE_CPP diff --git a/src/Example/languages/en.ts b/src/engine/languages/en.ts similarity index 100% rename from src/Example/languages/en.ts rename to src/engine/languages/en.ts diff --git a/src/engine/src/ButterflyEngineModule/AbstractMenuView.qml b/src/engine/src/ButterflyEngineModule/AbstractMenuView.qml new file mode 100644 index 0000000..1725a5d --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/AbstractMenuView.qml @@ -0,0 +1,8 @@ +import QtQuick +import QtQuick.Layouts + +GridLayout { + property var model: null + + anchors.fill: parent +} diff --git a/src/Library/src/ButterflyEngineModule/ButterflyEngine.qml b/src/engine/src/ButterflyEngineModule/ButterflyEngine.qml similarity index 92% rename from src/Library/src/ButterflyEngineModule/ButterflyEngine.qml rename to src/engine/src/ButterflyEngineModule/ButterflyEngine.qml index a66bed1..971450b 100644 --- a/src/Library/src/ButterflyEngineModule/ButterflyEngine.qml +++ b/src/engine/src/ButterflyEngineModule/ButterflyEngine.qml @@ -5,7 +5,7 @@ //# of this license document, but changing it is not allowed. //# -import QtQuick 2.15 +import QtQuick Item { diff --git a/src/engine/src/ButterflyEngineModule/Crawl.qml b/src/engine/src/ButterflyEngineModule/Crawl.qml new file mode 100644 index 0000000..274d9e5 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/Crawl.qml @@ -0,0 +1,130 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +//import QtQuick.Window +import QtQuick.Controls + +import NotifyModule + +ApplicationWindow { + id: mainWindow; + visible: true; + width: 1024; + height: 720; + title: qsTr("Crawl"); + + property var model: engine + + Metrix {id: metrix} + + Label { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: 25 + wrapMode: Text.WordWrap + text: qsTr("Please Select level. If level is not availabel please bue it first.") + } + + Scene { + id: scane; + worldModel: (model)? model.world : null; + anchors.fill: parent; + } + + Scene { + id: nest; + worldModel: (model)? model.nest : null; + anchors.fill: parent; + } + + ToolButton { + text: "👾" + font.pixelSize: 35 + + onClicked: { + mainMenuPopUp.open() + } + visible: !mainMenuPopUp.visible + } + + Drawer { + id: mainMenuPopUp + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + height: parent.height + width: parent.width / 3 + + MainMenu { + id: mainMenu + model: (mainWindow.model)? mainWindow.model.menu: null; + anchors.fill: parent; + } + } + + PagePopUp { + id: settingsPopUp + + source: SettingsView { + id: settingsView + model: mainMenu.model ? mainMenu.model.userSettingsModel: null + } + + standardButtons: Dialog.Save | Dialog.Cancel | Dialog.RestoreDefaults + modal: false; + width: parent.width * 0.8 + height: parent.height * 0.8; + + onAccepted: { + settingsView.save(); + } + + onReset: { + settingsView.reset(); + } + + onOpened: { + settingsView.update(); + } + + } + + PagePopUp { + id: storePopUp + source: StoreView { + id: view + model: mainMenu.model ? mainMenu.model.storeView: null + + } + + modal: false; + width: parent.width * 0.8 + height: parent.height * 0.8; + + } + + PagePopUp { + id: selectLvl + source: SelectLevelView { + id: selectLvlView + model: mainMenu.model ? mainMenu.model.selectLevelModle: null + + } + + modal: false; + width: parent.width * 0.8 + height: parent.height * 0.8; + + } + + NotificationServiceView { + anchors.fill: parent; + } + + +} diff --git a/src/engine/src/ButterflyEngineModule/DayLight.qml b/src/engine/src/ButterflyEngineModule/DayLight.qml new file mode 100644 index 0000000..5fe77b8 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/DayLight.qml @@ -0,0 +1,42 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D + +Node { + id: graphicItem + + property var model: null + property int guiId: (model) ? model.guiId : -1; + + PointLight { + id : sun + + brightness: (model)? model.lightForce * model.visible: 100 + color: (model)? model.color: "#ffffff" + castsShadow: (model)? model.castsShadow: 0 + shadowFactor: (model)? model.shadowFactor: 0 + shadowFilter: (model)? model.shadowFilter: 0 + shadowMapFar: (model)? model.shadowMapFar: 0 + shadowBias: (model)? model.shadowBias: 0 + shadowMapQuality: Light.ShadowMapQualityHigh + + Behavior on brightness { + NumberAnimation { + duration: 5000 + + } + } + } + + rotation: (model)? model.rotation: Qt.quaternion(0, 0, 0, 0) + scale: (model)? model.size: Qt.vector3d(0, 0, 0); + position: (model) ? model.position: Qt.vector3d(0,0,0); + visible: sun.brightness + +} diff --git a/src/engine/src/ButterflyEngineModule/DefaultMenu.qml b/src/engine/src/ButterflyEngineModule/DefaultMenu.qml new file mode 100644 index 0000000..104ccdd --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/DefaultMenu.qml @@ -0,0 +1,40 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Controls +import QtQuick.Layouts + +AbstractMenuView { + + columns: 2 + rows: 2 + + Button { + text: qsTr("Back to menu.") + onClicked: { + if (model) { + model.backToMenu() + } + } + } + + MouseArea { + cursorShape: Qt.DragMoveCursor + + Layout.fillHeight: true + Layout.fillWidth: true + Layout.columnSpan: 2 + Layout.rowSpan: 2 + + onClicked: { + model.userTap() + } + } + +} diff --git a/src/engine/src/ButterflyEngineModule/GraphicItem.qml b/src/engine/src/ButterflyEngineModule/GraphicItem.qml new file mode 100644 index 0000000..6ff4224 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/GraphicItem.qml @@ -0,0 +1,78 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D + +Model { + id: graphicItem + + property var model: null + property int guiId: (model) ? model.guiId : -1; + property bool fMapColor: model && (model.baseColorMap.length || + model.emissiveMap.length || + model.roughnessMap.length || + model.normalMap.length) + property int tilies: 1 + + DefaultMaterial { + id: defaultMaterial + diffuseColor: (model)? model.color: "#ff1111" + } + + PrincipledMaterial { + id: objMaterial + roughness : 1 + baseColorMap: Texture { + source: (model)? model.baseColorMap: "" + tilingModeHorizontal: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + tilingModeVertical: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + scaleU: tilies + scaleV: tilies + + } + + emissiveMap: Texture { + source: (model)? model.emissiveMap: "" + tilingModeHorizontal: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + tilingModeVertical: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + scaleU: tilies + scaleV: tilies + } + + roughnessMap: Texture { + source: (model)? model.roughnessMap: "" + tilingModeHorizontal: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + tilingModeVertical: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + scaleU: tilies + scaleV: tilies + } + + normalMap: Texture { + source: (model)? model.normalMap: "" + tilingModeHorizontal: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + tilingModeVertical: (tilies > 1)? Texture.Repeat : Texture.ClampToEdge + scaleU: tilies + scaleV: tilies + } + } + + materials: [ + (fMapColor)? objMaterial: defaultMaterial + ] + + rotation: (model)? model.rotation: Qt.quaternion(0, 0, 0, 0) + + + + scale: (model)? model.size: Qt.vector3d(0, 0, 0); + source: (model)? model.mash: "#Cube"; + position: (model) ? model.position: Qt.vector3d(0,0,0); + + visible: (model)? model.visible: false + +} diff --git a/src/engine/src/ButterflyEngineModule/Light.qml b/src/engine/src/ButterflyEngineModule/Light.qml new file mode 100644 index 0000000..fbaec42 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/Light.qml @@ -0,0 +1,33 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D + +Node { + id: graphicItem + + property var model: null + property int guiId: (model) ? model.guiId : -1; + + DirectionalLight { + position: Qt.vector3d(0, 0, 0); + brightness: (model)? model.lightForce: 100 + color: (model)? model.color: "#ffffff" + castsShadow: (model)? model.castsShadow: 0 + shadowFactor: (model)? model.shadowFactor: 0 + shadowFilter: (model)? model.shadowFilter: 0 + shadowMapFar: (model)? model.shadowMapFar: 0 + shadowBias: (model)? model.shadowBias: 0 + + } + + rotation: (model)? model.rotation: Qt.quaternion(0, 0, 0, 0) + scale: (model)? model.size: Qt.vector3d(0, 0, 0); + position: (model) ? model.position: Qt.vector3d(0,0,0); + +} diff --git a/src/engine/src/ButterflyEngineModule/MainMenu.qml b/src/engine/src/ButterflyEngineModule/MainMenu.qml new file mode 100644 index 0000000..f263243 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/MainMenu.qml @@ -0,0 +1,83 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Controls +import QtQuick.Layouts + +Item { + id: root + property var model: null + + visible: Boolean(model && model.visible) + z: 1 + + GridLayout { + id: columnLayout + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + + anchors.leftMargin: 0 + anchors.rightMargin: 0 + anchors.bottomMargin: 0 + anchors.topMargin: 0 + + columns: 1 + rows: 10 + + + transformOrigin: Item.Center + + MainMenuButton { + id: play + text: qsTr("Select level") + + onClicked: { + selectLvl.open() + } + } + + MainMenuButton { + id: store + text: qsTr("Store") + + onClicked: { + storePopUp.open() + } + } + + MainMenuButton { + id: settings + text: qsTr("My Settings") + + onClicked: { + settingsPopUp.open(); + + } + } + + MainMenuButton { + id: exit + text: qsTr("Exit") + + onClicked: { + Qt.quit(); + } + } + + } + +} + + +/*##^## Designer { + D{i:0;autoSize:true;height:480;width:640} +} + ##^##*/ diff --git a/src/engine/src/ButterflyEngineModule/MainMenuButton.qml b/src/engine/src/ButterflyEngineModule/MainMenuButton.qml new file mode 100644 index 0000000..1675f23 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/MainMenuButton.qml @@ -0,0 +1,24 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Controls +import QtQuick.Layouts + +Button { + id: exit + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + font.pixelSize: height * 0.2 + display: AbstractButton.TextBesideIcon + spacing: 4 + focusPolicy: Qt.StrongFocus + + Layout.preferredHeight: parent.height / (parent.rows + 1) + Layout.preferredWidth: parent.width / (parent.columns + 0.5) + +} diff --git a/src/engine/src/ButterflyEngineModule/Metrix.qml b/src/engine/src/ButterflyEngineModule/Metrix.qml new file mode 100644 index 0000000..d3b4446 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/Metrix.qml @@ -0,0 +1,34 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Window +import QtQuick.Controls.Material +import QtQuick.Controls + +Item { + readonly property int pointCount: 100; + readonly property real mm: Screen.pixelDensity + readonly property real sm: 10 * mm + readonly property real dsm: Math.sqrt(Math.pow(Screen.desktopAvailableWidth, 2) + Math.pow(Screen.desktopAvailableHeight, 2)) / sm + readonly property real pt: getfactor(dsm) * sm + readonly property real controlPtMaterial: Material.buttonHeight + readonly property real gamePt: (width < height) ? width / pointCount : height / pointCount; + + function getfactor(dsm) { + if (dsm < 30) { + return 0.5 + } else if ( dsm < 70) { + return 1 + } else if (dsm < 140) { + return 2; + } else + return 4; + } + + anchors.fill: parent; +} diff --git a/src/engine/src/ButterflyEngineModule/PagePopUp.qml b/src/engine/src/ButterflyEngineModule/PagePopUp.qml new file mode 100644 index 0000000..6dee424 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/PagePopUp.qml @@ -0,0 +1,32 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Material +import QtQuick.Layouts + +Dialog { + id: pagePopUp + property var source: null + + Item { + id: sourceVal + anchors.fill: parent + } + + onSourceChanged: { + if (!source) + return; + + source.parent = sourceVal; + source.anchors.fill = sourceVal; + } + + x: parent.width / 2 - width / 2 + y: parent.height / 2 - height / 2 +} diff --git a/src/engine/src/ButterflyEngineModule/PreviewControl.qml b/src/engine/src/ButterflyEngineModule/PreviewControl.qml new file mode 100644 index 0000000..094ef71 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/PreviewControl.qml @@ -0,0 +1,72 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Controls +import QtQuick.Layouts + +AbstractMenuView { + columns: 4 + rows: 2 + + MouseArea { + cursorShape: Qt.DragMoveCursor + + Layout.fillHeight: true + Layout.fillWidth: true + Layout.columnSpan: 4 + Layout.rowSpan: 1 + + + property bool track: false + property real oldX: 0 + property real oldY: 0 + + onPressed: (mouse) => { + track = true + oldX = mouse.x + oldY = mouse.y + + } + + onReleased: { + track = false + } + + onPositionChanged: (mouse) => { + if (!model) { + return; + } + + if (!track) { + return; + } + + let delta = mouse.y - oldY; + let radianDeltaY = (delta / (parent.height / 2)) * 45 + + delta = mouse.x - oldX; + let radianDeltaX = (delta / (parent.width / 2)) * 45 + + model.mousePositionChanged(radianDeltaX, radianDeltaY) + oldY = mouse.y; + oldX = mouse.x; + + } + } + + Button { + text: qsTr("Start") + onClicked: { + if (model) { + model.start() + } + } + } +} diff --git a/src/engine/src/ButterflyEngineModule/Scene.qml b/src/engine/src/ButterflyEngineModule/Scene.qml new file mode 100644 index 0000000..7813252 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/Scene.qml @@ -0,0 +1,145 @@ +import QtQuick +import QtQuick3D +import QtQuick.Controls.Material +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick3D.Particles3D + + +View3D { + id: scene; + + property var worldModel: null; + renderMode: View3D.Offscreen + + visible: worldModel && worldModel.visible + + Label { + text: scane.renderStats.fps + x: 200 + } + + PerspectiveCamera { + id: camera + position: (privateRoot.player && privateRoot.releativeCameraPosition)? + Qt.vector3d(privateRoot.player.position.x + privateRoot.releativeCameraPosition.x, + privateRoot.player.position.y + privateRoot.releativeCameraPosition.y, + privateRoot.player.position.z + privateRoot.releativeCameraPosition.z) + : + Qt.vector3d(0,0,100) + + rotation: (privateRoot.world)? privateRoot.world.cameraRotation: Qt.quaternion(0,0,0,0) + + } + + SceneEnvironment { + id: defautlBackground + backgroundMode: SceneEnvironment.Color + clearColor: "#777777" + } + + environment: /*(privateRoot.world)? background:*/ defautlBackground + + ParticleSystem3D { + id: privateRoot + property var arrayObjects: [] + + property var gameMenuModel: (worldModel)? worldModel.menu: null + property var player: (worldModel)? worldModel.player: null + property var releativeCameraPosition: (worldModel)? worldModel.cameraReleativePosition: null + + property var gameMenu: null + + function add (cppObjId) { + if (!worldModel) { + console.log("create object fail") + return; + } + + const objModel = worldModel.getItem(cppObjId); + + if (!objModel) { + console.log("model of the crawl object is not found"); + return; + } + + var viewTemplate = objModel.viewTemplate; + + var temp = Qt.createComponent(viewTemplate) + if (temp.status === Component.Ready) { + var obj = temp.createObject(privateRoot) + obj.model = objModel; + arrayObjects.push(obj) + } else { + console.log("wrong viewTemplate in model " + temp.errorString()); + } + } + + function remove(id) { + if (typeof id !== "number" || id < 0) { + console.log("id not found"); + return; + } + + for (var i = 0; i < arrayObjects.length; ++i) { + if (id === arrayObjects[i].guiId) { + arrayObjects[i].destroy(); + arrayObjects.splice(i,1); + + } + } + } + + Connections { + target: worldModel; + function onSigOBjctsListChanged(diff) { + if (!diff) { + console.log("diff not found"); + return; + } + + let tempDifRem = []; + tempDifRem = diff.getRemoveIds(); + let tempDifAdd = []; + tempDifAdd = diff.getAddedIds(); + + for (let i = 0; i < tempDifAdd.length; ++i) { + privateRoot.add(tempDifAdd[i]); + } + + for (let j = 0; j < tempDifRem.length; ++j) { + privateRoot.remove(tempDifRem[j]); + } + } + } + + Connections { + target: privateRoot; + + function onGameMenuModelChanged() { + if (!privateRoot.gameMenuModel) { + return; + } + + const comp = Qt.createComponent(privateRoot.gameMenuModel.view); + if (comp.status === Component.Ready) { + if (privateRoot.gameMenu) { + privateRoot.gameMenu.destroy() + } + + privateRoot.gameMenu = comp.createObject(scene); + if (privateRoot.gameMenu === null) { + // Error Handling + console.log("Error creating object"); + } + + privateRoot.gameMenu.model = privateRoot.gameMenuModel; + + } else if (comp.status === Component.Error) { + // Error Handling + console.log("Error loading component: " + privateRoot.gameMenuModel.view, comp.errorString()); + } + } + } + } +} diff --git a/src/engine/src/ButterflyEngineModule/SelectLevelView.qml b/src/engine/src/ButterflyEngineModule/SelectLevelView.qml new file mode 100644 index 0000000..eb0740b --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/SelectLevelView.qml @@ -0,0 +1,72 @@ +import QtQuick +import ViewSolutionsModule +import QtQuick.Controls +import QtQuick.Controls.Material +import QtQuick.Layouts + +Page { + id: store + property var model: null; + ColumnLayout { + anchors.fill: parent + ListView { + id: listView + Layout.fillHeight: true + Layout.fillWidth: true + model: store.model + delegate: delegateRow + + Component { + id: delegateRow + + Rectangle { + width: listView.width + height: 100 + color: (itemId === store.model.currentLevel) ? "#ffaf2c": "#00000000" + + Behavior on color { + + ColorAnimation { + duration: 200 + } + } + + RowLayout { + + anchors.fill: parent + + Image { + id: img + fillMode: Image.PreserveAspectCrop + source: itemImage + Layout.fillHeight: true + Layout.preferredWidth: height * 2 + } + + Label { + text: itemName + Layout.fillHeight: true + } + + Label { + text: itemDescription + Layout.fillWidth: true + Layout.fillHeight: true + } + + Button { + text: qsTr("Select"); + visible: itemId !== store.model.currentLevel + + onClicked: () => { + if (store.model) + store.model.select(itemId); + } + } + } + } + + } + } + } +} diff --git a/src/engine/src/ButterflyEngineModule/SettingsView.qml b/src/engine/src/ButterflyEngineModule/SettingsView.qml new file mode 100644 index 0000000..bb66b0d --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/SettingsView.qml @@ -0,0 +1,94 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Controls +import QtQuick.Layouts + +Item { + id: settingsView + + property var model: null + + function save() { + if (!model) { + return; + } + + model.setPort(port.value); + model.setHost(host.text); + model.setTheme(themeBox.currentIndex); + + } + + function reset() { + if (!model) { + return; + } + + model.toDefault(); + } + + function update() { + if (!model) { + return; + } + model.forceUpdate(); + } + + GridLayout { + + id: columnLayout + rows: 4 + columns: 2 + anchors.fill: parent + + Label { + text: qsTr("Use Them") + Layout.fillWidth: true + } + + ComboBox { + id: themeBox; + Layout.fillWidth: true + focusPolicy: Qt.NoFocus + + model: [qsTr("Light"), qsTr("Dark")]; + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + + currentIndex: (settingsView.model)? settingsView.model.theme: 0 + + onCurrentIndexChanged: { + if (((settingsView.model)? settingsView.model.theme: 0) + !== currentIndex) { + themeWarning.visible = true; + } + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + + } + + Label { + id: themeWarning + text: qsTr("In order for the new theme to take effect, you need to reload the game."); + + color: "#FF0000" + + wrapMode: Label.WordWrap + + Layout.maximumWidth: themeBox.width + + visible: false; + } + } + +} diff --git a/src/engine/src/ButterflyEngineModule/SnakeItem.qml b/src/engine/src/ButterflyEngineModule/SnakeItem.qml new file mode 100644 index 0000000..c04437e --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/SnakeItem.qml @@ -0,0 +1,12 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick + +GraphicItem { + +} diff --git a/src/engine/src/ButterflyEngineModule/StoreView.qml b/src/engine/src/ButterflyEngineModule/StoreView.qml new file mode 100644 index 0000000..10515f1 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/StoreView.qml @@ -0,0 +1,64 @@ +import QtQuick +import ViewSolutionsModule +import QtQuick.Controls +import QtQuick.Controls.Material +import QtQuick.Layouts + +Page { + id: store + property var model: null; + ColumnLayout { + anchors.fill: parent + ListView { + id: listView + Layout.fillHeight: true + Layout.fillWidth: true + model: store.model + delegate: delegateRow + + Component { + id: delegateRow + + RowLayout { + width: listView.width + height: 100 + Image { + id: img + fillMode: Image.PreserveAspectCrop + source: itemImage + Layout.fillHeight: true + Layout.preferredWidth: height * 2 + } + + Label { + text: itemName + Layout.fillHeight: true + } + + Label { + text: itemDescription + Layout.fillWidth: true + Layout.fillHeight: true + } + + CheckBox { + id: buyStatus + tristate: false + checkState: (itemWasBuy)? Qt.Checked: Qt.Unchecked + enabled: false + } + + Button { + text: qsTr("Buy"); + visible: !itemWasBuy + + onClicked: () => { + if (store.model) + store.model.buy(itemId); + } + } + } + } + } + } +} diff --git a/src/engine/src/ButterflyEngineModule/particles/CrawlTargetDirection.qml b/src/engine/src/ButterflyEngineModule/particles/CrawlTargetDirection.qml new file mode 100644 index 0000000..ed8440e --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/particles/CrawlTargetDirection.qml @@ -0,0 +1,22 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D +import QtQuick3D.Particles3D + +TargetDirection3D { + property var model: null + property string path: "" + + position: (model)? model.velosityTargetPosition : Qt.vector3d(0, 0, 0) + normalized: (model)? model.velosityNormalized : false + magnitude: (model)? model.velosityMagnitude : 1 + magnitudeVariation: (model)? model.velosityMagnitudeVariation : 0 + positionVariation: (model)? model.velosityTargetPositionVariation : Qt.vector3d(0, 0, 0) + +} diff --git a/src/engine/src/ButterflyEngineModule/particles/CrawlVectorDirection.qml b/src/engine/src/ButterflyEngineModule/particles/CrawlVectorDirection.qml new file mode 100644 index 0000000..20941bf --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/particles/CrawlVectorDirection.qml @@ -0,0 +1,18 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D +import QtQuick3D.Particles3D + +VectorDirection3D { + property var model: null + property string path: "" + + direction: (model)? model.velosityDirection : Qt.vector3d(0, 0, 0) + directionVariation: (model)? model.velosityDirectionValatility : Qt.vector3d(0, 0, 0) +} diff --git a/src/engine/src/ButterflyEngineModule/particles/Fire.qml b/src/engine/src/ButterflyEngineModule/particles/Fire.qml new file mode 100644 index 0000000..902d191 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/particles/Fire.qml @@ -0,0 +1,17 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D +import QtQuick3D.Particles3D + +ParticleEffect { + PointLight { + brightness: (model)? Math.sqrt(model.fireStrength): 0; + color: (model)? model.color: "#ffffff"; + } +} diff --git a/src/engine/src/ButterflyEngineModule/particles/FireParticel.qml b/src/engine/src/ButterflyEngineModule/particles/FireParticel.qml new file mode 100644 index 0000000..3621447 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/particles/FireParticel.qml @@ -0,0 +1,27 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D +import QtQuick3D.Particles3D + +SpriteParticle3D { + + id: particleFire + sprite: Texture { + source: "qrc:/CrawlCoreAssets/particles/sphere.png" + } + colorTable: Texture { + source: "qrc:/CrawlCoreAssets/particles/fireColorTable.png" + } + maxAmount: 300 + color: "#ffffff" + colorVariation: Qt.vector4d(0.0, 0.6, 0.8, 0.0) + billboard: true + blendMode: SpriteParticle3D.Screen + fadeInDuration: 100 +} diff --git a/src/engine/src/ButterflyEngineModule/particles/ParticleEffect.qml b/src/engine/src/ButterflyEngineModule/particles/ParticleEffect.qml new file mode 100644 index 0000000..97e755f --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/particles/ParticleEffect.qml @@ -0,0 +1,114 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D +import QtQuick3D.Particles3D + +ParticleEmitter3D { + + id: root + + property var model: null + property int guiId: (model) ? model.guiId : -1; + + rotation: (model)? model.rotation: Qt.quaternion(0, 0, 0, 0) + scale: (model)? model.size: Qt.vector3d(0, 0, 0); + position: (model) ? model.position: Qt.vector3d(0,0,0); + visible: (model)? model.visible: false + + depthBias: (model)? model.depthBias: 0 + emitRate: (model)? model.emitRate: 0 + + enabled: (model)? model.enabled: true + lifeSpan: (model)? model.lifeSpan: 0 + lifeSpanVariation: (model)? model.lifeSpanVariation: 0 + particleEndScale: (model)? model.particleEndScale: 0 + particleRotation: (model)? model.particleRotation: Qt.vector3d(0, 0, 0) + particleRotationVariation: (model)? model.particleRotationVariation: Qt.vector3d(0, 0, 0) + particleRotationVelocity: (model)? model.particleRotationVelocity: Qt.vector3d(0, 0, 0) + particleRotationVelocityVariation: (model)? model.particleRotationVelocityVariation: Qt.vector3d(0, 0, 0) + particleScaleVariation: (model)? model.particleScaleVariation: 0 + + onModelChanged: () => { + if (root.model) { + root.model.viewObject = root; + } + } + + Item { + id: privateRoot + property var velosity: (model)? model.velocity: null + property string delegate: (model)? model.particleDelegate: "" + property string particleShape: (model)? model.particleShape: "" + property var view: null + + onVelosityChanged: () => { + if (!root.model) + return; + + const objModel = root.model.velocity; + + if (!objModel) { + if (view) { + view.distory(); + } + + root.velocity = view = null; + return; + } + + const viewTemplate = objModel.viewTemplate; + + if (!view || (view.path !== viewTemplate)) { + let temp = Qt.createComponent(viewTemplate) + + if (!temp) + return + + if (temp.status === Component.Ready) { + let obj = temp.createObject(root) + obj.model = objModel; + + if (view) { + view.distory(); + } + + root.velocity = view = obj; + } else { + console.log("wrong path (viewTemplate property) ot thq velosity module " + temp.errorString()); + } + } + } + + onDelegateChanged: () => { + let temp = Qt.createComponent(privateRoot.delegate) + + if (!temp) + return + + if (temp.status === Component.Ready) { + root.particle = temp.createObject(root.parent); + } else { + console.log("wrong path to the in model " + temp.errorString()); + } + } + + onParticleShapeChanged: () => { + let temp = Qt.createComponent(privateRoot.particleShape) + + if (!temp) + return + + if (temp.status === Component.Ready) { + root.shape = temp.createObject(root.parent); + } else { + console.log("wrong viewTemplate in model " + temp.errorString()); + } + } + } +} diff --git a/src/engine/src/ButterflyEngineModule/particles/Wint.qml b/src/engine/src/ButterflyEngineModule/particles/Wint.qml new file mode 100644 index 0000000..1a60c51 --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/particles/Wint.qml @@ -0,0 +1,39 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +import QtQuick +import QtQuick3D +import QtQuick3D.Particles3D + +Gravity3D { + + property var model: null + property int guiId: (model) ? model.guiId : -1; + + enabled: (model)? model.enabled: false + + magnitude: (model)? model.magnitude: 0 + + direction: (model)? model.direction: Qt.vector3d(0, 0, 0) + + Behavior on magnitude { + NumberAnimation { + duration: 5000 + easing.type: Easing.InQuad + + } + } + + Behavior on direction { + Vector3dAnimation { + duration: 5000 + easing.type: Easing.InQuad + } + } + +} + diff --git a/src/engine/src/ButterflyEngineModule/qmldir b/src/engine/src/ButterflyEngineModule/qmldir new file mode 100644 index 0000000..925eebe --- /dev/null +++ b/src/engine/src/ButterflyEngineModule/qmldir @@ -0,0 +1,6 @@ +module CrawlModule +Crawl 1.0 Crawl.qml +DefaultMenu 1.0 DefaultMenu.qml +GraphicItem 1.0 GraphicItem.qml +ParticleEffect 1.0 ParticleEffect.qml +Light 1.0 Light.qml diff --git a/src/engine/src/private/asyncimageresponse.cpp b/src/engine/src/private/asyncimageresponse.cpp new file mode 100644 index 0000000..5e1ed73 --- /dev/null +++ b/src/engine/src/private/asyncimageresponse.cpp @@ -0,0 +1,30 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "asyncimageresponse.h" + +AsyncImageResponse::AsyncImageResponse() = default; +AsyncImageResponse::~AsyncImageResponse() = default; + +QQuickTextureFactory *AsyncImageResponse::textureFactory() const { + return _texture; +} + +// memory leak ? +void AsyncImageResponse::setResult(const QImage& image) { + _texture = QQuickTextureFactory::textureFactoryForImage(image); + emit finished(); +// deleteLater(); +} + +void AsyncImageResponse::error(const QString &err) { + _errorString = " " + err; +} + +QString AsyncImageResponse::errorString() const { + return QQuickImageResponse::errorString() + _errorString; +} diff --git a/src/engine/src/private/asyncimageresponse.h b/src/engine/src/private/asyncimageresponse.h new file mode 100644 index 0000000..d6b2db4 --- /dev/null +++ b/src/engine/src/private/asyncimageresponse.h @@ -0,0 +1,31 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef ASYNCIMAGERESPONSE_H +#define ASYNCIMAGERESPONSE_H + +#include + + +class AsyncImageResponse : public QQuickImageResponse { + +private: + QQuickTextureFactory *_texture = nullptr; + QString _errorString; +public: + + AsyncImageResponse (); + ~AsyncImageResponse () override; + + QQuickTextureFactory *textureFactory() const override; + + void setResult(const QImage &image); + void error(const QString &err); + + QString errorString() const override; +}; +#endif // ASYNCIMAGERESPONSE_H diff --git a/src/engine/src/private/availablelevelsmodel.cpp b/src/engine/src/private/availablelevelsmodel.cpp new file mode 100644 index 0000000..96f5cb4 --- /dev/null +++ b/src/engine/src/private/availablelevelsmodel.cpp @@ -0,0 +1,36 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "availablelevelsmodel.h" +#include "user.h" +#include + +namespace CRAWL { + +AvailableLevelsModel::AvailableLevelsModel() { + +} + +int AvailableLevelsModel::getCurrentLevel() const { + return currentLevel; +} + +void AvailableLevelsModel::setCurrentLevel(int newCurrentLevel) { + if (currentLevel == newCurrentLevel) + return; + currentLevel = newCurrentLevel; + emit currentLevelChanged(); +} + +void AvailableLevelsModel::select(int levelId) { + if (getUser()->isUnlocked(levelId)) { + setCurrentLevel(levelId); + emit sigUserSelectLevel(levelId); + } +} + +} diff --git a/src/engine/src/private/availablelevelsmodel.h b/src/engine/src/private/availablelevelsmodel.h new file mode 100644 index 0000000..010478b --- /dev/null +++ b/src/engine/src/private/availablelevelsmodel.h @@ -0,0 +1,83 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef AVAILABLELEVELSMODEL_H +#define AVAILABLELEVELSMODEL_H + +#include "baseuserlistmodel.h" + +namespace CRAWL { + +class User; +class IItem; + +/** + * @brief The AvailableLevelsModel class is model of the available levels qml view. + * This model just show available levels of the current user. + * @see the SelectLevelView.qml module. + */ +class AvailableLevelsModel: public BaseUserListModel +{ + Q_OBJECT + /** + * @brief currentLevel This property contains id of the loaded level. + * @see AvailableLevelsModel::getCurrentLevel + * @see AvailableLevelsModel::setCurrentLevel + * @see AvailableLevelsModel::currentLevelChanged + */ + Q_PROPERTY(int currentLevel READ getCurrentLevel WRITE setCurrentLevel NOTIFY currentLevelChanged) + +public: + AvailableLevelsModel(); + + /** + * @brief getCurrentLevel This method return value of the curernt level property + * @return value of the curernt level property + * @see AvailableLevelsModel::currentLevel + * @see AvailableLevelsModel::setCurrentLevel + * @see AvailableLevelsModel::currentLevelChanged + */ + int getCurrentLevel() const; + + /** + * @brief setCurrentLevel This method sets new current level. + * @param newCurrentLevel This is new value of the current level. + * @see AvailableLevelsModel::getCurrentLevel + * @see AvailableLevelsModel::currentLevel + * @see AvailableLevelsModel::currentLevelChanged + */ + void setCurrentLevel(int newCurrentLevel); + + /** + * @brief select This method select new level of user. + * @param levelId This is id of the selected level. + */ + Q_INVOKABLE void select(int levelId); + + +signals: + /** + * @brief currentLevelChanged This signal emited when the currentLevel propertye is changed. + * @see AvailableLevelsModel::getCurrentLevel + * @see AvailableLevelsModel::setCurrentLevel + * @see AvailableLevelsModel::currentLevel + */ + void currentLevelChanged(); + + /** + * @brief sigUserSelectLevel This signal emited when user select new level. + * @param level This is level id that user selected. + */ + void sigUserSelectLevel(int level); + +private: + int currentLevel = -1; + +}; + +} +#endif // AVAILABLELEVELSMODEL_H diff --git a/src/engine/src/private/baseuserlistmodel.cpp b/src/engine/src/private/baseuserlistmodel.cpp new file mode 100644 index 0000000..05933e5 --- /dev/null +++ b/src/engine/src/private/baseuserlistmodel.cpp @@ -0,0 +1,176 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "baseuserlistmodel.h" +#include "user.h" +#include "store.h" +#include + +namespace CRAWL { + +BaseUserListModel::BaseUserListModel() { + +} + +void BaseUserListModel::setUser(User *newUser) { + if (_user) { + disconnect(_user, &User::sigDropped, + this, &BaseUserListModel::handleDroppedItem); + disconnect(_user, &User::sigUnlcoked, + this, &BaseUserListModel::handleUnlockedItem); + disconnect(_user, &User::sigUlockedItemsChanged, + this, &BaseUserListModel::handleUnlockedItemsListChanged); + } + + _user = newUser; + + if (_user) { + connect(_user, &User::sigDropped, + this, &BaseUserListModel::handleDroppedItem); + connect(_user, &User::sigUnlcoked, + this, &BaseUserListModel::handleUnlockedItem); + connect(_user, &User::sigUlockedItemsChanged, + this, &BaseUserListModel::handleUnlockedItemsListChanged); + } +} + +int BaseUserListModel::getIndexById(int id) const { + return _keysIndexes.value(id, -1); +} + +Store *BaseUserListModel::store() const { + return _store; +} + +void BaseUserListModel::setStore(Store *newStore) { + _store = newStore; +} + +const QList &BaseUserListModel::keys() const { + return _keys; +} + +void BaseUserListModel::setKeys(const QList &visibleKeysList) { + int diff = visibleKeysList.size() - _keys.size(); + + auto update = [this](const QList & list) { + _keys = list; + for (int index = 0; index < _keys.size(); ++index) { + _keysIndexes[_keys[index]] = index; + } + }; + + if (diff > 0) { + beginInsertRows({}, _keys.size(), visibleKeysList.size() - 1); + update(visibleKeysList); + endInsertRows(); + + } else if (diff == 0) { + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); + + } else { + beginRemoveRows({}, visibleKeysList.size(), _keys.size() - 1); + update(visibleKeysList); + endRemoveRows(); + } +} + +void BaseUserListModel::addKey(int newKey) { + beginInsertRows({}, _keys.size(), _keys.size()); + _keys.push_back(newKey); + _keysIndexes[newKey] = _keys.size() - 1; + endInsertRows(); +} + +void BaseUserListModel::removeKey(int oldKey) { + int idx = getIndexById(oldKey); + + if (idx >= 0) { + beginRemoveRows({}, _keys.size(), _keys.size()); + + _keys.removeAt(idx); + _keysIndexes.remove(oldKey); + + endRemoveRows(); + + } +} + +int BaseUserListModel::rowCount(const QModelIndex &) const { + return _keys.size(); +} + +int BaseUserListModel::columnCount(const QModelIndex &) const { + return 1; +} + +QVariant BaseUserListModel::data(const QModelIndex &index, int role) const { + + if (index.row() >= rowCount()) { + return {}; + } + + int id = _keys.at(index.row()); + + const IItem* item = getItem(id); + + if (!item) + return {}; + + switch (role) { + case ItemId: return id; + case ItemName: return item->itemName(); + case ItemImage: return item->image(); + case ItemDescription: return item->description(); + case ItemWasBuy: return getUser() && getUser()->isUnlocked(id); + default: + return {}; + } +} + +QHash BaseUserListModel::roleNames() const { + QHash roles; + + roles[ItemId] = "itemId"; + roles[ItemName] = "itemName"; + roles[ItemDescription] = "itemDescription"; + roles[ItemImage] = "itemImage"; + roles[ItemWasBuy] = "itemWasBuy"; + + return roles; +} + +User *BaseUserListModel::getUser() const { + return _user; +} + +void BaseUserListModel::handleUnlockedItem(int item) { + int idx = _keysIndexes.value(item, -1); + + if (idx >= 0) { + emit dataChanged(index(idx,0), index(idx, 0), {ItemWasBuy}); + } +} + +void BaseUserListModel::handleDroppedItem(int item) { + int idx = _keysIndexes.value(item, -1); + + if (idx >= 0) { + emit dataChanged(index(idx,0), index(idx, 0), {ItemWasBuy}); + } +} + +void BaseUserListModel::handleUnlockedItemsListChanged(const QSet &) { + emit dataChanged(index(0,0), index(_keys.size() - 1, 0), {ItemWasBuy}); +} + +const IItem *BaseUserListModel::getItem(int id) const { + return _store->getItemById(id); +} + +} diff --git a/src/engine/src/private/baseuserlistmodel.h b/src/engine/src/private/baseuserlistmodel.h new file mode 100644 index 0000000..1bfaaf5 --- /dev/null +++ b/src/engine/src/private/baseuserlistmodel.h @@ -0,0 +1,134 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef BASEUSERLISTMODEL_H +#define BASEUSERLISTMODEL_H + +#include + +namespace CRAWL { + +class User; +class IItem; +class Store; + +/** + * @brief The BaseUserListModel class This is base class wint implementation methods for working with user object. + */ +class BaseUserListModel: public QAbstractListModel +{ + Q_OBJECT +public: + BaseUserListModel(); + + /** + * @brief setUser This method update user pointer + * @param user This is new pointer to current user. + */ + void setUser(User *newUser); + + /** + * @brief keys This method retutn curent visible items list. + * @return visible items list. + * @see BaseUserListModel::setKeys + */ + const QList &keys() const; + + /** + * @brief setKeys This method sets lsit of the keys for view. + * @param visibleKeysList This is new valud of the visible keys list. + * @see BaseUserListModel::keys + */ + void setKeys(const QList& visibleKeysList); + + /** + * @brief addKey This method add new key value for view. + * @param newKey new key value. + */ + void addKey(int newKey); + + /** + * @brief removeKey This method remove old key from view. + * @param oldKey This is old key that will be removed. + */ + void removeKey(int oldKey); + + int rowCount(const QModelIndex &parent = {}) const override; + int columnCount(const QModelIndex &parent = {}) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + /** + * @brief store This method return pointer to current store object. + * @return current store object. + */ + Store *store() const; + + /** + * @brief setStore This method sets new pointer value for the store property. + * @param newStore This is new value of the store property + */ + void setStore(Store *newStore); + +protected: + + enum ViewItemRoles { + ItemId, + ItemName, + ItemImage, + ItemDescription, + ItemWasBuy + }; + + /** + * @brief getUser This method return pointer to current user. + * @return pointer to current user. + */ + User* getUser() const; + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::unclokItem signal. + * @param item This is id of the unlocked item + */ + virtual void handleUnlockedItem(int item); + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::droppItem signal. + * @param item This is id of the dropped item + */ + virtual void handleDroppedItem(int item); + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::setUnlockedItems signal. + * @param item This is new list of the unclod items. + */ + virtual void handleUnlockedItemsListChanged(const QSet& newSet); + + /** + * @brief getItem This method should be return the item by id. Override this method for correct works this model. + * @param id This is item id + * @return const pointer to item object. + */ + virtual const IItem* getItem(int id) const; + + /** + * @brief getIndexById This method return index of the item by id. + * @param id This is id of the needed item + * @return index of the needed item. If the item with id not exists then return -1 + */ + int getIndexById(int id) const; +private: + + User * _user = nullptr; + QList _keys; + QHash _keysIndexes; + Store *_store = nullptr; + +}; + +} +#endif // BASEUSERLISTMODEL_H diff --git a/src/engine/src/private/defaultbackgroundai.cpp b/src/engine/src/private/defaultbackgroundai.cpp new file mode 100644 index 0000000..eaf7980 --- /dev/null +++ b/src/engine/src/private/defaultbackgroundai.cpp @@ -0,0 +1,39 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "defaultbackgroundai.h" +#include + +namespace CRAWL { + +DefaultBackgroundAI::DefaultBackgroundAI() { + _timer = new QTimer(); + _timer->setInterval(1000); + + connect(_timer, &QTimer::timeout, this, &DefaultBackgroundAI::handleTimerTriger); +} + +DefaultBackgroundAI::~DefaultBackgroundAI() { + _timer->stop(); + delete _timer; +} + +void DefaultBackgroundAI::startAI() { + _timer->start(); +} + +void DefaultBackgroundAI::stopAI() { + _timer->stop(); +} + +void DefaultBackgroundAI::handleTimerTriger() { + _timer->setInterval(rand() % 2000 + 200); + + emit userTap(); +} + +} diff --git a/src/engine/src/private/defaultbackgroundai.h b/src/engine/src/private/defaultbackgroundai.h new file mode 100644 index 0000000..e4dc8eb --- /dev/null +++ b/src/engine/src/private/defaultbackgroundai.h @@ -0,0 +1,36 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef DEFAULTBACKGROUNDAI_H +#define DEFAULTBACKGROUNDAI_H + +#include "Crawl/defaultcontrol.h" +#include +class QTimer; + +namespace CRAWL { + +class DefaultBackgroundAI: public DefaultControl, public IAI { + Q_OBJECT +public: + DefaultBackgroundAI(); + ~DefaultBackgroundAI(); + + // IAI interface +public: + void startAI() override; + void stopAI() override; + +private slots: + void handleTimerTriger(); + +private: + QTimer *_timer = nullptr; +}; + +} +#endif // DEFAULTBACKGROUNDAI_H diff --git a/src/engine/src/private/engine.cpp b/src/engine/src/private/engine.cpp new file mode 100644 index 0000000..7be0bff --- /dev/null +++ b/src/engine/src/private/engine.cpp @@ -0,0 +1,252 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "availablelevelsmodel.h" +#include "engine.h" +#include "mainmenumodel.h" + +#include +#include +#include +#include "Crawl/iworld.h" +#include +#include +#include +#include "Crawl/icontrol.h" +#include "QDateTime" +#include "QtConcurrent" +#include "store.h" + +namespace CRAWL { + +Engine::Engine(QObject *parent): QObject(parent) { + _store = new Store(); + _menu = new MainMenuModel(); + + setNewUser(new User()); + +} + +Engine::~Engine() { + + + for (auto it = _availableLvls.begin(); it != _availableLvls.end(); ++it) { + delete it.value(); + } + + _availableLvls.clear(); + + delete _menu; + delete _currentUser; +} + +QObject *Engine::scane() { + return _scane; +} + +void Engine::setLevel(ILevel *world) { + + if (_currentLevel == world) + return ; + + if (_currentLevel) { + _currentLevel->reset(); + } + + _currentLevel = world; + emit worldChanged(); + + if (!_currentLevel) { + + QuasarAppUtils::Params::log("Failed to init world. The World object is null! ", + QuasarAppUtils::Error); + + _currentLevel = nullptr; + return; + } + + if (!_currentLevel->world()) { + QuasarAppUtils::Params::log("Failed to init world. The World Object is null: " + + _currentLevel->world()->itemName(), + QuasarAppUtils::Error); + + _currentLevel = nullptr; + return; + } + + if (!_currentLevel->previewScane()) { + QuasarAppUtils::Params::log("Failed to init world. The World Preview scane is null. World Name: " + + _currentLevel->world()->itemName(), + QuasarAppUtils::Error); + + _currentLevel = nullptr; + return; + } + + connect(_currentLevel->previewScane(), &IPreviewScaneWorld::sigPrepareIsFinished, + this, &Engine::start); + + connect(_currentLevel->world(), &IPreviewScaneWorld::sigGameFinished, + this, &Engine::stop); + + _currentLevel->previewScane()->start({}); + +} + +void Engine::setScane(QObject *newScane) { + if (_scane == newScane) + return; + _scane = newScane; + emit scaneChanged(); +} + +QObject *Engine::player() const { + if (_currentLevel && _currentLevel->world()) + return _currentLevel->world()->player(); + + return nullptr; +} + +QObject *Engine::world() const { + if (!_currentLevel) + return nullptr; + + return _currentLevel->world(); +} + +void Engine::start(const StartData& config) const { + if (!_currentLevel) + return; + + + if (!_currentLevel->previewScane()->stop()) { + return; + } + + _currentLevel->world()->start(config); +} + +void Engine::stop() const { + if (!_currentLevel) + return; + + _currentLevel->previewScane()->start(_currentLevel->previewScane()->configuration()); +} + +void Engine::handleUnlockedItem(int item) { + static_cast(_menu->selectLevelModle())->addKey(item); +} + +void Engine::handleDroppedItem(int item) { + static_cast(_menu->selectLevelModle())->removeKey(item); +} + +void Engine::handleUnlockedItemsListChanged(const QSet &newSet) { + static_cast(_menu->selectLevelModle())->setKeys(QList(newSet.begin(), newSet.end())); +} + +void Engine::handleLevelChanged(int levelId) { + + ILevel* data = _availableLvls.value(levelId, nullptr); + + if (!data) { + QuasarAppUtils::Params::log("Failed to start lvl.", QuasarAppUtils::Error); + return; + } + + setLevel(data); +} + +ILevel *Engine::getLastLevel() { + for (const auto &data : qAsConst(_availableLvls)) { + if (data && data->world() && currentUser() && + currentUser()->isUnlocked(data->world()->itemId())) { + return data; + } + } + + return nullptr; +} + +QObject *Engine::menu() const { + return _menu; +} + +void Engine::setNewUser(User *user) { + if (_currentUser) { + + disconnect(_currentUser, &User::sigUnlcoked, this, &Engine::handleUnlockedItem); + disconnect(_currentUser, &User::sigDropped, this, &Engine::handleDroppedItem); + disconnect(_currentUser, &User::sigUlockedItemsChanged, + this, &Engine::handleUnlockedItemsListChanged); + } + + _currentUser = user; + static_cast(_menu->storeView())->setUser(_currentUser); + static_cast(_menu->selectLevelModle())->setUser(_currentUser); + + + if (_currentUser) { + + connect(_currentUser, &User::sigUnlcoked, this, &Engine::handleUnlockedItem); + connect(_currentUser, &User::sigDropped, this, &Engine::handleDroppedItem); + connect(_currentUser, &User::sigUlockedItemsChanged, + this, &Engine::handleUnlockedItemsListChanged); + } +} + +void Engine::addLvl(ILevel *levelWordl) { + if (!levelWordl->world()) { + QuasarAppUtils::Params::log("The Level not contains world object!!!"); + return; + } + _availableLvls.insert(levelWordl->world()->itemId(), levelWordl); +} + +Store *Engine::store() const { + return _store; +} + +QObject *Engine::nest() const { + if (!_currentLevel) + return nullptr; + + return _currentLevel->previewScane(); +} + +User *Engine::currentUser() const { + return _currentUser; +} + +void Engine::init() { + QMultiHash availabelItems; + + for (const auto &data : qAsConst(_availableLvls)) { + if (data && data->world()) + availabelItems.unite(data->world()->childItemsRecursive()); + } + + _store->init(availabelItems); + static_cast(_menu->storeView())->init(_store, _currentUser); + + QList availableWorlds; + for (int id : _currentUser->unlockedItems()) { + auto item = availabelItems.value(id); + if (item->itemType() == IWorld::type()) { + availableWorlds.push_back(item->itemId()); + } + } + +#define selectedLevelModel static_cast(_menu->selectLevelModle()) + selectedLevelModel->setStore(_store); + selectedLevelModel->setKeys(availableWorlds); + + connect(selectedLevelModel, &AvailableLevelsModel::sigUserSelectLevel, + this, &Engine::handleLevelChanged); +} + +} diff --git a/src/engine/src/private/engine.h b/src/engine/src/private/engine.h new file mode 100644 index 0000000..5e2af5d --- /dev/null +++ b/src/engine/src/private/engine.h @@ -0,0 +1,182 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef ENGINE_H +#define ENGINE_H + +#include +#include +#include +#include +#include + +namespace CRAWL { + +class IWorld; +class Store; +class StartData; +class User; +class StoreViewModel; +class MainMenuModel; + +/** + * @brief The Engine class + */ +class Engine : public QObject { + + Q_OBJECT + Q_PROPERTY(QObject* player READ player NOTIFY playerChanged) + Q_PROPERTY(QObject* world READ world NOTIFY worldChanged) + Q_PROPERTY(QObject* nest READ nest NOTIFY worldChanged) + + Q_PROPERTY(QObject* scane READ scane WRITE setScane NOTIFY scaneChanged) + Q_PROPERTY(QObject * menu READ menu NOTIFY menuChanged) + + +public: + Engine(QObject * parent = nullptr); + ~Engine(); + + /** + * @brief scane This method return main scane of the game. + * @return pointer to main game scane. + */ + Q_INVOKABLE QObject* scane(); + + /** + * @brief setLevel This method set new world level for game. + * @param world This is pointer to new world level. + */ + void setLevel(ILevel *world); + + /** + * @brief setScane This method sets new scane object. The scane object are + * @param newScane are Qt Quick 3d node object form qml. + */ + void setScane(QObject *newScane); + + /** + * @brief currentWorld return pointer to current world object. + * @return raw pointer to current world object. + */ + IWorld *currentWorld() const; + + /** + * @brief player return player object. + * @return player object + */ + QObject* player() const; + + /** + * @brief world return player object. + * @return world object + */ + QObject* world() const; + + /** + * @brief currentUser This method return pointer too current user. + * @return pointer too current user. + */ + User *currentUser() const; + + /** + * @brief init This method initialize the main model. Sets available levels and items. + * @param availabelItems This is list of available items. + */ + void init(); + + /** + * @brief store This pointer return pointer to store. + * @return pointer to store. + */ + Store *store() const; + + /** + * @brief nest This method return pointer to the nest model. + * @return pointer to the nest model. + */ + QObject *nest() const ; + + /** + * @brief menu This is a main menu model. + * @return main menu model object. + */ + QObject *menu() const; + + /** + * @brief setNewUser This method will initialise the new user profile. + * @param user This is pointer to new user profile. + */ + void setNewUser(User* user); + + /** + * @brief addLvl This method should be add level to game. + * @param levelWordl This is world instance + */ + void addLvl(ILevel* levelWordl); + +signals: + void scaneChanged(); + void playerChanged(); + void worldChanged(); + + void menuChanged(); + +private slots: + /** + * @brief start This method run current lvl ( move prepared data from the nest to game world) + * @param config This is confuguration that created new game world. + * @return true if lvl started successful. + */ + void start(const StartData &config) const; + + /** + * @brief stop This slots invoked when world finished own session. + */ + void stop() const; + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::unclokItem signal. + * @param item This is id of the unlocked item + */ + void handleUnlockedItem(int item); + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::droppItem signal. + * @param item This is id of the dropped item + */ + void handleDroppedItem(int item); + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::setUnlockedItems signal. + * @param item This is new list of the unclod items. + */ + void handleUnlockedItemsListChanged(const QSet& newSet); + + /** + * @brief handleLevelChanged This slot invoked when user select new level. + * @param levelId level id + */ + void handleLevelChanged(int levelId); +private: + + ILevel * getLastLevel(); + + void renderLoop(); + + QObject *_scane = nullptr; + ILevel* _currentLevel = nullptr; + QHash _availableLvls; + + MainMenuModel *_menu = nullptr; + + User *_currentUser = nullptr; + Store *_store = nullptr; +}; + +} +#endif // ENGINE_H diff --git a/src/engine/src/private/eventserver.cpp b/src/engine/src/private/eventserver.cpp new file mode 100644 index 0000000..923a00c --- /dev/null +++ b/src/engine/src/private/eventserver.cpp @@ -0,0 +1,116 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "eventserver.h" + +#include +#include +#include +#include + +namespace CRAWL { + +EventServer::EventServer(IWorld *instance) { + debug_assert(instance, "Invalid World pointer in EventServer"); + _worldInstance = instance; + + _supportedEventsKeys = {Events::Intersects}; +} + +EventServer::~EventServer() { + stop(); +} + +void EventServer::start() { + if (_renderLoopFuture.isRunning()) + return; + + _renderLoop = true; + _renderLoopFuture = QtConcurrent::run([this](){renderLoop();}); +} + +void EventServer::stop() { + _renderLoop = false; + _renderLoopFuture.waitForFinished(); +} + +void EventServer::handleAvailableObjectChanges(const Diff &diff) { + for (int added: diff.addedIds) { + auto obj = _worldInstance->getItem(added); + + if (obj->isDecorative()) { + continue; + } + + for (int event: qAsConst(_supportedEventsKeys)) { + addToSupportedEvents(obj, event); + } + + _objects.insert(obj->guiId(), obj); + } + + for (int removed: diff.removeIds) { + for (int event: qAsConst(_supportedEventsKeys)) { + _supportedEvents[event].remove(removed); + } + _objects.remove(removed); + } +} + +void EventServer::eventProcess() { + for (auto it = _supportedEvents.begin(); it != _supportedEvents.end(); ++it) { + for (const IWorldItem* item : qAsConst(it.value())) { + + switch (it.key()) { + + case Events::Intersects : { + QList result; + for (const IWorldItem *object : qAsConst(_objects)) { + if (item != object && item->intersects(*object)) { + result.append(object); + } + } + + if (result.size()) { + emit sigIntersect(item, result); + } + break; + } + + default: { + QuasarAppUtils::Params::log("Not supported event", QuasarAppUtils::Error); + } + + } + } + } +} + +void EventServer::addToSupportedEvents(const IWorldItem * obj, int event) { + if (obj->isSopportEvent(event)) { + _supportedEvents[event].insert(obj->guiId(), obj); + }; +} + +void EventServer::renderLoop() { + while (_renderLoop) { + quint64 currentTime = QDateTime::currentMSecsSinceEpoch(); + + if (!_oldTimeRender) { + _oldTimeRender = currentTime; + continue; + } + + eventProcess(); + int waitTime = 100 - currentTime + _oldTimeRender; + _oldTimeRender = currentTime; + + if (waitTime > 0) + std::this_thread::sleep_for(std::chrono::milliseconds(waitTime)); + } +} +} diff --git a/src/engine/src/private/eventserver.h b/src/engine/src/private/eventserver.h new file mode 100644 index 0000000..3e2494f --- /dev/null +++ b/src/engine/src/private/eventserver.h @@ -0,0 +1,77 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include +#include + +#include +#include + + +#ifndef EVENTSERVER_H +#define EVENTSERVER_H + +namespace CRAWL { + +class IWorldItem; +class IWorld; + +/** + * @brief The EventServer class process all game events. + * This class process all game events on the separate thread and do not change the game objects. All signal of the events return constant object pointers. +*/ +class EventServer: public QObject +{ + Q_OBJECT +public: + EventServer(IWorld * instance); + ~EventServer(); + + /** + * @brief start This method start a processing og the objects events. + */ + void start(); + + /** + * @brief stop This method stop the processing of the objects. + */ + void stop(); + +public slots: + /** + * @brief handleAvailableObjectChanges This slots handle all changes of the world. + * @param diff This is changes on the world. + */ + void handleAvailableObjectChanges(const Diff& diff); + +signals: + /** + * @brief sigIntersect This signal emit when objects intersect on the world. + * @param trigger This is pointer to object that support this evvent. + * @param objects This is list of the intersects objects. + */ + void sigIntersect(const IWorldItem* trigger, QList objects); + +private: + void eventProcess(); + void addToSupportedEvents(const IWorldItem *obj, int event); + + void renderLoop(); + + IWorld * _worldInstance = nullptr; + QHash _objects; + QHash> _supportedEvents; + QList _supportedEventsKeys; + QFuture _renderLoopFuture; + bool _renderLoop = false; + quint64 _oldTimeRender = 0; + +}; + +} + +#endif // EVENTSERVER_H diff --git a/src/engine/src/private/imageprovider.cpp b/src/engine/src/private/imageprovider.cpp new file mode 100644 index 0000000..0177a4f --- /dev/null +++ b/src/engine/src/private/imageprovider.cpp @@ -0,0 +1,46 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "asyncimageresponse.h" +#include "imageprovider.h" +#include +#include + +ImageProvider::ImageProvider() = default; +ImageProvider::~ImageProvider() = default; + +#define IgnoreQFuture(x) x.isRunning() + +QQuickImageResponse *ImageProvider::requestImageResponse(const QString &id, + const QSize &requestedSize) { + + AsyncImageResponse* response = new AsyncImageResponse(); + auto readImage = [id, requestedSize, response]() mutable { + Q_UNUSED(requestedSize); + + auto params = id.split("/"); + + if (params.contains("player")) { + response->setResult(QImage(":/img/defaultuser"). + scaled(requestedSize, Qt::KeepAspectRatioByExpanding)); + + } else if (params.contains("item")) { + response->setResult(QImage(":/img/defaultsnake"). + scaled(requestedSize, Qt::KeepAspectRatioByExpanding)); + } else { + response->error("Wrong first parametr example 'first/last'"); + } + + }; + + IgnoreQFuture(QtConcurrent::run(readImage)); + + return response; +} + + + diff --git a/src/engine/src/private/imageprovider.h b/src/engine/src/private/imageprovider.h new file mode 100644 index 0000000..58f0fe9 --- /dev/null +++ b/src/engine/src/private/imageprovider.h @@ -0,0 +1,26 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IMAGEPROVIDER_H +#define IMAGEPROVIDER_H + +#include +#include + +class ImageProvider: public QQuickAsyncImageProvider +{ +private: +public: + explicit ImageProvider(); + ~ImageProvider() override; + + QQuickImageResponse *requestImageResponse(const QString &id, + const QSize &requestedSize) override; +}; + + +#endif // IMAGEPROVIDER_H diff --git a/src/engine/src/private/mainmenumodel.cpp b/src/engine/src/private/mainmenumodel.cpp new file mode 100644 index 0000000..49ef03c --- /dev/null +++ b/src/engine/src/private/mainmenumodel.cpp @@ -0,0 +1,54 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include +#include "availablelevelsmodel.h" +#include "mainmenumodel.h" +#include "settingsviewmodel.h" +#include "storeviewmodel.h" + +#include + +namespace CRAWL { + +MainMenuModel::MainMenuModel(QObject *ptr): QObject (ptr) { + + _conf = QuasarAppUtils::Settings::instance(); + _userSettingsModel = new SettingsViewModel(this); + _storeView = new StoreViewModel(); + _selectLevelModle = new AvailableLevelsModel(); +} + +MainMenuModel::~MainMenuModel() { + delete _storeView; + delete _selectLevelModle; +} + +QObject *MainMenuModel::userSettingsModel() const { + return _userSettingsModel; +} + +bool MainMenuModel::getVisible() const { + return visible; +} + +void MainMenuModel::setVisible(bool newVisible) { + if (visible == newVisible) + return; + visible = newVisible; + emit visibleChanged(); +} + +QObject *MainMenuModel::storeView() const { + return _storeView; +} + +QObject *MainMenuModel::selectLevelModle() const { + return _selectLevelModle; +} + +} diff --git a/src/engine/src/private/mainmenumodel.h b/src/engine/src/private/mainmenumodel.h new file mode 100644 index 0000000..68e7493 --- /dev/null +++ b/src/engine/src/private/mainmenumodel.h @@ -0,0 +1,87 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef NETWORKPROFILEMAINMODEL_H +#define NETWORKPROFILEMAINMODEL_H + +#include +#include "settings.h" + +namespace ViewSolutions { +class ListViewModel; +} + +namespace CRAWL { + +class WorldInfo; +class StoreViewModel; +class AvailableLevelsModel; + +/** + * @brief The MainMenuModel class This is main class for controll user interface + */ +class MainMenuModel : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QObject* userSettingsModel READ userSettingsModel NOTIFY userSettingsModelChanged) + Q_PROPERTY(bool visible READ getVisible WRITE setVisible NOTIFY visibleChanged) + Q_PROPERTY(QObject * storeView READ storeView NOTIFY storeViewChanged) + Q_PROPERTY(QObject * selectLevelModle READ selectLevelModle NOTIFY selectLevelModleChanged) + +public: + MainMenuModel(QObject *ptr = nullptr); + ~MainMenuModel(); + + /** + * @brief userSettingsModel This method return pointer to the setting model. + * @return This is pointer to setting model. + */ + QObject* userSettingsModel() const; + + /** + * @brief getVisible This method return visible property of the main game menu. + * @return true if the menu is visble. + */ + bool getVisible() const; + + /** + * @brief setVisible This method will change visible of the main menu. + * @param newVisible This is new vlaue of the visible. + */ + void setVisible(bool newVisible); + + /** + * @brief storeView This method return pointer to store view model + * @return pointer to store view model + */ + QObject *storeView() const; + + /** + * @brief selectLevelModle This method return pointer to the available levels model. + * @return pointer to main available levels model. + */ + QObject *selectLevelModle() const; + + +signals: + void userSettingsModelChanged(QObject* userSettingsModel); + void visibleChanged(); + void storeViewChanged(); + void selectLevelModleChanged(); + +private: + Settings *_conf = nullptr; + QObject* _userSettingsModel = nullptr; + bool visible = true; + StoreViewModel *_storeView = nullptr; + AvailableLevelsModel *_selectLevelModle = nullptr; + +}; + +} +#endif // NETWORKPROFILEMAINMODEL_H diff --git a/src/engine/src/private/pluginloader.cpp b/src/engine/src/private/pluginloader.cpp new file mode 100644 index 0000000..a588a48 --- /dev/null +++ b/src/engine/src/private/pluginloader.cpp @@ -0,0 +1,42 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "pluginloader.h" +#include +#include + +typedef IWorld* (*worldInstance)(); + + +PluginLoader::PluginLoader() { + +} + +IWorld* PluginLoader::load(const QString &pluginPath) { + QLibrary lib(pluginPath); + + if (!lib.load()) { + + QuasarAppUtils::Params::log("Fail to load game module. Message: " + lib.errorString(), + QuasarAppUtils::Error); + + return nullptr; + } + + worldInstance worldFunc = (worldInstance)lib.resolve("worldInstance"); + + if (!worldFunc) { + QuasarAppUtils::Params::log("Fail to load game module." + " Message: Failed to find a instance function in the %0 module", + QuasarAppUtils::Error); + + lib.unload(); + return nullptr; + } + + return worldFunc(); +} diff --git a/src/engine/src/private/pluginloader.h b/src/engine/src/private/pluginloader.h new file mode 100644 index 0000000..b767e64 --- /dev/null +++ b/src/engine/src/private/pluginloader.h @@ -0,0 +1,31 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef PLUGINLOADER_H +#define PLUGINLOADER_H + +#include + +class IWorld; + +/** + * @brief The PluginLoader class This class load shared objects like a plugins. + */ +class PluginLoader { +public: + PluginLoader(); + + /** + * @brief load This method load a plugin game module. + * @param pluginPath Path to so or dll plugin file. + * @return Snake WorldInstance; + * @note The plugin shiold be implement instance function and if you youse Windows systems marked as a DLL_EXPORT symbol. + */ + static IWorld* load(const QString& pluginPath); +}; + +#endif // PLUGINLOADER_H diff --git a/src/engine/src/private/settings.cpp b/src/engine/src/private/settings.cpp new file mode 100644 index 0000000..75dd5a3 --- /dev/null +++ b/src/engine/src/private/settings.cpp @@ -0,0 +1,8 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "settings.h" diff --git a/src/engine/src/private/settings.h b/src/engine/src/private/settings.h new file mode 100644 index 0000000..8f365fb --- /dev/null +++ b/src/engine/src/private/settings.h @@ -0,0 +1,16 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef SNAKESETTINGS_H +#define SNAKESETTINGS_H +#include + +#define THEME "THEME_GUI" +#define THEME_DEFAULT 0 +using Settings = QuasarAppUtils::Settings; + +#endif // SNAKESETTINGS_H diff --git a/src/engine/src/private/settingsviewmodel.cpp b/src/engine/src/private/settingsviewmodel.cpp new file mode 100644 index 0000000..7503ff1 --- /dev/null +++ b/src/engine/src/private/settingsviewmodel.cpp @@ -0,0 +1,39 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "settingsviewmodel.h" +#include +#include "settings.h" + +void SettingsViewModel::handleValueChanged(QString key, QVariant value) { + if (key == THEME) { + emit themeChanged(value.toInt()); + } +} + +SettingsViewModel::SettingsViewModel(QObject *ptr): + QObject (ptr) { + _cfg = Settings::instance(); + + connect(_cfg, &Settings::valueChanged, this , &SettingsViewModel::handleValueChanged); +} + +int SettingsViewModel::theme() const { + return _cfg->getValue(THEME, THEME_DEFAULT).toInt(); +} + +void SettingsViewModel::forceUpdate() { + emit themeChanged(0); +} + +void SettingsViewModel::toDefault() { + setTheme(THEME_DEFAULT); +} + +void SettingsViewModel::setTheme(int theme) { + _cfg->setValue(THEME, theme); +} diff --git a/src/engine/src/private/settingsviewmodel.h b/src/engine/src/private/settingsviewmodel.h new file mode 100644 index 0000000..f906952 --- /dev/null +++ b/src/engine/src/private/settingsviewmodel.h @@ -0,0 +1,41 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef SETTINGSVIEWMODEL_H +#define SETTINGSVIEWMODEL_H + +#include +#include "settings.h" + + +class SettingsViewModel: public QObject +{ + Q_OBJECT + Q_PROPERTY(int theme READ theme WRITE setTheme NOTIFY themeChanged) + +private: + Settings *_cfg = nullptr; + +private slots: + void handleValueChanged(QString key, QVariant value); + +public: + SettingsViewModel(QObject* ptr = nullptr); + int theme() const; + + Q_INVOKABLE void forceUpdate(); + Q_INVOKABLE void toDefault(); + + +public slots: + void setTheme(int theme); + +signals: + void themeChanged(int theme); +}; + +#endif // SETTINGSVIEWMODEL_H diff --git a/src/engine/src/private/store.cpp b/src/engine/src/private/store.cpp new file mode 100644 index 0000000..68da23c --- /dev/null +++ b/src/engine/src/private/store.cpp @@ -0,0 +1,54 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "store.h" + +#include +namespace CRAWL { + +Store::Store() +{ + +} + +bool Store::buy(User &buyer, int itemId) { + + auto item = getItemById(itemId); + + if (buyer.getTier() < item->requiredTier()) { + return false; + } + + if (buyer.getMoney() < item->cost()) { + return false; + } + + buyer.setMoney(buyer.getMoney() - item->cost()); + buyer.unclokItem(itemId); + + return true; +} + +bool Store::init(const QMultiHash &availabelItems) { + _store = availabelItems; + + return true; +} + +const IItem *Store::getItemById(int id) const { + return _store.value(id, nullptr); +} + +int Store::size() const { + return _store.size(); +} + +QList Store::keysList() const { + return QList{_store.keyBegin(), _store.keyEnd()}; +} +} diff --git a/src/engine/src/private/store.h b/src/engine/src/private/store.h new file mode 100644 index 0000000..d3b04cb --- /dev/null +++ b/src/engine/src/private/store.h @@ -0,0 +1,64 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef STORE_H +#define STORE_H + +#include "user.h" + +namespace CRAWL { + +class IItem; + +/** + * @brief The Store class contains method for control all game items beetwin users. + */ +class Store +{ +public: + Store(); + + /** + * @brief buy This method unlock the item with @a itemId for @a buyer. The + * @param buyer This is user that will be buy item with @a itemId id. + * @param itemId This is id of the item that @a buyer will be buy + * @return true if the deal gas been completed successfully + */ + bool buy(User& buyer, int itemId); + + /** + * @brief init This method initialise store of the game. + * @param availabelItems This is hash of the available item. + * @return true if the items inited successfuly else false. + */ + bool init(const QMultiHash &availabelItems); + + /** + * @brief getItemById This method return item by id. + * @param id This is id of the required item. + * @return pointer to item. if The item with @a id not found then return nullptr. + */ + const IItem* getItemById(int id) const; + + /** + * @brief size This method return count of the available items in store. + * @return count of the available items. + */ + int size() const; + + /** + * @brief keysList This method return a list of available keys + * @return a list of available keys + */ + QList keysList() const; + +private: + QMultiHash _store; +}; +} +#endif // STORE_H diff --git a/src/engine/src/private/storeviewmodel.cpp b/src/engine/src/private/storeviewmodel.cpp new file mode 100644 index 0000000..466f475 --- /dev/null +++ b/src/engine/src/private/storeviewmodel.cpp @@ -0,0 +1,32 @@ +#include "storeviewmodel.h" +#include "store.h" +#include "user.h" + +#include + +namespace CRAWL { + +StoreViewModel::StoreViewModel() { + +} + +void StoreViewModel::init(Store *store, User *user) { + setUser(user); + setStore(store); + setKeys(store->keysList()); +} + +void StoreViewModel::buy(int item) { + if (store() && getUser()) { + store()->buy(*getUser(), item); + } +} + +const IItem *StoreViewModel::getItem(int id) const { + if (!store()) + return nullptr; + + return store()->getItemById(id); +} + +} diff --git a/src/engine/src/private/storeviewmodel.h b/src/engine/src/private/storeviewmodel.h new file mode 100644 index 0000000..606e17f --- /dev/null +++ b/src/engine/src/private/storeviewmodel.h @@ -0,0 +1,49 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef STOREVIEWMODEL_H +#define STOREVIEWMODEL_H + +#include "baseuserlistmodel.h" + +namespace CRAWL { + +class Store; +class User; + +/** + * @brief The StoreViewModel class This is view model of the store. The object of this class should be initialized it he Store class. + */ +class StoreViewModel: public BaseUserListModel +{ + Q_OBJECT + +public: + StoreViewModel(); + + /** + * @brief init This method initialize data of the view model. + * @param _store This is poiter to store that contains all inforamtion about store items. + * @param user This is new pointer to current user. + * @see StoreViewModel::setUser + */ + void init(Store * store, User* user); + + /** + * @brief buy This is qml method for receive signal from view about buying item. + * @param item This is item id that user want to buy. + */ + Q_INVOKABLE void buy(int item); + + // BaseUserListModel interface +protected: + const IItem *getItem(int id) const; + +}; + +} +#endif // STOREVIEWMODEL_H diff --git a/src/engine/src/private/targetdirection.cpp b/src/engine/src/private/targetdirection.cpp new file mode 100644 index 0000000..1e7cd68 --- /dev/null +++ b/src/engine/src/private/targetdirection.cpp @@ -0,0 +1,80 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "targetdirection.h" +namespace CRAWL { + +TargetDirection::TargetDirection(float velosityMagnitude, + float velosityMagnitudeVariation, + bool velosityNormalized, + const QVector3D &velosityTargetPosition, + const QVector3D &velosityTargetPositionVariation, + QObject *parent): + ViewTemaplateModel("qrc:/CrawlModule/particles/CrawlTargetDirection.qml", parent) +{ + setVelosityMagnitude(velosityMagnitude); + setVelosityMagnitudeVariation(velosityMagnitudeVariation); + setVelosityNormalized(velosityNormalized); + setVelosityTargetPosition(velosityTargetPosition); + setVelosityTargetPositionVariation(velosityTargetPositionVariation); +} + +float TargetDirection::velosityMagnitude() const { + return _velosityMagnitude; +} + +void TargetDirection::setVelosityMagnitude(float newVelosityMagnitude) { + if (qFuzzyCompare(_velosityMagnitude, newVelosityMagnitude)) + return; + _velosityMagnitude = newVelosityMagnitude; + emit velosityMagnitudeChanged(); +} + +float TargetDirection::velosityMagnitudeVariation() const { + return _velosityMagnitudeVariation; +} + +void TargetDirection::setVelosityMagnitudeVariation(float newVelosityMagnitudeVariation) { + if (qFuzzyCompare(_velosityMagnitudeVariation, newVelosityMagnitudeVariation)) + return; + _velosityMagnitudeVariation = newVelosityMagnitudeVariation; + emit velosityMagnitudeVariationChanged(); +} + +bool TargetDirection::velosityNormalized() const { + return _velosityNormalized; +} + +void TargetDirection::setVelosityNormalized(bool newVelosityNormalized) { + if (_velosityNormalized == newVelosityNormalized) + return; + _velosityNormalized = newVelosityNormalized; + emit velosityNormalizedChanged(); +} + +const QVector3D &TargetDirection::velosityTargetPosition() const { + return _velosityTargetPosition; +} + +void TargetDirection::setVelosityTargetPosition(const QVector3D &newVelosityTargetPosition) { + if (_velosityTargetPosition == newVelosityTargetPosition) + return; + _velosityTargetPosition = newVelosityTargetPosition; + emit velosityTargetPositionChanged(); +} + +const QVector3D &TargetDirection::velosityTargetPositionVariation() const { + return _velosityTargetPositionVariation; +} + +void TargetDirection::setVelosityTargetPositionVariation(const QVector3D &newVelosityTargetPositionVariation) { + if (_velosityTargetPositionVariation == newVelosityTargetPositionVariation) + return; + _velosityTargetPositionVariation = newVelosityTargetPositionVariation; + emit velosityTargetPositionVariationChanged(); +} +} diff --git a/src/engine/src/private/targetdirection.h b/src/engine/src/private/targetdirection.h new file mode 100644 index 0000000..567d26a --- /dev/null +++ b/src/engine/src/private/targetdirection.h @@ -0,0 +1,191 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "Crawl/viewtemaplatemodel.h" +#include +#include "global.h" + +#ifndef TARGETDIRECTION_H +#define TARGETDIRECTION_H + +namespace CRAWL { + +/** + * @brief The TargetDirection class. + * This element sets emitted particle velocity towards the target position. + * For example, to emit particles towards position (100, 0, 0) with random magnitude between 10..20: + * @code + TargetDirection { + position: Qt.vector3d(100, 0, 0) + normalized: true + magnitude: 15.0 + magnitudeVariation: 5.0 + } + } + @endcode + + * @note This class use the CrawlTargetDirection.qml template as a view temaplate. + */ +class TargetDirection: public ViewTemaplateModel +{ + Q_OBJECT + + /** + * @brief velosityMagnitude This property defines the magnitude in position change per second. + * Negative magnitude accelerates the opposite way from the position. + * When the normalized is false, this is multiplied with the distance to the target position. + * The default value is 1.0. + */ + Q_PROPERTY(float velosityMagnitude READ velosityMagnitude WRITE setVelosityMagnitude NOTIFY velosityMagnitudeChanged) + + /** + * @brief velosityMagnitudeVariation This property defines the magnitude variation in position change per second. + * When the normalized is false, this is multiplied with the distance to the target position. + * The default value is 0.0. + */ + Q_PROPERTY(float velosityMagnitudeVariation READ velosityMagnitudeVariation WRITE setVelosityMagnitudeVariation NOTIFY velosityMagnitudeVariationChanged) + + /** + * @brief velosityNormalized This property defines if the distance to position should be considered as normalized or not. + * When this is false, distance to the position affects the magnitude of the particles velocity. + * When set to true, distance is normalized and velocity amount comes only from magnitude and magnitudeVariation. + * The default value is false. + */ + Q_PROPERTY(bool velosityNormalized READ velosityNormalized WRITE setVelosityNormalized NOTIFY velosityNormalizedChanged) + + /** + * @brief velosityTargetPosition This property defines the position for particles target. + * The default value is (0, 0, 0) (the center of the emitter). + */ + Q_PROPERTY(QVector3D velosityTargetPosition READ velosityTargetPosition WRITE setVelosityTargetPosition NOTIFY velosityTargetPositionChanged) + + /** + * @brief velosityTargetPositionVariation This property defines the position variation for particles target. + * The default value is (0, 0, 0) (no variation). + */ + Q_PROPERTY(QVector3D velosityTargetPositionVariation READ velosityTargetPositionVariation WRITE setVelosityTargetPositionVariation NOTIFY velosityTargetPositionVariationChanged) + +public: + TargetDirection(float velosityMagnitude = 1, + float velosityMagnitudeVariation = 0, + bool velosityNormalized = false, + const QVector3D& velosityTargetPosition = {0,0,0}, + const QVector3D& velosityTargetPositionVariation = {0,0,0}, + QObject * parent = nullptr); + + /** + * @brief velosityMagnitude This property defines the magnitude in position change per second. + * Negative magnitude accelerates the opposite way from the position. + * When the normalized is false, this is multiplied with the distance to the target position. + * The default value is 1.0. + * @return current value of the velosityMagnitude property + */ + float velosityMagnitude() const; + + /** + * @brief setVelosityMagnitude This method sets new value of the ParticleEffect::velosityMagnitude property. + * @param newVelosityMagnitude This is a new value of the ParticleEffect::velosityMagnitude property + * @note This property will be workd only after invoke the useTargetVelosity method. + */ + void setVelosityMagnitude(float newVelosityMagnitude); + + /** + * @brief velosityMagnitudeVariation This property defines the magnitude variation in position change per second. + * When the normalized is false, this is multiplied with the distance to the target position. + * The default value is 0.0. + * @return current value of the velosityMagnitudeVariation property + */ + float velosityMagnitudeVariation() const; + + /** + * @brief setVelosityMagnitudeVariation This method sets new value of the ParticleEffect::velosityMagnitudeVariation property. + * @param newVelosityMagnitudeVariation This is a new value of the ParticleEffect::velosityMagnitudeVariation property + * @note This property will be workd only after invoke the useTargetVelosity method. + */ + void setVelosityMagnitudeVariation(float newVelosityMagnitudeVariation); + + /** + * @brief velosityNormalized This property defines if the distance to position should be considered as normalized or not. + * When this is false, distance to the position affects the magnitude of the particles velocity. + * When set to true, distance is normalized and velocity amount comes only from magnitude and magnitudeVariation. + * The default value is false. + * @return current value of the velosityNormalized property + */ + bool velosityNormalized() const; + + /** + * @brief setVelosityNormalized This method sets new value of the ParticleEffect::velosityNormalized property. + * @param newVelosityNormalized This is a new value of the ParticleEffect::velosityNormalized property + * @note This property will be workd only after invoke the useTargetVelosity method. + */ + void setVelosityNormalized(bool newVelosityNormalized); + + /** + * @brief velosityTargetPosition This property defines the position for particles target. + * The default value is (0, 0, 0) (the center of the emitter). + * @return current value of the velosityNormalized property + */ + const QVector3D &velosityTargetPosition() const; + + /** + * @brief setVelosityTargetPosition This method sets new value of the ParticleEffect::velosityTargetPosition property. + * @param newVelosityTargetPosition This is a new value of the ParticleEffect::velosityTargetPosition property + * @note This property will be workd only after invoke the useTargetVelosity method. + */ + void setVelosityTargetPosition(const QVector3D &newVelosityTargetPosition); + + /** + * @brief velosityTargetPositionVariation This property defines the position variation for particles target. + * The default value is (0, 0, 0) (no variation). + * @return current value of the velosityTargetPositionVariation property + */ + const QVector3D &velosityTargetPositionVariation() const; + + /** + * @brief setVelosityTargetPositionVariation This method sets new value of the ParticleEffect::velosityTargetPositionVariation property. + * @param newVelosityTargetPositionVariation This is a new value of the ParticleEffect::velosityTargetPositionVariation property + * @note This property will be workd only after invoke the useTargetVelosity method. + */ + void setVelosityTargetPositionVariation(const QVector3D &newVelosityTargetPositionVariation); + +signals: + + /** + * @brief velosityMagnitudeChanged This signal emited when the velosityMagnitude property changed. + */ + void velosityMagnitudeChanged(); + + /** + * @brief velosityMagnitudeVariationChanged This signal emited when the velosityMagnitudeVariation property changed. + */ + void velosityMagnitudeVariationChanged(); + + /** + * @brief velosityNormalizedChanged This signal emited when the velosityNormalized property changed. + */ + void velosityNormalizedChanged(); + + /** + * @brief velosityTargetPositionChanged This signal emited when the velosityTargetPosition property changed. + */ + void velosityTargetPositionChanged(); + + /** + * @brief velosityTargetPositionVariationChanged This signal emited when the velosityTargetPositionVariation property changed. + */ + void velosityTargetPositionVariationChanged(); + +private: + float _velosityMagnitude = 1; + float _velosityMagnitudeVariation = 0; + bool _velosityNormalized = false; + QVector3D _velosityTargetPosition = {}; + QVector3D _velosityTargetPositionVariation = {}; +}; + +} +#endif // TARGETDIRECTION_H diff --git a/src/engine/src/private/user.cpp b/src/engine/src/private/user.cpp new file mode 100644 index 0000000..f15c0f6 --- /dev/null +++ b/src/engine/src/private/user.cpp @@ -0,0 +1,124 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "user.h" +namespace CRAWL { + +constexpr float tierMul = 1.2; +constexpr int firstTierCount = 10; + +/// @private +template +struct Tiers +{ + enum { value = static_cast(tierMul * Tiers::value)}; +}; + +/// @private +template <> +struct Tiers<0> +{ + enum { value = 0 }; +}; + +/// @private +template <> +struct Tiers<1> +{ + enum { value = firstTierCount }; +}; +// End Tiers table + +constexpr int maximumTear = 100; + +#define T(X) Tiers::value +constexpr int tiersTable[maximumTear] = {T(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(9), + T(10), T(11), T(12), T(13), T(14), T(15), T(16), T(17), T(18), T(19), + T(20), T(21), T(22), T(23), T(24), T(25), T(26), T(27), T(28), T(29), + T(30), T(31), T(32), T(33), T(34), T(35), T(36), T(37), T(38), T(39), + T(40), T(41), T(42), T(43), T(44), T(45), T(46), T(47), T(48), T(49), + T(50), T(51), T(52), T(53), T(54), T(55), T(56), T(57), T(58), T(59), + T(60), T(61), T(62), T(63), T(64), T(65), T(66), T(67), T(68), T(69), + T(70), T(71), T(72), T(73), T(74), T(75), T(76), T(77), T(78), T(79), + T(80), T(81), T(82), T(83), T(84), T(85), T(86), T(87), T(88), T(89), + T(90), T(91), T(92), T(93), T(94), T(95), T(96), T(97), T(98), T(99)}; +User::User() { + +} + +const QSet &User::unlockedItems() const { + return _unlockedItems; +} + +bool User::isUnlocked(int item) const { + return _unlockedItems.contains(item); +} + +void User::unclokItem(int item) { + _unlockedItems.insert(item); + emit sigUnlcoked(item); +} + +void User::droppItem(int item) { + _unlockedItems.remove(item); + emit sigDropped(item); +} + +void User::setUnlockedItems(const QSet &newUnlockedItems) { + _unlockedItems = newUnlockedItems; + emit sigUlockedItemsChanged(newUnlockedItems); +} + +int User::recalcTier() { + int _tier = 0; + + while (getXp() > tiersTable[_tier]) { + _tier++; + } + + return _tier; +} + +void User::setTier(int tier) { + if (_tier == tier) + return; + + _tier = tier; + + emit tierChanged(); +} + +int User::getXp() const { + return _xp; +} + +void User::setXp(int newXp) { + if (_xp == newXp) + return; + _xp = newXp; + + setTier(recalcTier()); + + emit xpChanged(); +} + +int User::getTier() { + return _tier; +} + +int User::getMoney() const { + return _money; +} + +void User::setMoney(int newMoney) { + if (_money == newMoney) + return; + _money = newMoney; + emit moneyChanged(); +} + +} diff --git a/src/engine/src/private/user.h b/src/engine/src/private/user.h new file mode 100644 index 0000000..e8f96db --- /dev/null +++ b/src/engine/src/private/user.h @@ -0,0 +1,192 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include +#include + +#ifndef USER_H +#define USER_H + +namespace CRAWL { + +/** + * @brief The User class This is internal class for collection all user data and user state. + */ +class User : public QObject +{ + + Q_OBJECT + + /** + * @brief money This current user money count. An user can buy and sell game items using own money amount. + * @see User::setMoney + * @see User::getMoney + */ + Q_PROPERTY(int money READ getMoney WRITE setMoney NOTIFY moneyChanged) + + /** + * @brief xp This is experience count of an user. The experience unlock new tiers and make available new items for buying. + * @see User::setXp + * @see User::getXp + * @see User::tier + * @see User::getTier + */ + Q_PROPERTY(int xp READ getXp WRITE setXp NOTIFY xpChanged) + + /** + * @brief tier This us user tier. This value automaticaly generated by cuuren user experience count. + * @see User::xp + * @see User::getXp + * @see User::getTier + */ + Q_PROPERTY(int tier READ getTier NOTIFY tierChanged) + +public: + User(); + + /** + * @brief getMoney This current user money count. An user can buy and sell game items using own money amount. + * @return current value of the User::money property + * @see User::setMoney + * @see User::money + */ + int getMoney() const; + + /** + * @brief setMoney This method sets new value of the user money amount. + * @param newMoney this is new value of users money. + * @see User::getMoney + * @see User::money + */ + void setMoney(int newMoney); + + /** + * @brief getXp This is experience count of an user. The experience unlock new tiers and make available new items for buying. + * @return current user xpereans. + * @see User::setXp + * @see User::getXp + * @see User::tier + * @see User::getTier + */ + int getXp() const; + + /** + * @brief setXp This method sets new value of the user experience. + * @param newXp This is new value of the users experience. + * @note This method can be change the User::tier property + * @see User::xp + * @see User::getXp + * @see User::tier + * @see User::getTier + */ + void setXp(int newXp); + + /** + * @brief getTier This us user tier. This value automaticaly generated by cuuren user experience count. + * @return current value of the users tier. + * @see User::xp + * @see User::getXp + * @see User::tier + */ + int getTier(); + + /** + * @brief unlockedItems This method return set of the unlocked items of this user. + * @return Set of the unlocked items of this user. + * @see User::unclokItem + * @see User::unlockedItems + * @see User::droppItem + * @see User::isUnlocked + * @see User::setUnlockedItems + */ + const QSet &unlockedItems() const; + + /** + * @brief isUnlocked This method check if the @a item is unlocked for this user. + * @param item This is id of the checked item. + * @return true if the item is uncloked else false. + * @see User::unclokItem + * @see User::unlockedItems + * @see User::droppItem + * @see User::isUnlocked + * @see User::setUnlockedItems + */ + bool isUnlocked(int item) const; + + /** + * @brief unclokItem This method unclok the @a item for current user. + * @param item This is id of item that need to unclok. + * @see User::unclokItem + * @see User::unlockedItems + * @see User::droppItem + * @see User::isUnlocked + * @see User::setUnlockedItems + */ + void unclokItem(int item); + + /** + * @brief droppItem This method dropp item from user. + * @param item This is id of the dropped item + * @see User::unclokItem + * @see User::unlockedItems + * @see User::droppItem + * @see User::isUnlocked + * @see User::setUnlockedItems + */ + void droppItem(int item); + +signals: + void moneyChanged(); + void tierChanged(); + void xpChanged(); + + /** + * @brief sigUlockedItemsChanged This signal emited when users list of unclode items is changed.. + * @param unclokedItems This is unlocked items set. Each items in the set is id of the unclocked item. + */ + void sigUlockedItemsChanged(const QSet & unclokedItems); + + /** + * @brief sigUnlcoked This signal emmited when user unlock one item. + * @param item This is unlocked item id. + * @see User::unclokItem + */ + void sigUnlcoked(int item); + + /** + * @brief sigDropped This signal emmited when user dropped one item. + * @param item This is dpopped item id. + * @see User::droppItem + */ + void sigDropped(int item); + +protected: + /** + * @brief setUnlockedItems This method sets new set of uncloked items + * @param newUnlockedItems This is new set of the uncloked items + * @see User::unclokItem + * @see User::unlockedItems + * @see User::droppItem + * @see User::isUnlocked + * @see User::setUnlockedItems + */ + void setUnlockedItems(const QSet &newUnlockedItems); + +private: + + int recalcTier(); + + void setTier(int tier); + + int _money = 0; + int _xp = 0; + int _tier = 0; + QSet _unlockedItems; +}; +} + +#endif // USER_H diff --git a/src/engine/src/private/vectordirection.cpp b/src/engine/src/private/vectordirection.cpp new file mode 100644 index 0000000..a52d0f3 --- /dev/null +++ b/src/engine/src/private/vectordirection.cpp @@ -0,0 +1,44 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "vectordirection.h" + +namespace CRAWL { + +VectorDirection::VectorDirection(const QVector3D &direction, + const QVector3D &directionValatility, + QObject *parent): + ViewTemaplateModel("qrc:/CrawlModule/particles/CrawlVectorDirection.qml", parent) { + + setVelosityDirection(direction); + setVelosityDirectionValatility(directionValatility); +} + +const QVector3D &VectorDirection::velosityDirection() const { + return _velosityDirection; +} + +void VectorDirection::setVelosityDirection(const QVector3D &newVelosityDirection) { + if (_velosityDirection == newVelosityDirection) + return; + _velosityDirection = newVelosityDirection; + emit velosityDirectionChanged(); +} + +const QVector3D &VectorDirection::velosityDirectionValatility() const { + return _velosityDirectionValatility; +} + +void VectorDirection::setVelosityDirectionValatility(const QVector3D &newVelosityDirectionValatility) { + if (_velosityDirectionValatility == newVelosityDirectionValatility) + return; + _velosityDirectionValatility = newVelosityDirectionValatility; + emit velosityDirectionValatilityChanged(); +} + +} diff --git a/src/engine/src/private/vectordirection.h b/src/engine/src/private/vectordirection.h new file mode 100644 index 0000000..3982e3c --- /dev/null +++ b/src/engine/src/private/vectordirection.h @@ -0,0 +1,99 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef VECTORDIRECTION_H +#define VECTORDIRECTION_H + +#include "Crawl/viewtemaplatemodel.h" +#include +#include "global.h" + +namespace CRAWL { + +/** + * @brief The VectorDirection class. + * This element sets emitted particle velocity towards the target direction vector. + * The length of the direction vector is used as the velocity magnitude. + * For example, to emit particles towards some random direction within x: 50..150, y: -20..20, z: 0: + * @code + * VectorDirection { + direction: Qt.vector3d(100, 0, 0) + directionVariation: Qt.vector3d(50, 20, 0) + } + @endcode + * + * @note This class use the CrawlVectorDirection.qml template as a view temaplate. + */ +class VectorDirection: public ViewTemaplateModel +{ + Q_OBJECT + + /** + * @brief velosityDirection this property defines the direction for particles target. + * The default value is (0, 100, 0) (upwards on the y-axis). + */ + Q_PROPERTY(QVector3D velosityDirection READ velosityDirection WRITE setVelosityDirection NOTIFY velosityDirectionChanged) + + /** + * @brief velosityDirectionValatility This property defines the direction variation for particles target. + * The default value is (0, 0, 0) (no variation). + */ + Q_PROPERTY(QVector3D velosityDirectionValatility READ velosityDirectionValatility WRITE setVelosityDirectionValatility NOTIFY velosityDirectionValatilityChanged) + +public: + VectorDirection(const QVector3D& direction = {}, + const QVector3D& directionValatility = {}, + QObject * parent = nullptr); + + /** + * @brief velosityDirection this property defines the direction for particles target. + * The default value is (0, 100, 0) (upwards on the y-axis). + * @return current value of the velosityDirection property + */ + const QVector3D &velosityDirection() const; + + /** + * @brief setVelosityDirection This method sets new value of the ParticleEffect::velosityDirection property. + * @param newVelosityDirection This is a new value of the ParticleEffect::velosityDirection property + * @note This property will be workd only after invoke the useDirectionVelosity method. + */ + void setVelosityDirection(const QVector3D &newVelosityDirection); + + /** + * @brief velosityDirectionValatility This property defines the direction variation for particles target. + * The default value is (0, 0, 0) (no variation). + * @return current value of the velosityDirectionValatility property + */ + const QVector3D &velosityDirectionValatility() const; + + /** + * @brief setVelosityDirectionValatility This method sets new value of the ParticleEffect::velosityDirectionValatility property. + * @param newVelosityDirectionValatility This is a new value of the ParticleEffect::velosityDirectionValatility property + * @note This property will be workd only after invoke the useDirectionVelosity method. + */ + void setVelosityDirectionValatility(const QVector3D &newVelosityDirectionValatility); + +signals: + + /** + * @brief velosityDirectionChanged This signal emited when the velosityDirection property changed. + */ + void velosityDirectionChanged(); + + /** + * @brief velosityDirectionValatilityChanged This signal emited when the velosityDirectionValatility property changed. + */ + void velosityDirectionValatilityChanged(); + +private: + + QVector3D _velosityDirection = {}; + QVector3D _velosityDirectionValatility = {}; +}; +} +#endif // VECTORDIRECTION_H diff --git a/src/engine/src/private/worldstatus.cpp b/src/engine/src/private/worldstatus.cpp new file mode 100644 index 0000000..869af32 --- /dev/null +++ b/src/engine/src/private/worldstatus.cpp @@ -0,0 +1,9 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "worldstatus.h" + diff --git a/src/engine/src/private/worldstatus.h b/src/engine/src/private/worldstatus.h new file mode 100644 index 0000000..8004ab8 --- /dev/null +++ b/src/engine/src/private/worldstatus.h @@ -0,0 +1,35 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef WORLDSTATUS_H +#define WORLDSTATUS_H + +#include + +/** + * @brief The WorldStatus enum This enum contains statuses of the world. + * @note This statuses available only internal in main engine library. + */ +namespace WorldStatus +{ + Q_NAMESPACE // required for meta object creation + /** + * @brief The WorldStatus enum This enum contains statuses of the world. + * @note This statuses available only internal in main engine library. + */ + enum Status { + /// Undefined status. Using by default + Undefined = 0, + /// World with this status emit random control signals for the player object fir emulate game session of the AI. + Background, + /// World with this status show hame control menu and listem player signals. + Game + }; + Q_ENUM_NS(Status) // register the enum in meta object data +} + +#endif // WORLDSTATUS_H diff --git a/src/Library/src/public/ButterflyEngine.cpp b/src/engine/src/public/ButterflyEngine.cpp similarity index 91% rename from src/Library/src/public/ButterflyEngine.cpp rename to src/engine/src/public/ButterflyEngine.cpp index b769f49..643feb9 100644 --- a/src/Library/src/public/ButterflyEngine.cpp +++ b/src/engine/src/public/ButterflyEngine.cpp @@ -16,7 +16,7 @@ bool init() { } QString version() { - return ButterflyEngine_VERSION; + return BUTTERFLY_ENGINE_VERSION; } diff --git a/src/Library/src/public/ButterflyEngine.h b/src/engine/src/public/ButterflyEngine.h similarity index 89% rename from src/Library/src/public/ButterflyEngine.h rename to src/engine/src/public/ButterflyEngine.h index 52f09e1..4d1ab89 100644 --- a/src/Library/src/public/ButterflyEngine.h +++ b/src/engine/src/public/ButterflyEngine.h @@ -16,12 +16,12 @@ namespace ButterflyEngine { * @brief init main initialize method of The ButterflyEngine library * @return true if library initialized successfull */ -bool ButterflyEngine_EXPORT init(); +bool BUTTERFLY_ENGINE_EXPORT init(); /** * @brief version This method return string value of a library version * @return string value of a library version */ -QString ButterflyEngine_EXPORT version(); +QString BUTTERFLY_ENGINE_EXPORT version(); }; diff --git a/src/engine/src/public/ButterflyEngine/components/Concept.md b/src/engine/src/public/ButterflyEngine/components/Concept.md new file mode 100644 index 0000000..b0d08ac --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/Concept.md @@ -0,0 +1,110 @@ +# Extension concept + +The extension it is separate module class with custom function. + +## How to use + +1. Create own child class from IRender interface. +2. Override the IRender::render method of base interface +3. Check compatibility betwin this type and requred type using the IRender::checkminimumRequariedType method. +4. In the render method using dynamic_cast operator get neede interface of class object. +5. Implement needed functions for object. + + +## Example: + +Movable object header: + +```cpp + +class CRAWL_EXPORT MovableObject: public virtual IRender +{ + +public: + MovableObject(); + + void render(unsigned int tbfMsec) override; + + const QVector3D &movableVector() const; + + void setMovableVector(const QVector3D &newMovableVector); + + float angularVelocity() const; + + void setAngularVelocity(float newAngularVelocity); + + float breakingForce() const; + + void setBreakingForce(float newBreakingForce); + +private: + QVector3D _movableVector; + QVector3D _currentMovableVector; + + float _angularVelocity = 0; + float _breakingForce = 0; +}; +``` + +Movable object source: + +```cpp +MovableObject::MovableObject() +{ + +} + +void MovableObject::render(unsigned int tbfMsec) { + auto _this = checkminimumRequariedType(); + + // get object center position + QVector3D currentPosition = _this->position(); + + // move object to vector + currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); + _this->setposition(currentPosition); + + // calc temp vector betvin user moveble vector and real moveble vector + QVector3D tempVector = _movableVector - _currentMovableVector ; + + // calc change on this iteration for new moveble vector + float delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + + // resize temp vector for calc changes of the movableVector + tempVector = tempVector.normalized() * delta; + + // recalc new currentMovable vector (applay changes) + _currentMovableVector += tempVector; + + float newMovableVectorLength = std::max(_movableVector.length() - (_breakingForce * (tbfMsec / 1000.0)), 0.0); + + // update movable vector + _movableVector = _movableVector.normalized() * newMovableVectorLength; + +} + +const QVector3D &MovableObject::movableVector() const { + return _movableVector; +} + +void MovableObject::setMovableVector(const QVector3D &newMovableVector) { + _movableVector = newMovableVector; +} + +float MovableObject::angularVelocity() const { + return _angularVelocity; +} + +void MovableObject::setAngularVelocity(float newAngularVelocity) { + _angularVelocity = newAngularVelocity; +} + +float MovableObject::breakingForce() const { + return _breakingForce; +} + +void MovableObject::setBreakingForce(float newBreakingForce) { + _breakingForce = newBreakingForce; +} + +``` diff --git a/src/engine/src/public/ButterflyEngine/components/autogenerateclaster.cpp b/src/engine/src/public/ButterflyEngine/components/autogenerateclaster.cpp new file mode 100644 index 0000000..07fd467 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/autogenerateclaster.cpp @@ -0,0 +1,39 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "autogenerateclaster.h" +namespace CRAWL { + +AutoGenerateClaster::AutoGenerateClaster() { +} + +void AutoGenerateClaster::generateItems() { + + for (unsigned int count = itemsCount(); count > 0; count--) { + if (!_factory) { + QuasarAppUtils::Params::log("Please use the registerItemType method" + " before invoke parent constructor.", + QuasarAppUtils::Error); + return; + } + + add(factory()); + } +} + +ClasterItem *AutoGenerateClaster::factory() const { + + if (!_factory) { + QuasarAppUtils::Params::log("Please use the registerBodyitem method" + " before invoke parent constructor.", + QuasarAppUtils::Error); + return nullptr; + } + + return _factory(); +} +} diff --git a/src/engine/src/public/ButterflyEngine/components/autogenerateclaster.h b/src/engine/src/public/ButterflyEngine/components/autogenerateclaster.h new file mode 100644 index 0000000..3e230c2 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/autogenerateclaster.h @@ -0,0 +1,65 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef AUTOGENERATECLASTER_H +#define AUTOGENERATECLASTER_H + +#include "claster.h" + +namespace CRAWL { + +/** + * @brief The AutoGenerateClaster class hs support the registration default claster item class and factory method for the items. + */ +class CRAWL_EXPORT AutoGenerateClaster: public Claster +{ +public: + AutoGenerateClaster(); + + /** + * @brief itemsCount This method sould be return count of the registered items on the claster object. + * @return items count of the child objects. + */ + virtual unsigned int itemsCount() const = 0; + + template + /** + * @brief registerItemType This method register claster item type. Items will be generated in the generateItems method. The size of body companents calc from the itemsCount property. + */ + void registerItemType() { + _factory = [](){ + return new Type; + }; + } + +protected: + /** + * @brief generateItems This method invoked after iit object on the world and generate list of the default claster items. + * @note This method should be invked after initialized of this object. + */ + virtual void generateItems(); + + /** + * @brief factory This method create new item of the claster. See the registerItemType for get more information. + * @return return new item of the claster item. If the object not registered return nullptr. + */ + ClasterItem *factory() const; + + /** + * @brief isClasterItemRegistered + * @return tru if the class is registered. + */ + bool isClasterItemRegistered() const; + + +private: + std::function _factory = nullptr; + +}; + +} +#endif // AUTOGENERATECLASTER_H diff --git a/src/engine/src/public/ButterflyEngine/components/basemotion.cpp b/src/engine/src/public/ButterflyEngine/components/basemotion.cpp new file mode 100644 index 0000000..14458b2 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/basemotion.cpp @@ -0,0 +1,32 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "basemotion.h" +#include "Crawl/guiobject.h" + +namespace CRAWL { + +BaseMotion::BaseMotion() { + +} + +const QQuaternion &BaseMotion::staticRotation() const { + return _staticRotation; +} + +void BaseMotion::setStaticRotation(const QQuaternion &newStaticRotation) { + _staticRotation = newStaticRotation; +} + +void BaseMotion::render(unsigned int tbfMsec) { + if (auto _this = checkminimumRequariedType()) { + renderPosition(_this, tbfMsec); + renderRotation(_this, tbfMsec); + } +} +} diff --git a/src/engine/src/public/ButterflyEngine/components/basemotion.h b/src/engine/src/public/ButterflyEngine/components/basemotion.h new file mode 100644 index 0000000..69da274 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/basemotion.h @@ -0,0 +1,72 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef BASEMOTION_H +#define BASEMOTION_H + +#include "Crawl/irender.h" + +#include + +namespace CRAWL { + +class GuiObject; + +/** + * @brief The BaseMotion class contains base functions of the motion. + * For Create your own motion alghoritm you need to override two methods: + * * renderPosition + * * renderRotation + * + */ +class CRAWL_EXPORT BaseMotion : public virtual IRender +{ +public: + BaseMotion(); + + // IRender interface +public: + void render(unsigned int tbfMsec); + + /** + * @brief staticRotation This method retur nstatic rotation in quaternion. The static rotation rotate object to setted value independet then movable vector. + * @return quterion of the static rotation + */ + const QQuaternion &staticRotation() const; + + /** + * @brief setStaticRotation This metho sets new value of the static rotation of this object. + * @param newStaticRotation new value of the static rotation. + * @note if you want use eilor angles then use the QQuaternion::fromEulerAngles method. + * @note See the staticRotation method for get more information. + */ + void setStaticRotation(const QQuaternion &newStaticRotation); + +protected: + + /** + * @brief renderRotation This method recalc raration for an @a object. The Default do nothing. + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + virtual void renderRotation(GuiObject* object, unsigned int tbfMsec) = 0; + + /** + * @brief renderRotation This method recalc position for an @a object. + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + virtual void renderPosition(GuiObject* object, unsigned int tbfMsec) = 0; + +private: + + QQuaternion _staticRotation = QQuaternion::fromEulerAngles(0,0,0); + +}; +} +#endif // BASEMOTION_H diff --git a/src/engine/src/public/ButterflyEngine/components/circularmotion.cpp b/src/engine/src/public/ButterflyEngine/components/circularmotion.cpp new file mode 100644 index 0000000..c52197b --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/circularmotion.cpp @@ -0,0 +1,77 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "circularmotion.h" + +#include +#include "cmath" + +namespace CRAWL { + +CircularMotion::CircularMotion(const QVector3D *center) { + _center = center; +} + +void CircularMotion::render(unsigned int tbfMsec) { + + if (auto _this = checkminimumRequariedType()) { + renderPosition(_this, tbfMsec); + renderRotation(_this, tbfMsec); + } +} + +float CircularMotion::angularVelocity() const { + return _angularVelocity; +} + +void CircularMotion::setAngularVelocity(float newAngularVelocity) { + _angularVelocity = newAngularVelocity; +} + +const QVector3D &CircularMotion::axis() const { + return _axis; +} + +void CircularMotion::setAxis(const QVector3D &newAxis) { + _axis = newAxis; +} + +float CircularMotion::radius() const { + return _radius; +} + +void CircularMotion::setRadius(float newRadius) { + _radius = newRadius; +} + +double CircularMotion::anglePosition() const { + return _angle; +} + +void CircularMotion::setAnglePosition(double newAngle) { + _angle = newAngle; +} + +void CircularMotion::renderRotation(GuiObject *object, + unsigned int ) { + object->setRotation(QQuaternion::rotationTo({1.0f, 0.0, 0.0}, *_center) * staticRotation()); +} + +void CircularMotion::renderPosition(GuiObject *object, + unsigned int tbfMsec) { + + if (!_center) + return; + + double motionCoef = 360 / (2 * M_PI * radius()); + _angle += motionCoef * angularVelocity() * (tbfMsec / 1000.f); + auto normal = (QQuaternion::fromAxisAndAngle(_axis, _angle) * QVector3D{0,0,1}).normalized(); + + object->setposition(*_center + normal * radius()); + +} +} diff --git a/src/engine/src/public/ButterflyEngine/components/circularmotion.h b/src/engine/src/public/ButterflyEngine/components/circularmotion.h new file mode 100644 index 0000000..7c6b7a7 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/circularmotion.h @@ -0,0 +1,106 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CIRCULARMOTION_H +#define CIRCULARMOTION_H + +#include +#include + + +namespace CRAWL { + +class GuiObject; + +/** + * @brief The CircularMotion class. This class contains render function for the moving guiobject by round. + * @note For motion set motion asix and angular velocity + */ +class CRAWL_EXPORT CircularMotion: public BaseMotion +{ +public: + CircularMotion(const QVector3D* center); + + // IRender interface +public: + void render(unsigned int tbfMsec) override; + + /** + * @brief angularVelocity This is property are speed of motion. + * @return current speed of the motion object. + */ + float angularVelocity() const; + + /** + * @brief setAngularVelocity This method sets new value of the current speed of the object. + * @param newAngularVelocity This is new value of the motion speed + */ + void setAngularVelocity(float newAngularVelocity); + + /** + * @brief axis This method are asix of motion. This object will moving around this axis. + * @return curretn asix value. + */ + const QVector3D &axis() const; + + /** + * @brief setAxis This method sets new value of the motion axis. + * @param newAxis This is new value of the motion asix. + */ + void setAxis(const QVector3D &newAxis); + + /** + * @brief radius This method return current radius of the circular motion + * @return current radius + */ + float radius() const; + + /** + * @brief setRadius This method sets new value of the circular motion radius. + * @param newRadius This is new value of the circular motion radius. + */ + void setRadius(float newRadius); + + /** + * @brief anglePosition This method return current angel of the item position arountd center. + * @return current angle position around center. + */ + double anglePosition() const; + + /** + * @brief setAnglePosition This method sets new angel of the item position arountd center. + * @return newAngle angle position around center. + */ + void setAnglePosition(double newAngle); + +protected: + + /** + * @brief renderRotation This method recalc raration for an @a object. The Default implementation rotate object to center. + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + void renderRotation(GuiObject* object, unsigned int) override; + + /** + * @brief renderRotation This method recalc position for an @a object. The Default implementation move the current object around center. + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + void renderPosition(GuiObject* object, unsigned int tbfMsec) override; + +private: + float _angularVelocity = 0; + QVector3D _axis; + const QVector3D *_center = nullptr; + float _radius; + double _angle = 0; + +}; + +} +#endif // CIRCULARMOTION_H diff --git a/src/engine/src/public/ButterflyEngine/components/claster.cpp b/src/engine/src/public/ButterflyEngine/components/claster.cpp new file mode 100644 index 0000000..f315657 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/claster.cpp @@ -0,0 +1,41 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "claster.h" +#include "Crawl/singleclasterworlditem.h" + +namespace CRAWL { + +Claster::Claster() {} + +Claster::~Claster() { + for (auto child : qAsConst(_objects)) { + if (auto obj = dynamic_cast(child)) + obj->removeClaster(this); + } +} + +void Claster::add(ClasterItem *object) { + _objects.insert(object->guiId(), object); + if (auto singlClasterObject = dynamic_cast(object)) { + singlClasterObject->setClaster(this); + } +} + +void Claster::remove(ClasterItem *object) { + _objects.remove(object->guiId()); +} + +void Claster::remove(int id) { + _objects.remove(id); +} + +const QHash &Claster::objects() const { + return _objects; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/components/claster.h b/src/engine/src/public/ButterflyEngine/components/claster.h new file mode 100644 index 0000000..4a1f1e3 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/claster.h @@ -0,0 +1,61 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CLASTER_H +#define CLASTER_H + +#include "Crawl/iworlditem.h" + +namespace CRAWL { + + +class ClasterItem; + +/** + * @brief The Claster class are object with support multiple objects render. + * For example snake with 20 points of the snake blocks. + * @note The claster object is extansion for the IWorldItems objects. + */ +class CRAWL_EXPORT Claster +{ +public: + Claster(); + + virtual ~Claster(); + + /** + * @brief add This method added new object to claster. + * @param object This is model of added object + * @note if you want you can override this methods for extend functionality of this class. + */ + virtual void add(ClasterItem* object); + + /** + * @brief remove This method remove object from claster + * @param object poiter of removed object + */ + virtual void remove(ClasterItem* object); + + /** + * @brief remove some as a Claster::remove(IWorldItem* object) but by id. + * @param id of the remved object. + */ + virtual void remove(int id); + + /** + * @brief objects This method return list of collected objects. + * @return return const reference to objects list . + */ + const QHash &objects() const; + +private: + QHash _objects; + +}; + +} +#endif // CLASTER_H diff --git a/src/engine/src/public/ButterflyEngine/components/movableobject.cpp b/src/engine/src/public/ButterflyEngine/components/movableobject.cpp new file mode 100644 index 0000000..2c42ad1 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/movableobject.cpp @@ -0,0 +1,94 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "movableobject.h" +#include +#include + +namespace CRAWL { + + +MovableObject::MovableObject() { + +} + +void MovableObject::render(unsigned int tbfMsec) { + + if (auto _this = checkminimumRequariedType()) { + renderPosition(_this, tbfMsec); + renderRotation(_this, tbfMsec); + } +} + +const QVector3D &MovableObject::movableVector() const { + return _movableVector; +} + +void MovableObject::setMovableVector(const QVector3D &newMovableVector) { + _movableVector = newMovableVector; +} + +float MovableObject::angularVelocity() const { + return _angularVelocity; +} + +void MovableObject::setAngularVelocity(float newAngularVelocity) { + _angularVelocity = newAngularVelocity; +} + +float MovableObject::breakingForce() const { + return _breakingForce; +} + +void MovableObject::setBreakingForce(float newBreakingForce) { + _breakingForce = newBreakingForce; +} + +void MovableObject::renderRotation(GuiObject *object, unsigned int) { + if (_currentMovableVector.length() > 0) { + object->setRotation(QQuaternion::rotationTo({1.0f, 0.0, 0.0}, _currentMovableVector) * staticRotation()); + } +} + +void MovableObject::renderPosition(GuiObject *object, unsigned int tbfMsec) { + // get object center position + QVector3D currentPosition = object->position(); + + // move object to vector + currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); + object->setposition(currentPosition); + + // calc temp vector betvin user moveble vector and real moveble vector + QVector3D tempVector = _movableVector - _currentMovableVector ; + + // calc change on this iteration for new moveble vector + float delta = 0.0; + if (_angularVelocity <= 0) { + delta = tempVector.length(); + } else { + delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + } + + // resize temp vector for calc changes of the movableVector + tempVector = tempVector.normalized() * delta; + + // recalc new currentMovable vector (applay changes) + _currentMovableVector += tempVector; + + float newMovableVectorLength = std::max(_movableVector.length() - (_breakingForce * (tbfMsec / 1000.0)), 0.0); + + // update movable vector + _movableVector = _movableVector.normalized() * newMovableVectorLength; + +} + +const QVector3D &MovableObject::currentMovableVector() const { + return _currentMovableVector; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/components/movableobject.h b/src/engine/src/public/ButterflyEngine/components/movableobject.h new file mode 100644 index 0000000..d47f18e --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/movableobject.h @@ -0,0 +1,116 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef MOVABLEOBJECT_H +#define MOVABLEOBJECT_H + +#include "Extensions/basemotion.h" +#include +#include + +namespace CRAWL { + + +class GuiObject; + +/** + * @brief The MovableObject class contains functions for moving object on the world. + * All moving separate to next properties: + * + * * **Movable vector** This property sets direction of move + * * **Movable vector force** This is force of the movable vector. + * * **Angular velocity** This property sets spead of the angle moving. + * * **Braking force** This property are delta decriment the Power of the movable vector on time. + */ +class CRAWL_EXPORT MovableObject: public BaseMotion +{ + +public: + MovableObject(); + + /** + * @brief render This impplementation of the render method add simulation of the physics in the vacuum space. + * @param tbfMsec This is time betwin frames argument. + */ + void render(unsigned int tbfMsec) override; + + /** + * @brief movableVector This method return current mvable vector. + * The movable vector it is second point of line betwin object center and movableVector point. + * The movableVector base on own releative asix system wher the object center is vector {0 0 0} + * @note So movableVector are 3d angle of the moving of this object. + * @return movable vector of object + */ + const QVector3D &movableVector() const; + + /** + * @brief setMovableVector This method sets new value of the mvable vector. + * @param newMovableVector this is a new value ofthe movable vector + * @note The movable vector will be changed in time if you set the MovableObject::breakingForce property to non 0 value. + */ + void setMovableVector(const QVector3D &newMovableVector); + + /** + * @brief angularVelocity This method return current angular veloscity. + * @return angular velosity + * @note This property contains speed on angle per second (a/s) + */ + float angularVelocity() const; + + /** + * @brief setAngularVelocity This method sets new value of the angular velacity in angele per second + * @param newAngularVelocity This is new value of the angular velacity + */ + void setAngularVelocity(float newAngularVelocity); + + /** + * @brief breakingForce This method return current value of the breaking force. + * @return urrent value of the breaking force + */ + float breakingForce() const; + + /** + * @brief setBreakingForce This method sets new value of the breaking force. + * @param newBreakingForce This is new value of the breaking force + */ + void setBreakingForce(float newBreakingForce); + + /** + * @brief currentMovableVector This method return current movable vector. + * @return current movable vector. + */ + const QVector3D ¤tMovableVector() const; + +protected: + + /** + * @brief renderRotation This method recalc raration for an @a object. The Default implementation converts movableVector to rotation of an @a object. + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + void renderRotation(GuiObject* object, unsigned int tbfMsec) override; + + /** + * @brief renderRotation This method recalc position for an @a object. The Default implementation move the current movable vector to setts movable vector. For example if you invoke the MovableObject::setMovableVector method then object change current movable vector with spead MovableObject::angularVelocity. If you sets + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + void renderPosition(GuiObject* object, unsigned int tbfMsec) override; + +private: + QVector3D _movableVector; + QVector3D _currentMovableVector; + QQuaternion _staticRotation = QQuaternion::fromEulerAngles(0,0,0); + + float _angularVelocity = 0; + float _breakingForce = 0; +}; + +} + +#endif // MOVABLEOBJECT_H diff --git a/src/engine/src/public/ButterflyEngine/components/rotationaroundaxis.cpp b/src/engine/src/public/ButterflyEngine/components/rotationaroundaxis.cpp new file mode 100644 index 0000000..f90b8a9 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/rotationaroundaxis.cpp @@ -0,0 +1,28 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "rotationaroundaxis.h" + +#include + +namespace CRAWL { + +RotationAroundAxis::RotationAroundAxis(): CircularMotion(nullptr) { + +} + +void RotationAroundAxis::renderRotation(GuiObject *object, unsigned int tbfMsec) { + setAnglePosition(anglePosition() + angularVelocity() * (tbfMsec / 1000.0f)); + + object->setRotation(QQuaternion::fromAxisAndAngle(axis(), angularVelocity())); +} + +void RotationAroundAxis::renderPosition(GuiObject *, unsigned int ) { + +} + +} diff --git a/src/engine/src/public/ButterflyEngine/components/rotationaroundaxis.h b/src/engine/src/public/ButterflyEngine/components/rotationaroundaxis.h new file mode 100644 index 0000000..f82fcad --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/components/rotationaroundaxis.h @@ -0,0 +1,34 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef ROTATIONAROUNDAXIS_H +#define ROTATIONAROUNDAXIS_H + +#include "circularmotion.h" + +namespace CRAWL { + +/** + * @brief The RotationAroundAxis class This class provide the rotation of our axis + */ +class RotationAroundAxis: public CircularMotion +{ +public: + RotationAroundAxis(); + + // BaseMotion interface +protected: + void renderRotation(GuiObject *object, unsigned int tbfMsec) override; + void renderPosition(GuiObject *object, unsigned int tbfMsec) override; + +}; + +} + + + +#endif // ROTATIONAROUNDAXIS_H diff --git a/src/engine/src/public/ButterflyEngine/core/affector.cpp b/src/engine/src/public/ButterflyEngine/core/affector.cpp new file mode 100644 index 0000000..e8559dd --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/affector.cpp @@ -0,0 +1,32 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "affector.h" + +namespace CRAWL { + +Affector::Affector(const QString &name, + const QString &viewTempalte, + QObject *ptr) : + IWorldItem(name, viewTempalte, ptr) +{ + +} + +bool Affector::enabled() const { + return _enabled; +} + +void Affector::setEnabled(bool newEnabled) { + if (_enabled == newEnabled) + return; + _enabled = newEnabled; + emit enabledChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/affector.h b/src/engine/src/public/ButterflyEngine/core/affector.h new file mode 100644 index 0000000..d8fefeb --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/affector.h @@ -0,0 +1,79 @@ +#ifndef AFFECTOR_H +#define AFFECTOR_H + +#include "iworlditem.h" + + +namespace CRAWL { + +/** + * @brief The Affector class is an abstract base class of affectors like Gravity3D, Wander3D, and PointRotator3D. By default affectors affect all particles in the system, + * but this can be limited by defining the particles list. + * If the system has multiple affectors, the order of affectors may result in different outcome, as affectors are applied one after another. + * + * For custumisation your own Affectors you need to change the templateView qml file for your own class. + * @note For get more inforamtion about available qml affectors see the qt documentation [page](https://doc.qt.io/qt-6.1/qml-qtquick3d-particles3d-affector3d.html) + + **Example of qml view file** + + @code + + Attractor3D { + + property var model: null + property int guiId: (model) ? model.guiId : -1; + + rotation: (model)? model.rotation: Qt.quaternion(0, 0, 0, 0) + scale: (model)? model.size: Qt.vector3d(0, 0, 0); + position: (model) ? model.position: Qt.vector3d(0,0,0); + visible: (model)? model.visible: false + + enabled: (model)? model.enabled: false + + positionVariation: Qt.vector3d(50, 50, 50) + duration: 3000 + durationVariation: 1000 + } + + @endcode +*/ +class CRAWL_EXPORT Affector : public IWorldItem +{ + Q_OBJECT + + /** + * @brief enabled if enabled is set to false, this affector will not alter any particles. Usually this is used to conditionally turn an affector on or off. +The default value is true. + */ + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + +public: + Affector(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + /** + * @brief enabled if enabled is set to false, this affector will not alter any particles. Usually this is used to conditionally turn an affector on or off. +The default value is true. + * @return true if the Affector is enabled else false. + */ + bool enabled() const; + + /** + * @brief setEnabled This method enable or disable the affector object. + * @param newEnabled new value. + */ + void setEnabled(bool newEnabled); + +signals: + /** + * @brief enabledChanged This signal emited when the object change own enabled status. + */ + void enabledChanged(); + +private: + bool _enabled = true; +}; +} + +#endif // AFFECTOR_H diff --git a/src/engine/src/public/ButterflyEngine/core/clasteritem.cpp b/src/engine/src/public/ButterflyEngine/core/clasteritem.cpp new file mode 100644 index 0000000..21225ed --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/clasteritem.cpp @@ -0,0 +1,43 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "Extensions/claster.h" +#include "clasteritem.h" + +namespace CRAWL { + + +ClasterItem::ClasterItem(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { + +} + +ClasterItem::~ClasterItem() { + for (auto claster : qAsConst(_parentClasters)) { + claster->remove(this); + } +} + +int ClasterItem::parentClastersCount() const { + return _parentClasters.size(); +} + +void ClasterItem::setClaster(Claster *claster) { + _parentClasters += claster; +} + +void ClasterItem::removeClaster(Claster *claster) { + _parentClasters -= claster; +} + +const QSet &ClasterItem::parentClasters() const { + return _parentClasters; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/clasteritem.h b/src/engine/src/public/ButterflyEngine/core/clasteritem.h new file mode 100644 index 0000000..70ea6f5 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/clasteritem.h @@ -0,0 +1,65 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iworlditem.h" + +#include + + +#ifndef CLASTERITEM_H +#define CLASTERITEM_H + +namespace CRAWL { + +class Claster; + +/** + * @brief The ClasterItem class This is item of the claster object. Thi class can be used as a one element of the claster class. + * @note This object invoke the Claster::remove method in destructor. + */ +class CRAWL_EXPORT ClasterItem: public IWorldItem +{ + Q_OBJECT +public: + ClasterItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + ~ClasterItem(); + + /** + * @brief parentClastersCount This method return count of the parent clasters. + * @return parent clasters count + */ + int parentClastersCount() const; + +protected: + /** + * @brief setClaster invoked when object added to new claster. + * @param claster pointer to invoker claster object. + */ + virtual void setClaster(Claster *claster); + + /** + * @brief removeClaster + * @param claster + */ + virtual void removeClaster(Claster *claster); + + /** + * @brief parentClasters return current parent clasters list; + * @return + */ + const QSet &parentClasters() const; +private: + + QSet _parentClasters; + + friend class Claster; +}; + +} +#endif // CLASTERITEM_H diff --git a/src/engine/src/public/ButterflyEngine/core/clientapp.cpp b/src/engine/src/public/ButterflyEngine/core/clientapp.cpp new file mode 100644 index 0000000..c2c1b8f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/clientapp.cpp @@ -0,0 +1,95 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clientapp.h" +#include "imageprovider.h" +#include "iworld.h" +#include "mainmenumodel.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "pluginloader.h" +#include +#include "worldstatus.h" +#include "user.h" + +namespace CRAWL { + + +QByteArray ClientApp::initTheme() { + int themeIndex = Settings::instance()->getValue(THEME, THEME_DEFAULT).toInt(); + + switch (themeIndex) { + case 1: return "Dark"; + default: return "Light"; + } +} + + +ClientApp::ClientApp() { + _engine = new Engine(); +} + +ClientApp::~ClientApp() { + delete _engine; +} + +bool ClientApp::init(QQmlApplicationEngine *engine) { + + qputenv("QT_QUICK_CONTROLS_MATERIAL_THEME", initTheme()); + qputenv("QT_QUICK_CONTROLS_STYLE", "Material"); + + auto root = engine->rootContext(); + if (!root) + return false; + + engine->addImageProvider(QLatin1String("userItems"), new ImageProvider()); + + root->setContextProperty("engine", QVariant::fromValue(_engine)); + + qmlRegisterUncreatableMetaObject( + WorldStatus::staticMetaObject, + "engine.worldstatus", + 1, 0, + "WorldStatus", + "Error: only enums"); + + initCrawlResources(); + + engine->addImportPath(":/CrawlModule/"); + + + if (!QmlNotificationService::init(engine)) { + return false; + } + + if (!ViewSolutions::init(engine)) { + return false; + } + + engine->load("qrc:/CrawlModule/Crawl.qml"); + if (engine->rootObjects().isEmpty()) + return false; + + _engine->init(); + + return true; +} + +void ClientApp::addLvl(ILevel *levelWordl) { + _engine->addLvl(levelWordl); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/clientapp.h b/src/engine/src/public/ButterflyEngine/core/clientapp.h new file mode 100644 index 0000000..8880bac --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/clientapp.h @@ -0,0 +1,74 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include +#include +#include +#include "global.h" +#include "ilevel.h" + +class QQmlApplicationEngine; +inline void initCrawlResources() { Q_INIT_RESOURCE(Crawl); } + +namespace CRAWL { + + +class Engine; +class IWorld; +class MainMenuModel; +class IControl; +class Store; + +/** + * @brief The ClientApp class This is main class of the Game engine. + */ +class CRAWL_EXPORT ClientApp : public QObject +{ + Q_OBJECT +public: + ClientApp(); + ~ClientApp() override; + + /** + * @brief init This method initialize engine on application. + * @param engine This is qml engine instance object. + * @return true if all initialize successful + */ + bool init(QQmlApplicationEngine* engine); + + template + + /** + * @brief registerLevel This method register new levels in game. + */ + void registerLevel() { + + static_assert(std::is_base_of_v, + "Plrease use the child classes of the ILevel interface for tegistering new levels in the crawl game."); + + addLvl(new LevelType()); + } + +private: + QByteArray initTheme(); + + /** + * @brief addLvl This method should be add level to game. + * @param levelWordl This is world instance + */ + void addLvl(ILevel* levelWordl); + + Engine *_engine = nullptr; + +}; + +} + +#endif // CLIENTAPP_H diff --git a/src/engine/src/public/ButterflyEngine/core/day.cpp b/src/engine/src/public/ButterflyEngine/core/day.cpp new file mode 100644 index 0000000..0c0d8b8 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/day.cpp @@ -0,0 +1,10 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "day.h" + + diff --git a/src/engine/src/public/ButterflyEngine/core/day.h b/src/engine/src/public/ButterflyEngine/core/day.h new file mode 100644 index 0000000..a509b06 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/day.h @@ -0,0 +1,189 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef DAY_H +#define DAY_H + +#include "Extensions/claster.h" +#include "dayitem.h" +#include "iworlditem.h" +#include "math.h" + +namespace CRAWL { + +template + +/** + * @brief The Day class is template wrapper for the moon and sun objects. + * The moon and sun objects moving around world center for imitation of the day. + * + * ### Integration on the world. + * You need to add one object of this class in the IWorld::initWorldRules method. + * **Example:** + * + * ```cpp + * CRAWL::WorldRule *World::initWorldRules() { + + using Day = CRAWL::Day; + + return new CRAWL::WorldRule { + {0, { + {registerObject(), 1}, + } + }, + {1000, { + {registerObject(), 1}, + } + }, + }; +} + * ``` + * @note All objects will be moving around this objects with radius. The Radius by default is 1000. + * @note This class automaticly sets ligth force for the light objects. + * + * + */ +class Day: public IWorldItem, public Claster +{ + +public: + Day(): IWorldItem(AUTO_CLASS_NAME) { + + static_assert(std::is_base_of_v, + "The Day class can be works only with DayItem child classes"); + + DayItem* sun = new Sun(&position()); + DayItem* moon = new Moon(&position()); + + sun->setAnglePosition(0); + moon->setAnglePosition(180); + + add(sun); + add(moon); + + } + + void render(unsigned int ) override { + setposition(getPlayer()->position() + QVector3D{0, 0, 0}); + } + + void add(ClasterItem *object) override { + + if (auto item = dynamic_cast(object)) { + item->setRadius(radius()); + item->setAxis(_axis); + item->setAngularVelocity(lengthToSpeed(_dayLengthSec)); + item->setLightForce(lengthForce()); + + Claster::add(item); + } else { + QuasarAppUtils::Params::log("The Day class can works only with " + " Child classes of the DayItem", + QuasarAppUtils::Error); + + } + }; + + void remove(ClasterItem *object) override { + Claster::remove(object); + }; + + /** + * @brief radius This method return radius of the motion day objects. + * @return radius of the motions + */ + int radius() const { + return _radius; + } + + /** + * @brief setRadius This method sets new value of the motions radius. + * @param newRadius This is new value o fthe motion. + */ + void setRadius(int newRadius) { + if (newRadius == _radius) + return; + + _radius = newRadius; + + for (auto object: objects()) { + reinterpret_cast(object)->setLightForce(lengthForce()); + reinterpret_cast(object)->setRadius(_radius); + + } + } + + /** + * @brief axis This is sxis of rotation. all objects will be moving around this axis. The axis is general 3d vector object. + * @return rotation axis. + * @note By default it is y axis + */ + const QVector3D &axis() const { + return _axis; + } + + /** + * @brief setAxis This method sets new value of the rotation axis. For get more information see the axis method. + * @param newAxis This is new value of the rotation axis. + */ + void setAxis(const QVector3D &newAxis) { + if (newAxis == _axis) + return; + + _axis = newAxis; + + for (auto object: objects()) { + reinterpret_cast(object)->setAxis(_axis); + } + } + + /** + * @brief dayLengthSec This method return length of the game day in real secs. + * @note by default this value is 360 sec + * @return length of the game day in real secs. + */ + float dayLengthSec() const { + return _dayLengthSec; + } + + /** + * @brief setDayLengthSec This method sets new value of the day length. + * @param newDayLongSec This is new value of the day length. + * @note For get more information see the dayLengthSec method. + */ + void setDayLengthSec(float newDayLengthSec) { + + if (newDayLengthSec == _dayLengthSec) + return; + + _dayLengthSec = newDayLengthSec; + + for (auto object: objects()) { + reinterpret_cast(object)->setAngularVelocity(lengthToSpeed(_dayLengthSec)); + } + } + +private: + float lengthToSpeed(float length) const { + return (2 * M_PI * radius()) / length; + } + + float lengthForce() const { +#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) + return _radius * 0.1; +#else + return _radius * 15; +#endif + } + + int _radius = 1000; + float _dayLengthSec = 360; + QVector3D _axis = {1,0,0}; +}; + +} +#endif // DAY_H diff --git a/src/engine/src/public/ButterflyEngine/core/dayitem.cpp b/src/engine/src/public/ButterflyEngine/core/dayitem.cpp new file mode 100644 index 0000000..2698161 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/dayitem.cpp @@ -0,0 +1,29 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "dayitem.h" + +namespace CRAWL { + +DayItem::DayItem( + const QVector3D* center, + const QString &name, + const QString &viewTempalte, + QObject *ptr): + + IWorldLight(name, viewTempalte, ptr), + CircularMotion(center) { + + +} + +void DayItem::render(unsigned int tbfMsec) { + CircularMotion::render(tbfMsec); + setVisible(position().z() > 0); + +} +} diff --git a/src/engine/src/public/ButterflyEngine/core/dayitem.h b/src/engine/src/public/ButterflyEngine/core/dayitem.h new file mode 100644 index 0000000..330c7fd --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/dayitem.h @@ -0,0 +1,29 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef DAYITEM_H +#define DAYITEM_H + +#include "iworldlight.h" +#include "Extensions/circularmotion.h" +namespace CRAWL { + +/** + * @brief The DayItem class This is base class of the sun of moon of anther movable around center objects. + */ +class DayItem: public IWorldLight, public CircularMotion { + Q_OBJECT +public: + DayItem(const QVector3D* center, + const QString& name, + const QString& viewTempalte = "qrc:/CrawlModule/DayLight.qml", + QObject *ptr = nullptr); + + void render(unsigned int tbfMsec); +}; +} +#endif // DAYITEM_H diff --git a/src/engine/src/public/ButterflyEngine/core/defaultcontrol.cpp b/src/engine/src/public/ButterflyEngine/core/defaultcontrol.cpp new file mode 100644 index 0000000..e99e3d8 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/defaultcontrol.cpp @@ -0,0 +1,19 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "defaultcontrol.h" + +namespace CRAWL { + +DefaultControl::DefaultControl() { + +} + +QString DefaultControl::initQmlView() const { + return "qrc:/CrawlModule/DefaultMenu.qml"; +} +} diff --git a/src/engine/src/public/ButterflyEngine/core/defaultcontrol.h b/src/engine/src/public/ButterflyEngine/core/defaultcontrol.h new file mode 100644 index 0000000..fc65cc7 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/defaultcontrol.h @@ -0,0 +1,44 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef DEFAULTCONTROL_H +#define DEFAULTCONTROL_H + +#include "player.h" + +namespace CRAWL { + + +/** + * @brief The DefaultControl class This class contains default implementation of the game menu. + */ +class CRAWL_EXPORT DefaultControl : public Player { + Q_OBJECT +public: + DefaultControl(); + + /** + * @brief initQmlView This implementation use the DefaultMenu.qml file. + * @return qrc:/CrawlModule/DefaultMenu.qml + */ + QString initQmlView() const; + +signals: + /** + * @brief backToMenu Emit when user click the return to main menu button. + */ + void backToMenu(); + + /** + * @brief userTap Emit when user tap to screen on any position. + */ + void userTap(); +}; + +} + +#endif // DEFAULTCONTROL_H diff --git a/src/engine/src/public/ButterflyEngine/core/defaultlight.cpp b/src/engine/src/public/ButterflyEngine/core/defaultlight.cpp new file mode 100644 index 0000000..f0c915f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/defaultlight.cpp @@ -0,0 +1,27 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "defaultlight.h" + +namespace CRAWL { + +DefaultLight::DefaultLight(): IWorldLight(AUTO_CLASS_NAME) { + setColor("#fff8e7"); + setposition({10000, 0, 10000}); + setRotation(QQuaternion::fromEulerAngles({-90,0,0})); + setLightForce(110); +} + +void DefaultLight::render(unsigned int) { + +} + +void DefaultLight::init() { + +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/defaultlight.h b/src/engine/src/public/ButterflyEngine/core/defaultlight.h new file mode 100644 index 0000000..1343365 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/defaultlight.h @@ -0,0 +1,32 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef DEFAULTLIGHT_H +#define DEFAULTLIGHT_H + +#include "iworldlight.h" + +namespace CRAWL { + +/** + * @brief The DefaultLight class This is default implementation of the world light. + * This object create uniform illumination for all world. + * For integration This object yo worl see the IWorld::initWorldRules method + */ +class DefaultLight final: public IWorldLight +{ + Q_OBJECT +public: + DefaultLight(); + + void render(unsigned int tbfMsec) override; + void init() override; +}; + +} +#endif // DEFAULTLIGHT_H diff --git a/src/engine/src/public/ButterflyEngine/core/diff.cpp b/src/engine/src/public/ButterflyEngine/core/diff.cpp new file mode 100644 index 0000000..a4356c8 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/diff.cpp @@ -0,0 +1,21 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "diff.h" + +namespace CRAWL { + +QList Diff::getAddedIds() const { + return addedIds; +} + +QList Diff::getRemoveIds() const { + return removeIds; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/diff.h b/src/engine/src/public/ButterflyEngine/core/diff.h new file mode 100644 index 0000000..3d10a94 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/diff.h @@ -0,0 +1,35 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef DIFF_H +#define DIFF_H + +#include +#include + +namespace CRAWL { + +class GuiObject; + +/** + * @brief The Diff class contains list of the last changes on a game world. + */ +class Diff { + Q_GADGET + +public: + Q_INVOKABLE QList getRemoveIds() const; + Q_INVOKABLE QList getAddedIds() const; + + QList removeIds; + QList addedIds; +}; + +} +Q_DECLARE_METATYPE(CRAWL::Diff) + +#endif // DIFF_H diff --git a/src/engine/src/public/ButterflyEngine/core/dynamicwint.cpp b/src/engine/src/public/ButterflyEngine/core/dynamicwint.cpp new file mode 100644 index 0000000..c687279 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/dynamicwint.cpp @@ -0,0 +1,60 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "dynamicwint.h" + +namespace CRAWL { + +DynamicWint::DynamicWint() { + +} + +void DynamicWint::render(unsigned int tbfMsec) { + _time += tbfMsec; + + if (_time > _nextWintChange) { + setMagnitude(_baseMagnitude + (rand() % _magnitudeVariation) - _magnitudeVariation / 2 ); + setDirection(QVector3D{static_cast(rand()) - rand(), static_cast(rand()) - rand(), static_cast(rand()) - rand()} * _directionChangeMask); + + _nextWintChange += ((rand() % 100) / 100.0f) * dayLengthSec() * 1000; + } +} + +int DynamicWint::dayLengthSec() const { + return _dayLengthSec; +} + +void DynamicWint::setDayLengthSec(int newDayLengthSec) { + _dayLengthSec = newDayLengthSec; +} + +unsigned int DynamicWint::magnitudeVariation() const { + return _magnitudeVariation; +} + +void DynamicWint::setMagnitudeVariation(unsigned int newMagnitudeVariation) { + _magnitudeVariation = newMagnitudeVariation; +} + +unsigned int DynamicWint::baseMagnitude() const { + return _baseMagnitude; +} + +void DynamicWint::setBaseMagnitude(unsigned int newBaseMagnitude) { + _baseMagnitude = newBaseMagnitude; +} + +const QVector3D &DynamicWint::directionChangeMask() const { + return _directionChangeMask; +} + +void DynamicWint::setDirectionChangeMask(const QVector3D &newDirectionChangeMask) { + _directionChangeMask = newDirectionChangeMask; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/dynamicwint.h b/src/engine/src/public/ButterflyEngine/core/dynamicwint.h new file mode 100644 index 0000000..0da96ad --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/dynamicwint.h @@ -0,0 +1,90 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef DYNAMICWINT_H +#define DYNAMICWINT_H + +#include "wint.h" +namespace CRAWL { + +/** + * @brief The DynamicWint class This implementation dynamicly change wint direction and magnituede per day. + */ +class CRAWL_EXPORT DynamicWint : public Wint +{ + Q_OBJECT +public: + DynamicWint(); + + // IRender interface +public: + void render(unsigned int tbfMsec) override; + + /** + * @brief dayLengthSec This method return length of the game day in real secs. + * @note by default this value is 360 sec + * @return length of the game day in real secs. + */ + int dayLengthSec() const; + + /** + * @brief setDayLengthSec This method sets new value of the day length. + * @param newDayLongSec This is new value of the day length. + * @note For get more information see the dayLengthSec method. + */ + void setDayLengthSec(int newDayLengthSec); + + /** + * @brief magnitudeVariation This method return curerent value of the magnitude variation. + * @return curerent value of the magnitude variation. + */ + unsigned int magnitudeVariation() const; + + /** + * @brief setMagnitudeVariation This method sets magnitude variation; by default it is 10 + * @param newMagnitudeVariation This is new value of the magitude + */ + void setMagnitudeVariation(unsigned int newMagnitudeVariation); + + /** + * @brief baseMagnitude This method return current base magnitude of the wint. The wint will be changed dynamicly one time per day length to the magnitudeVariation + * @return curretn value of the base magnitude + */ + unsigned int baseMagnitude() const; + + /** + * @brief setBaseMagnitude This method sets new value of the base magnitude of the wint. + * @param newBaseMagnitude this is new value of the base magnitude of the wint. + */ + void setBaseMagnitude(unsigned int newBaseMagnitude); + + /** + * @brief directionChangeMask This method return current value of mask of the direction variation. By default the wint will be changed by x and y axis. + * @return curertn value of the directionChangeMask + */ + const QVector3D &directionChangeMask() const; + + /** + * @brief setDirectionChangeMask This method sets mask of the direction variation. By default the wint will be changed by x and y axis. + * @param newDirectionChangeMask This is new value of the directionChangeMask + */ + void setDirectionChangeMask(const QVector3D &newDirectionChangeMask); + +private: + int _dayLengthSec = 360; + unsigned int _nextWintChange = 0; + unsigned int _time = 0; + + unsigned int _magnitudeVariation = 50; + unsigned int _baseMagnitude = 50; + + QVector3D _directionChangeMask = {1, 1, 0}; +}; + +} +#endif // DYNAMICWINT_H diff --git a/src/engine/src/public/ButterflyEngine/core/fire.cpp b/src/engine/src/public/ButterflyEngine/core/fire.cpp new file mode 100644 index 0000000..e3b67f6 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/fire.cpp @@ -0,0 +1,54 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "fire.h" +#include "vectordirection.h" + +namespace CRAWL { + +Fire::Fire(): ParticleEffect(AUTO_CLASS_NAME, "qrc:/CrawlModule/particles/Fire.qml") { + + useDirectionVelosity({0, 0 , 10}, {10, 10, 0}); + setParticleScale(1); + setParticleEndScale(3); + setParticleScaleVariation(3); + + setLifeSpanVariation(500); + setColor("#ffaf2c"); + setposition({0,0,1}); + setEnabled(true); + + setParticleDelegate("qrc:/CrawlModule/particles/FireParticel.qml"); + + setFireStrength(100); +} + +void CRAWL::Fire::onIntersects(const IWorldItem *) { + +} + +float Fire::fireStrength() const { + return _fireStrength; +} + +void Fire::setFireStrength(float newFireStrength) { + if (qFuzzyCompare(_fireStrength, newFireStrength)) + return; + + _fireStrength = newFireStrength; + + setEmitRate(10 + _fireStrength); + setLifeSpan(1000 + _fireStrength); + + auto vel = static_cast(velocity()); + vel->setVelosityDirection({0, 0 , _fireStrength / 4}); + vel->setVelosityDirectionValatility({10, 10, 0}); + + emit fireStrengthChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/fire.h b/src/engine/src/public/ButterflyEngine/core/fire.h new file mode 100644 index 0000000..97d1381 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/fire.h @@ -0,0 +1,59 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef FIRE_H +#define FIRE_H + +#include "particleeffect.h" + +namespace CRAWL { + +/** + * @brief The Fire class This is default implementation of the Fire on game. + */ +class Fire: public ParticleEffect +{ + Q_OBJECT + + /** + * @brief fireStrength This propertye chenge fire power. By Default it is 100. + */ + Q_PROPERTY(float fireStrength READ fireStrength WRITE setFireStrength NOTIFY fireStrengthChanged) +public: + Fire(); + + // IWorldItem interface + + /** + * @brief fireStrength This method return current value of the Fire::fireStrength propertye. + * @return current value of the Fire::fireStrength propertye. + */ + float fireStrength() const; + + /** + * @brief setFireStrength This method sets new value of the Fire::fireStrength propertye. + * @param newFireStrength This is new value of the Fire::fireStrength prpertye. + * @warning This method change the emitRate, lifeSpan and velosity propertyes of this objects, + */ + void setFireStrength(float newFireStrength); + +signals: + + /** + * @brief fireStrengthChanged This signal emited when the Fire::fireStrength propertye is changed. + */ + void fireStrengthChanged(); + +protected: + void onIntersects(const IWorldItem *item); + +private: + float _fireStrength = 0; +}; + +} +#endif // FIRE_H diff --git a/src/engine/src/public/ButterflyEngine/core/gameresult.cpp b/src/engine/src/public/ButterflyEngine/core/gameresult.cpp new file mode 100644 index 0000000..4150ff9 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/gameresult.cpp @@ -0,0 +1,8 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "gameresult.h" diff --git a/src/engine/src/public/ButterflyEngine/core/gameresult.h b/src/engine/src/public/ButterflyEngine/core/gameresult.h new file mode 100644 index 0000000..21930e2 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/gameresult.h @@ -0,0 +1,31 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef GAMERESULT_H +#define GAMERESULT_H + +namespace CRAWL { + +/** + * @brief The GameResult struct This is simple structure with game statistic. + */ +struct GameResult +{ + /** + * @brief points This is count of the receved point in game. + */ + int points = 0; + + /** + * @brief distance this is the distance traveled for the level. + */ + int distance = 0; +}; + +} + +#endif // GAMERESULT_H diff --git a/src/engine/src/public/ButterflyEngine/core/global.h b/src/engine/src/public/ButterflyEngine/core/global.h new file mode 100644 index 0000000..83f6891 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/global.h @@ -0,0 +1,12 @@ +#ifndef Crawl_GLOBAL_H +#define Crawl_GLOBAL_H + +#include + +#if defined(CRAWL_LIBRARY) +# define CRAWL_EXPORT Q_DECL_EXPORT +#else +# define CRAWL_EXPORT Q_DECL_IMPORT +#endif + +#endif // QTSECRET_GLOBAL_H diff --git a/src/engine/src/public/ButterflyEngine/core/groundclaster.cpp b/src/engine/src/public/ButterflyEngine/core/groundclaster.cpp new file mode 100644 index 0000000..e1a451e --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/groundclaster.cpp @@ -0,0 +1,79 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clasteritem.h" +#include "groundclaster.h" +#include "iworld.h" + +namespace CRAWL { + + +GroundClaster::GroundClaster(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { + + +} + +void GroundClaster::render(unsigned int ) { + const IWorldItem *playerObject = getPlayer(); + + if (!_itemsOrder.size()) { + QuasarAppUtils::Params::log("The GroundClaster do not have any claster items.", + QuasarAppUtils::Error); + return; + } + + auto object = _itemsOrder.at(_index % _itemsOrder.size()); + + if (playerObject->position().distanceToPoint(object->position()) > + newObjectDistance()) { + + auto prewObject = _itemsOrder.at((_index - 1) % _itemsOrder.size()); + + object->setposition({prewObject->position().x() + newObjectDistance(), + playerObject->position().y(), + object->position().z() - static_cast(0.0001)}); + + _index++; + } +} + +void GroundClaster::add(ClasterItem *object) { + object->setX(newObjectDistance() * _itemsOrder.count()); + _itemsOrder.push_back(object); + + Claster::add(object); +} + +void GroundClaster::remove(ClasterItem *object) { + _itemsOrder.push_back(object); + + Claster::remove(object); +} + +void GroundClaster::remove(int id) { + _itemsOrder.push_back(objects().value(id)); + + Claster::remove(id); +} + +void GroundClaster::init() { + generateItems(); +} + +int GroundClaster::newObjectDistance() const { + return 500; +} + +unsigned int GroundClaster::itemsCount() const { + return 3; +} + + +} diff --git a/src/engine/src/public/ButterflyEngine/core/groundclaster.h b/src/engine/src/public/ButterflyEngine/core/groundclaster.h new file mode 100644 index 0000000..60e040a --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/groundclaster.h @@ -0,0 +1,58 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef GROUNDCLASTER_H +#define GROUNDCLASTER_H + +#include "Extensions/autogenerateclaster.h" +#include "global.h" +#include "Crawl/iworlditem.h" + +namespace CRAWL { + +/** + * @brief The GroundClaster class This is main control class for background plates of the world. + * Default behavior: create the tile grid and move old tiles to end of the world. + * + * @note use This class with child classes of the GroundTile class. + */ +class CRAWL_EXPORT GroundClaster: public IWorldItem, public AutoGenerateClaster { + + Q_OBJECT + +public: + GroundClaster(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + // IRender interface + void render(unsigned int tbfMsec) override; + + void add(ClasterItem *object) override; + void remove(ClasterItem *object) override; + void remove(int id) override; + void init() override; + unsigned int itemsCount() const override; + +protected: + + /** + * @brief newObjectDistance This method should be return default distance betwin clstersItems + * @return default distance betwin clstersItems + * @note By default this value equals 2000 points + */ + virtual int newObjectDistance() const; + +private: + QList _itemsOrder; + unsigned int _index = 0; + +}; + +} + +#endif // GROUNDCLASTER_H diff --git a/src/engine/src/public/ButterflyEngine/core/groundtile.cpp b/src/engine/src/public/ButterflyEngine/core/groundtile.cpp new file mode 100644 index 0000000..33afab4 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/groundtile.cpp @@ -0,0 +1,14 @@ +#include "groundtile.h" +namespace CRAWL { + +GroundTile::GroundTile(const QString &name, + const QString &viewTempalte, + QObject *ptr): + ClasterItem(name, viewTempalte, ptr) { + +} + +void CRAWL::GroundTile::render(unsigned int) { + +} +} diff --git a/src/engine/src/public/ButterflyEngine/core/groundtile.h b/src/engine/src/public/ButterflyEngine/core/groundtile.h new file mode 100644 index 0000000..5d14c97 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/groundtile.h @@ -0,0 +1,39 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef GROUNDTILE_H +#define GROUNDTILE_H + +#include "clasteritem.h" +#include "iworlditem.h" + +namespace CRAWL { + +/** + * @brief The GroundTile class It reimplementation of the ClasterItem. The groundTile do not heve own render function because the GroundClaster class control position of this class. + * + * @note use This class with the GroundClaster class. + */ +class CRAWL_EXPORT GroundTile: public ClasterItem +{ + Q_OBJECT +public: + GroundTile(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + // IRender interface +public: + + /** + * @brief render The current render implementation do nothing. + * @param tbfMsec This is time betwin frames value. (in milleseconds) + */ + void render(unsigned int tbfMsec) override; +}; +} +#endif // GROUNDTILE_H diff --git a/src/engine/src/public/ButterflyEngine/core/groupobject.cpp b/src/engine/src/public/ButterflyEngine/core/groupobject.cpp new file mode 100644 index 0000000..96e2cc9 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/groupobject.cpp @@ -0,0 +1,104 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clasteritem.h" +#include "groupobject.h" + +namespace CRAWL { + +GroupObject::GroupObject() { + +} + +void GroupObject::render(unsigned int tbfMsec) { + Q_UNUSED(tbfMsec) + + GuiObject* _this = checkminimumRequariedType(); + + for (ClasterItem* object: objects()) { + + if (Localpropertys *props = getLocalpropertys(object->guiId())) { + + if (!props->_rotation.isNull()) + object->setRotation(_this->rotation() * props->_rotation); + + QVector3D reCalcVectorPs = reCalcPos(props->_position, + _this->rotation().toEulerAngles()); + + object->setposition(_this->position() + reCalcVectorPs); + } + + } +} + +void GroupObject::installObject(ClasterItem *object, + const QVector3D &localPosition, + const QQuaternion &localRotation) { + + updatePosition(object->guiId(), localPosition); + updateRotation(object->guiId(), localRotation); + Claster::add(object); +} + +void GroupObject::updatePosition(int id, const QVector3D &position) { + _extrapropertys[id]._position = position; +} + +void GroupObject::updateRotation(int id, const QQuaternion &roatation) { + _extrapropertys[id]._rotation = roatation; +} + +const QVector3D GroupObject::reCalcPos(const QVector3D& pos, const QVector3D &eulerAngles) const +{ + float alha = eulerAngles.z(); + float beta = eulerAngles.y(); + float gamma = eulerAngles.x(); + + float x = pos.x(); + float y = pos.y(); + float z = pos.z(); + + float newX = x*(qCos(alha)*qCos(beta)) + + y*(qCos(alha)*qSin(beta)*qSin(gamma) - qSin(alha)*qCos(gamma)) + + z*(qCos(alha)*qSin(beta)*qCos(gamma) + qSin(alha)*qSin(gamma)); + + float newY = x*(qSin(alha)*qCos(beta)) + + y*(qSin(alha)*qSin(beta)*qSin(gamma) + qCos(alha)*qCos(gamma)) + + z*(qSin(alha)*qSin(beta)*qCos(gamma) - qCos(alha)*qSin(gamma)); + + float newZ = x*(-qSin(beta)) + + y*(qCos(beta)*qSin(gamma)) + + z*(qCos(beta)*qCos(gamma)); + + return QVector3D({newX, newY, newZ}); +} + +QQuaternion *GroupObject::getLocalrotation(int id) { + if (_extrapropertys.contains(id)) { + return &_extrapropertys[id]._rotation; + } + + return nullptr; +} + +QVector3D *GroupObject::getLocalPosition(int id) { + if (_extrapropertys.contains(id)) { + return &_extrapropertys[id]._position; + } + + return nullptr; +} + +Localpropertys *GroupObject::getLocalpropertys(int id) { + if (_extrapropertys.contains(id)) { + return &_extrapropertys[id]; + } + + return nullptr; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/groupobject.h b/src/engine/src/public/ButterflyEngine/core/groupobject.h new file mode 100644 index 0000000..f8208d9 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/groupobject.h @@ -0,0 +1,130 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef GROUPOBJECT_H +#define GROUPOBJECT_H + + + +#include +#include + +namespace CRAWL { + +/** + * @brief The Localpropertys struct This structure contains local propertys of the all childs object of a GroupObject class object. + */ +struct Localpropertys { + QVector3D _position = {0,0,0}; + QQuaternion _rotation = {}; +}; + +/** + * @brief The GroupObject class is extension with group object behavior. + * ### Requried child classes: IWorldItem + * + * This class have implementation of the render method that move all child objects on selected local positions on parent object. + * + * ## Example of use + * + * ### For what this object uses + *This object will be very convenient where you want to create a directly cluster object with multiple sub objects that should contains in the parent root object. + * For example : weapon of the player. + * + * ### Example of use + * + * 1. create the Player class: + * + * ```cpp + * const QVector3d weaponPosition = {1,0,0}; + * const QQuaternion weaponRotation = QQuaternion::fromEilorAngle(90,0,0); + * + * class Player: public IWorldItem, public GroupObject { + * //... some implementation + * void setWeapon(WeaponObject * weapon) { + * installObject(weapon, weaponPosition, weaponRotation); + * } + * //... some implementation + * }; + * ``` + * + * All done. Now the weapon will be static on forward of the Player object. + * + * You can change the position and rotation of the weapon object using updatePosition and updateRotation methods. + * + * @note This class requried the GuiObject functions as a parent class. + */ +class GroupObject: public IRender, public Claster +{ +public: + GroupObject(); + + void render(unsigned int tbfMsec); + + /** + * @brief installObject This method is wrapper of the Claster::add method + * but sets local position and local rotation for an @a object releative current object. + * @param object This is pointer to the adding object. + * @param localPosition This is local position of the @a object. The default value is current object center. + * @param localRotation This is local rotation of the @a object. The default value is invalid quaternion and will be ignored.. + * @note The @a object should be disable own render method of a render method + * or @a object should not be change position and rotation propertys + * @note if you want to ignore the local rotation functionality then set the @a localRotation argument to invalid or default value. + */ + void installObject(ClasterItem* object, + const QVector3D& localPosition = {0,0,0}, + const QQuaternion& localRotation = {}); + + /** + * @brief updatePosition This method sets new releative position of the child object. + * @param id This is id of the object that position need to change. + * @param position This is new value of the object position + */ + void updatePosition(int id, const QVector3D& position); + + /** + * @brief updateRotation This method sets new raleative rotation of the object with @a id. + * @param id This is id of the object that rotation need to change + * @param roatation This is new value of the object with @a id. + */ + void updateRotation(int id, const QQuaternion& roatation); + +protected: + /** + * @brief getLocalrotation This method return current local rotation of the object with @a id. + * @param id This is id of the object that rotation will be returned. + * @return current local rotation ot the object winth @a id. IF the object with id not exists on this classter then return nullptr. + * @warning use this return not const pointer and you can change them value without invoke the updatePosition method but this is not thread safe. + */ + QQuaternion* getLocalrotation(int id); + + /** + * @brief getLocalPosition This method return current local position of the object with @a id. + * @param id This is id of the object that position will be returned. + * @return current local position ot the object winth @a id. IF the object with id not exists on this classter then return nullptr. + * @warning use this return not const pointer and you can change them value without invoke the updateRotation method but this is not thread safe. + + */ + QVector3D* getLocalPosition(int id); + + /** + * @brief getLocalpropertys This method return all local propertys of an object with @a id + * @param id This is id of the object for getting changes. + * @return pointer to structure with local propertys of the object. IF the object with id not exists on this classter then return nullptr. + * @warning use this return not const pointer and you can change them value but this is not thread safe. + */ + Localpropertys* getLocalpropertys(int id); + + +private: + QHash _extrapropertys; + + const QVector3D reCalcPos(const QVector3D& pos, const QVector3D& eulerAngles) const; + +}; +} +#endif // GROUPOBJECT_H diff --git a/src/engine/src/public/ButterflyEngine/core/guiobject.cpp b/src/engine/src/public/ButterflyEngine/core/guiobject.cpp new file mode 100644 index 0000000..9642fb3 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/guiobject.cpp @@ -0,0 +1,227 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "guiobject.h" + +#include + +namespace CRAWL { + + +GuiObject::GuiObject(const QString &name, const QString &viewTempalte, QObject *ptr): + ViewTemaplateModel (viewTempalte, ptr) { + _className = name; + generateId(); + setRotation(QQuaternion::fromEulerAngles({0,0,0})); +} + +const QString& GuiObject::color() const { + return _color; +} + +void GuiObject::setColor(const QString& color) { + if (_color == color) + return; + + _color = color; + emit colorChanged(_color); +} + +void GuiObject::generateId() { + static int id = 0; + setGuiId(id++); +} + +void GuiObject::setContainerSize(const QVector3D &newContainerSize) { + _containerSize = newContainerSize; +} + +bool GuiObject::visible() const { + return _visible; +} + +void GuiObject::setVisible(bool newVisible) { + if (_visible == newVisible) + return; + _visible = newVisible; + emit visibleChanged(); +} + +const QString &GuiObject::className() const { + return _className; +} + +void GuiObject::reset() { + setX(0); + setY(0); + setZ(0); +} + +int GuiObject::guiId() const { + return _guiId; +} + +void GuiObject::setGuiId(int guiId) { + if (guiId == _guiId) + return; + + _guiId = guiId; + emit guiIdChanged(guiId); +} + +void GuiObject::setX(float newX) { + if (qFuzzyCompare(_position.x(), newX)) + return; + _position.setX(newX); + emit positionChanged(); +} + +void GuiObject::setY(float newY) { + if (qFuzzyCompare(_position.y(), newY)) + return; + _position.setY(newY); + emit positionChanged(); +} + +void GuiObject::setZ(float newZ) { + if (qFuzzyCompare(_position.z(), newZ)) + return; + _position.setZ(newZ); + emit positionChanged(); +} + +void GuiObject::setDx(float newDx) { + if (qFuzzyCompare(size().x(), newDx)) + return; + _size.setX(newDx); + emit sizeChanged(); +} + +void GuiObject::setDy(float newDy) { + if (qFuzzyCompare(size().y(), newDy)) + return; + _size.setY(newDy); + emit sizeChanged(); +} + +void GuiObject::setDz(float newDz) { + if (qFuzzyCompare(size().z(), newDz)) + return; + _size.setZ(newDz); + emit sizeChanged(); +} + +const QString &GuiObject::baseColorMap() const { + return _baseColorMap; +} + +const QString &GuiObject::roughnessMap() const { + return _roughnessMap; +} + +const QString &GuiObject::normalMap() const { + return _normalMap; +} + +const QString &GuiObject::emissiveMap() const { + return _emissiveMap; +} + +QVector3D GuiObject::center() const { + return _position + (_size / 2); +} + +bool GuiObject::intersects(const QVector3D &point) const { + auto radius = _containerSize / 2; + float thisMidRadius = (radius.z() + radius.y() + radius.x()) / 3; + return center().distanceToPoint(point) < thisMidRadius ; +} + +bool GuiObject::intersects(const GuiObject &object) const { + auto radius = _containerSize / 2; + auto objRadius = object._containerSize / 2; + float thisMidRadius = (radius.z() + radius.y() + radius.x()) / 3; + float objMidRadius = (objRadius.z() + objRadius.y() + objRadius.x()) / 3; + + return center().distanceToPoint(object.center()) < (thisMidRadius + objMidRadius); +} + +const QVector3D &GuiObject::position() const { + return _position; +} + +void GuiObject::setposition(const QVector3D &newposition) { + if (_position == newposition) + return; + _position = newposition; + emit positionChanged(); +} + +const QVector3D &GuiObject::size() const { + return _size; +} + +void GuiObject::setSize(const QVector3D &newSize) { + if (_size == newSize) + return; + _size = newSize; + emit sizeChanged(); +} + +const QQuaternion &GuiObject::rotation() const { + return _rotation; +} + +void GuiObject::setRotation(const QQuaternion &newRotation) { + if (_rotation == newRotation) + return; + _rotation = newRotation; + emit rotationChanged(); +} + +const QString &GuiObject::mash() const { + return _mash; +} + +void GuiObject::setMash(const QString &newMash) { + if (_mash == newMash) + return; + _mash = newMash; + emit mashChanged(); +} + +void GuiObject::setBaseColorMap(const QString &baseColorMap) { + if (_baseColorMap == baseColorMap) + return; + _baseColorMap = baseColorMap; + emit baseColorMapChanged(); +} + + +void GuiObject::setRoughnessMap(const QString &roughnessMap) { + if (_roughnessMap == roughnessMap) + return; + _roughnessMap = roughnessMap; + emit roughnessMapChanged(); +} + + +void GuiObject::setNormalMap(const QString &normalMap) { + if (_normalMap == normalMap) + return; + _normalMap = normalMap; + emit normalMapChanged(); +} + +void GuiObject::setEmissiveMap(const QString &emissiveMap) { + if (_emissiveMap == emissiveMap) + return; + _emissiveMap = emissiveMap; + emit emissiveMapChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/guiobject.h b/src/engine/src/public/ButterflyEngine/core/guiobject.h new file mode 100644 index 0000000..ab362be --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/guiobject.h @@ -0,0 +1,232 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef GUIOBJECT_H +#define GUIOBJECT_H + +#include "viewtemaplatemodel.h" + +#include +#include +#include +#include "Crawl/irender.h" + +#define DEFAULT_VIEW_TEMPLATE "qrc:/CrawlModule/GraphicItem.qml" +/** the AUTO_CLASS_NAME define gets name from the class and namespace. + */ +#define AUTO_CLASS_NAME typeid(this).name() + +namespace CRAWL { + + +/** + * @brief The GuiObject class This base model for gui objects. + * + * # Overriding Own gui objects. + * + * The gui objct contains base properties for drow objects on scane + * * position + * * rotation + * * mash + * * and map textures + * + * All properies implemented on the GraphicItem.qml file. + * + * If you want to change view for your own object then you need to ooverride the GuiObject::viewTemplate property and create a own qml file for view your changes. + * + * ### Example: + * + * Create a new qml file **OwnView.qml** + * ```qml + * import CrawlModule 1.0 + * + * GraphicItem { + * // your own implementation + * } + * ``` + * + * Override property in cpp object. + * + * ```cpp + * class MyObject: public IWorldItem { + * MyObject(): IWorldItem("name", "qrc:/path/to/OwnView.qml") { + * } + * } + * ``` + */ +class CRAWL_EXPORT GuiObject: public ViewTemaplateModel, virtual public IRender { + Q_OBJECT + Q_PROPERTY(int guiId READ guiId NOTIFY guiIdChanged) + Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged) + + Q_PROPERTY(QVector3D position READ position WRITE setposition NOTIFY positionChanged) + Q_PROPERTY(QVector3D size READ size WRITE setSize NOTIFY sizeChanged) + Q_PROPERTY(QQuaternion rotation READ rotation WRITE setRotation NOTIFY rotationChanged) + + Q_PROPERTY(QString mash READ mash WRITE setMash NOTIFY mashChanged) + + // textures + Q_PROPERTY(QString baseColorMap READ baseColorMap NOTIFY baseColorMapChanged) + Q_PROPERTY(QString roughnessMap READ roughnessMap NOTIFY roughnessMapChanged) + Q_PROPERTY(QString normalMap READ normalMap NOTIFY normalMapChanged) + Q_PROPERTY(QString emissiveMap READ emissiveMap NOTIFY emissiveMapChanged) + + +public: + GuiObject(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + const QString &color() const; + void setColor(const QString &color); + + virtual void reset(); + + void setX(float newX); + void setY(float newY); + void setZ(float newZ); + + void setDx(float newDx); + void setDy(float newDy); + void setDz(float newDz); + + const QString &baseColorMap() const; + const QString &roughnessMap() const; + const QString &normalMap() const; + const QString &emissiveMap() const; + + /** + * @brief center This method return center of object + * @return 3d point of the object center. + * @warning This method calc center in runtime. + */ + QVector3D center() const; + + /** + * @brief intersects This method check if this object contains @a point object. + * @param point This is checked point + * @return true if the point contains in the object cube. + * @warning This functions check intersect approximate and only works correctly for cubic objects. if you try compare plane objects or lines you get incorrect results. + */ + bool intersects(const QVector3D& point) const; + + /** + * @brief intersects This method check intersects betwin current object and @a object. + * @param object This is input object. + * @return true if the two objects has common points. + * @warning This functions check intersect approximate and only works correctly for cubic objects. if you try compare plane objects or lines you get incorrect results. + */ + bool intersects(const GuiObject& object) const; + + const QVector3D &position() const; + void setposition(const QVector3D &newposition); + + const QVector3D &size() const; + void setSize(const QVector3D &newSize); + + const QQuaternion &rotation() const; + void setRotation(const QQuaternion &newRotation); + + const QString &mash() const; + void setMash(const QString &newMash); + + /** + * @brief className This method return class name. + * The class name using as a group of objects on thw world. + * @return class name; + * @note the class name should be sets on the consturctor of child classes of this class. + */ + const QString &className() const; + + /** + * @brief visible This property sets to true if object visibel else false. + * @return true if object is visible + */ + bool visible() const; + + /** + * @brief setVisible This method sets new vlaue of the visible property + * @param newVisible new value of visible + */ + void setVisible(bool newVisible); + + int guiId() const; + void setGuiId(int guiId); + + /** + * @brief containerSize This method sets container size of object. Change this propertye for setting correct work the GuiObject::intersects method. + * @param newContainerSize new is new value of the object contaier cube. + * @see GuiObject::intersects + */ + void setContainerSize(const QVector3D &newContainerSize); + +signals: + void guiIdChanged(int guiId); + void colorChanged(QString color); + + void baseColorMapChanged(); + void roughnessMapChanged(); + void normalMapChanged(); + void emissiveMapChanged(); + + void positionChanged(); + void sizeChanged(); + void rotationChanged(); + + void mashChanged(); + + void visibleChanged(); + +protected: + + /** + * @brief setBaseColorMap This method sets path to the base color map of the object. See the baseColorMap method for get more information. + * @param baseColorMap This is new value of the path to base color map. + */ + void setBaseColorMap(const QString& baseColorMap); + + /** + * @brief setRoughnessMap This method sets path to the roughness map of the object. See the roughnessMap method for get more information. + * @param roughnessMap This is new value of the path to roughness map. + */ + void setRoughnessMap(const QString& roughnessMap); + + /** + * @brief setNormalMap This method sets path to the normal map of the object. See the normalMap method for get more information. + * @param normalMap This is new value of the path to normal map. + */ + void setNormalMap(const QString& normalMap); + + /** + * @brief setEmissiveMap This method sets path to the emissive map of the object. See the emissiveMap method for get more information. + * @param emissiveMap This is new value of the path to emissive map. + */ + void setEmissiveMap(const QString& emissiveMap); + +private: + void generateId(); + + int _guiId = -1; + QString _color = "#ff1111"; + + QString _baseColorMap; + QString _roughnessMap; + QString _normalMap; + QString _emissiveMap; + + QVector3D _position; + QVector3D _size; + QVector3D _containerSize = {1,1,1}; + QQuaternion _rotation; + QString _mash; + QString _className; + bool _visible = true; + Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged) +}; + +} +#endif // GUIOBJECT_H diff --git a/src/engine/src/public/ButterflyEngine/core/iai.cpp b/src/engine/src/public/ButterflyEngine/core/iai.cpp new file mode 100644 index 0000000..33aa30f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iai.cpp @@ -0,0 +1,16 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iai.h" + +namespace CRAWL { + +IAI::IAI() { + +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/iai.h b/src/engine/src/public/ButterflyEngine/core/iai.h new file mode 100644 index 0000000..5c61f9f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iai.h @@ -0,0 +1,42 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IAI_H +#define IAI_H + +#include "global.h" + +namespace CRAWL { + +/** + * @brief The IAI class Is default interface for ai classes. + * @note example of use : + * ```cpp + * class MyAI :public MyControl, public IAI { + * void startAI(); + * void stopAI(); + * } + * ``` + */ +class CRAWL_EXPORT IAI { +public: + IAI(); + virtual ~IAI() = default; + + /** + * @brief startAI This method must be run ai. + */ + virtual void startAI() = 0; + + /** + * @brief stopAI This method must be stop ai. + */ + virtual void stopAI() = 0; +}; + +} +#endif // IAI_H diff --git a/src/engine/src/public/ButterflyEngine/core/icontrol.cpp b/src/engine/src/public/ButterflyEngine/core/icontrol.cpp new file mode 100644 index 0000000..7588f86 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/icontrol.cpp @@ -0,0 +1,36 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "icontrol.h" + +namespace CRAWL { + + +IControl::IControl() { + +} + +IControl::~IControl() { + +} + +const QString &IControl::view() { + if (_view.isEmpty()) { + setView(initQmlView()); + } + + return _view; +} + +void IControl::setView(const QString &newView) { + if (_view == newView) + return; + _view = newView; + emit viewChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/icontrol.h b/src/engine/src/public/ButterflyEngine/core/icontrol.h new file mode 100644 index 0000000..9f5cd10 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/icontrol.h @@ -0,0 +1,63 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CRAWL_ICONTROL_H +#define CRAWL_ICONTROL_H + +#include +#include "global.h" + +namespace CRAWL { + + +/** + * @brief The IControl class This interface should be contains implementation of custom user interface + * How to use this class: + * * inherit of this class + * * add to you class neede signals + * * subscribe to your signals in your world class and your qml interface class. + * For more information see the DefaultControl class. + * + */ +class CRAWL_EXPORT IControl : public QObject { + Q_OBJECT + Q_PROPERTY(QString view READ view NOTIFY viewChanged) + +public: + IControl(); + virtual ~IControl(); + + /** + * @brief initQmlView This method should be return path to qml view element. + * @return path to qml view. + */ + virtual QString initQmlView() const = 0; + + /** + * @brief view This method retun qml view element. + * @return return path to qml view. + */ + const QString &view(); + +signals: + void viewChanged(); + +private: + /** + * @brief setView This method sets new value of qml view element. + * @param newView path to qml view. + */ + void setView(const QString &newView); + + QString _view; + + friend class Engine; +}; + +} + +#endif // CRAWL_ICONTROL_H diff --git a/src/engine/src/public/ButterflyEngine/core/iitem.cpp b/src/engine/src/public/ButterflyEngine/core/iitem.cpp new file mode 100644 index 0000000..b16e11b --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iitem.cpp @@ -0,0 +1,91 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "iitem.h" +#include + +namespace CRAWL { + +IItem::IItem() { + +} + +const QHash& IItem::childItems() const { + return _childs; +} + +QMultiHash IItem::childItemsRecursive() const { + QMultiHash result; + + for (const IItem* item : _childs) { + result.unite(item->childItemsRecursive()); + } + + result.insert(itemId(), this); + return result; +} + +void IItem::addChildItem(const IItem *item) { + _childs.insert(item->itemId(), item); +} + +unsigned int IItem::itemId() { + if (_id) { + return _id; + } + + _id = qHash(itemTextId()); + return _id; +} + +unsigned int IItem::itemId() const { + if (_id) { + return _id; + } + + return qHash(itemTextId()); +} + +const QSet &IItem::activeItems() const { + return _activeItems; +} + +void IItem::setActiveItems(const QSet &newActiveItems) { + _activeItems = newActiveItems; +} + +void IItem::activate(int item) { + _activeItems += item; +} + +void IItem::deactivate(int item) { + _activeItems -= item; +} + +bool IItem::isActive(int item) { + return _childs.contains(item) && _activeItems.contains(item); +} + +unsigned int IItem::itemType() { + if (_typeItem) { + return _typeItem; + } + + _typeItem = qHash(itemTextType()); + return _typeItem; +} + +unsigned int IItem::itemType() const { + if (_typeItem) { + return _typeItem; + } + + return qHash(itemTextType()); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/iitem.h b/src/engine/src/public/ButterflyEngine/core/iitem.h new file mode 100644 index 0000000..cd7b98c --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iitem.h @@ -0,0 +1,191 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef IITEM_H +#define IITEM_H + +#include +#include +#include +#include "global.h" + +namespace CRAWL { + +/** + * @brief The IItem class contains base description of the game items (player perks, game levels, and levels items.) + */ +class CRAWL_EXPORT IItem +{ +public: + IItem(); + virtual ~IItem() = default; + + /** + * @brief itemTextId All items contains own ids, override this method for create base for generate new item id. + * @return item text id. + * @see IItem::itemId + * @note do not use the tr function for implementation of this method. + * If you want to translate the name of the item then use the IItem::itemName method. + */ + virtual QString itemTextId() const = 0; + + /** + * @brief itemTextType This method return text of the item group or type. + * @return text of the item group of type. + * @see IITem::itemType + */ + virtual QString itemTextType() const = 0; + + /** + * @brief itemName This method should be return name of the item. + * @return Name of the item (translated to all supported languages) + */ + virtual QString itemName() const = 0; + + /** + * @brief description This method must be return full description of this item. The description should be translated to all supported languages. + * @return Full description of this item. + */ + virtual QString description() const = 0; + + /** + * @brief image This method should be return path to image preview of the item object. + * @return path to image form qt resources. + */ + virtual QString image() const = 0; + + /** + * @brief cost This method should be return costo to unlock. + * @return costo to unlock. + */ + virtual int cost() const = 0; + + /** + * @brief requiredTier This method return requried level to unlock. + * @return requried level to unlock. + */ + virtual int requiredTier() const = 0; + + /** + * @brief childItems This method shold be return list of the child items available for unlocked for this item. + * @return list of the child items pointers. + * @note The child items connot be removed automaticalu. All child items will be removed in the Store object. + * @see IItem::addChildItem + * @see IItem::childItemsRecursive + */ + const QHash &childItems() const; + + /** + * @brief childItemsRecursive This method return hash map of all items of this item. + * @note This method working recursive. + * @return Hash map of the all child items (include current item). + * @see IItem::addChildItem + * @see IItem::childItems + */ + QMultiHash childItemsRecursive() const; + + /** + * @brief addChildItem This method add child item. + * @param item This is pointe of the item. + * @see IItem::childItems + */ + void addChildItem(const IItem* item); + + /** + * @brief itemId This method return hash of the IItem::itemTextId. + * @return hash of the IItem::itemTextId. + * @see IItem::itemTextId + * @note The not const implementation inlike const implementation write a id to cache. + */ + unsigned int itemId(); + + /** + * @brief itemId This method return hash of the IItem::itemTextId. + * @return hash of the IItem::itemTextId. + * @see IItem::itemTextId + * @warning This method not cached id value, so works sloyle then not cons implementation. + */ + unsigned int itemId() const; + + /** + * @brief itemType This method return item type id. (items group) + * @return item type id. + * @see IItem::itemTextType + * @note The not const implementation inlike const implementation write a id to cache. + */ + unsigned int itemType(); + + /** + * @brief itemType This method return item type id. (items group) + * @return item type id. + * @see IItem::itemTextType + * @warning This method not cached id value, so works sloyle then not cons implementation. + */ + unsigned int itemType() const; + + /** + * @brief activeItems This method return set of the actived items. + * @return set of the actived items. + * @see IItem::setActiveItems + * @see IItem::activate + * @see IItem::deactivate + * @see IItem::isActive + */ + const QSet &activeItems() const; + + /** + * @brief setActiveItems This method sets new set of the actived items. + * @param newActiveItems This is new set of the ctived items. + * @see IItem::activeItems + * @see IItem::activate + * @see IItem::deactivate + * @see IItem::isActive + */ + virtual void setActiveItems(const QSet &newActiveItems); + + /** + * @brief activate This method activate the child item with @a item id of this item. + * @param item activated item id. + * @see IItem::setActiveItems + * @see IItem::activeItems + * @see IItem::deactivate + * @see IItem::isActive + */ + virtual void activate(int item); + + /** + * @brief deactivate This method deactivate the child item with @a item id of this item. + * @param item deactivated item id. + * @see IItem::setActiveItems + * @see IItem::activate + * @see IItem::activeItems + * @see IItem::isActive + */ + virtual void deactivate(int item); + + /** + * @brief isActive This method will be return true if the @a item is actived. else false. If the item not child item of this object the this method return false. + * @param item This is checked item id. + * @return true if the @a item is actived. else false. If the item not child item of this object the this method return false. + * @see IItem::setActiveItems + * @see IItem::activate + * @see IItem::deactivate + * @see IItem::activeItems + */ + bool isActive(int item); + +private: + unsigned int _id = 0; + unsigned int _typeItem = 0; + QHash _childs; + QSet _activeItems; + +}; + +} +#endif // IITEM_H diff --git a/src/engine/src/public/ButterflyEngine/core/ilevel.cpp b/src/engine/src/public/ButterflyEngine/core/ilevel.cpp new file mode 100644 index 0000000..7fdf80f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/ilevel.cpp @@ -0,0 +1,40 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iitem.h" +#include "ilevel.h" +#include "ipreviewscaneworld.h" + +namespace CRAWL { + +ILevel::~ILevel() { + delete _world; + delete _previewScane; +} + +IWorld *ILevel::world() { + return _world; +} + +IPreviewScaneWorld *ILevel::previewScane() { + return _previewScane; +} + +void ILevel::reset() { + _world->reset(); + _previewScane->reset(); +} + +void ILevel::setWorld(IWorld *newWorld) { + _world = newWorld; +} + +void ILevel::setPreviewScane(IPreviewScaneWorld *newPreviewScane) { + _previewScane = newPreviewScane; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/ilevel.h b/src/engine/src/public/ButterflyEngine/core/ilevel.h new file mode 100644 index 0000000..bc21c36 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/ilevel.h @@ -0,0 +1,75 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include + +#ifndef LEVEL_H +#define LEVEL_H + +namespace CRAWL { + + +class IWorld; +class IItem; +class IPreviewScaneWorld; + +/** + * @brief The ILevel class This interface make the world instance object. + * All levels libraries should be override this interface. + * + */ +class ILevel +{ +public: + ILevel() = default; + virtual ~ILevel(); + + /** + * @brief world This method should be return pointer to the level world. + * @return pointer to the level world. + * @see ILevel::setWorld + */ + IWorld* world(); + + /** + * @brief previewScane this method should be create a model of the snake preview scane. + * @return pointer to the model of the preview scane. + * @see ILevel::setPreviewScane + */ + IPreviewScaneWorld* previewScane(); + + /** + * @brief reset This method unload all loaded data from level. + */ + void reset(); + +protected: + /** + * @brief setWorld This method sets new world pointer. + * @param newWorld This is new world model object. + * @note The @a newWorld item will be distroued with the parent object. + * @see ILevel::world + */ + void setWorld(IWorld *newWorld); + + /** + * @brief setPreviewScane This method sets new object for the preview scane. + * @param newPreviewScane This is new value of the preview scane. + * @note The @a newPreviewScane item will be distroued with the parent object. + * @see ILevel::previewScane + */ + void setPreviewScane(IPreviewScaneWorld *newPreviewScane); + +private: + + IWorld* _world = nullptr; + IPreviewScaneWorld* _previewScane = nullptr; +}; + +} + +#endif // LEVEL_H diff --git a/src/engine/src/public/ButterflyEngine/core/ipreviewscaneworld.cpp b/src/engine/src/public/ButterflyEngine/core/ipreviewscaneworld.cpp new file mode 100644 index 0000000..87fdb27 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/ipreviewscaneworld.cpp @@ -0,0 +1,113 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "ipreviewscaneworld.h" +#include "previewcontrol.h" + +namespace CRAWL { + +IPreviewScaneWorld::IPreviewScaneWorld(const IWorld* mainWorld) { + debug_assert(mainWorld, "The mainWorld world option should be initialized."); + _mainWorld = mainWorld; + + setCameraReleativePosition({0, 100, 100}); + setCameraRotation(QQuaternion::fromEulerAngles(-40,0,0)); +} + +QString IPreviewScaneWorld::itemTextId() const { + return "preview"; +} + +QString IPreviewScaneWorld::itemName() const { + return itemTextId(); +} + +QString IPreviewScaneWorld::description() const { + return ""; +} + +QString IPreviewScaneWorld::image() const { + return ""; +} + +int IPreviewScaneWorld::cost() const { + return 0; +} + +int IPreviewScaneWorld::requiredTier() const { + return 0; +} + +PlayableObject *IPreviewScaneWorld::initPlayer(int objectType) const { + return _mainWorld->initPlayer(objectType); +} + +bool IPreviewScaneWorld::start(const StartData& config) { + _configuration = config; + + setPlayer(initPlayer(config.snakeType())); + + worldChanged(worldRules()->cbegin()); + setTargetFps(60); + setVisible(true); + startRenderLoop(); + + return true; +} + +bool IPreviewScaneWorld::stop() { + stopRenderLoopWithClearItems(); + setVisible(false); + + return true; +} + +void IPreviewScaneWorld::handleRotation(double x, double y) { + auto rotation = cameraRotation() * QQuaternion::fromEulerAngles(x, y, 0); + auto normal = (rotation * QVector3D{0,0,1}).normalized(); + + setCameraReleativePosition(normal * 100); + setCameraRotation(rotation); +} + +void IPreviewScaneWorld::handleStart() { + auto playerObj = dynamic_cast(player()); + _configuration.setSnakePerks(playerObj->activeItems()); + emit sigPrepareIsFinished(_configuration); + stop(); +} + +void IPreviewScaneWorld::handleSelect(int item, bool isSelected) { + auto playerItem = dynamic_cast(player()); + + if (isSelected) { + playerItem->activate(item); + } else { + playerItem->deactivate(item); + } +} + +const StartData &IPreviewScaneWorld::configuration() const { + return _configuration; +} + +void IPreviewScaneWorld::initControl(IControl *control) { + auto controlObject = dynamic_cast(control); + + if (controlObject) { + connect(controlObject, &PreviewControl::mousePositionChanged, this, &IPreviewScaneWorld::handleRotation); + connect(controlObject, &PreviewControl::start, this, &IPreviewScaneWorld::handleStart); + connect(controlObject, &PreviewControl::select, this, &IPreviewScaneWorld::handleSelect); + + } +} + +IControl *IPreviewScaneWorld::initUserInterface() const { + return new PreviewControl(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/ipreviewscaneworld.h b/src/engine/src/public/ButterflyEngine/core/ipreviewscaneworld.h new file mode 100644 index 0000000..afedd26 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/ipreviewscaneworld.h @@ -0,0 +1,65 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IPREVIEWSCANEWORLD_H +#define IPREVIEWSCANEWORLD_H + +#include "iworld.h" + +namespace CRAWL { + +/** + * @brief The IPreviewScaneWorld class is interface of the all preview scanes models. + */ +class CRAWL_EXPORT IPreviewScaneWorld: public IWorld +{ + Q_OBJECT +public: + /** + * @brief IPreviewScaneWorld This is main constructo of the preview world model. + * @param mainWorld This pointer to the main world. This is needed for correctly working initPalayer methods. The implementation of the some methods should be identy with the main world. + */ + IPreviewScaneWorld(const IWorld* mainWorld); + + // IItem interface +public: + QString itemTextId() const override final; + QString itemName() const override final; + QString description() const override final; + QString image() const override final; + int cost() const override final; + int requiredTier() const override final; + PlayableObject *initPlayer(int objectType) const override final; + void initControl(IControl *control) override; + IControl* initUserInterface() const override; + bool start(const StartData &config) override; + bool stop() override; + + const StartData &configuration() const; + +signals: + /** + * @brief sigPrepareIsFinished This signal emited when user finished prepare to game. + * @param config This is data for start. + */ + void sigPrepareIsFinished(const StartData& config); + +private slots: + + void handleRotation(double x, double y); + void handleStart(); + void handleSelect(int item, bool isSelected); + +private: + StartData _configuration; + const IWorld* _mainWorld; + + +}; + +} +#endif // IPREVIEWSCANEWORLD_H diff --git a/src/engine/src/public/ButterflyEngine/core/irender.cpp b/src/engine/src/public/ButterflyEngine/core/irender.cpp new file mode 100644 index 0000000..2b30996 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/irender.cpp @@ -0,0 +1,15 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "irender.h" +namespace CRAWL { + +IRender::IRender() +{ + +} +} diff --git a/src/engine/src/public/ButterflyEngine/core/irender.h b/src/engine/src/public/ButterflyEngine/core/irender.h new file mode 100644 index 0000000..a8d35a6 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/irender.h @@ -0,0 +1,63 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IRENDER_H +#define IRENDER_H + +#include "global.h" +#include "quasarapp.h" + +namespace CRAWL { + +/** + * @brief The IRender class This interface provide render functionality for all objects. + * @note Override the render method. + * @note The IRender Interface suppor extension concept + * + * ### Extension concept + * You can create child class of the IRender class and override the render method. But the render method will works with another class object using dynamic_cast of this pointer. + * + */ +class CRAWL_EXPORT IRender { +public: + IRender(); + virtual ~IRender() = default; + + /** + * @brief render This method should be recalc all properyes of the this object. + * @param tbf This is time betwin frame in milesecunds. + */ + virtual void render(unsigned int tbfMsec) = 0; + + /** + * @brief init This method should be invoked after create object. + */ + virtual void init() = 0; + + /** + * @brief checkminimumRequariedType This method check + * @return This object casted to Requared type this objct. + * + * **Example of use**: + * + * ```cpp + * auto _this = checkminimumRequariedType(); + * ``` + */ + template + Requared* checkminimumRequariedType() { + + Requared* result = dynamic_cast(this); + + debug_assert(result, "This render function not support this class"); + + return result; + }; +}; + +} +#endif // IRENDER_H diff --git a/src/engine/src/public/ButterflyEngine/core/iworld.cpp b/src/engine/src/public/ButterflyEngine/core/iworld.cpp new file mode 100644 index 0000000..0aed561 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iworld.cpp @@ -0,0 +1,536 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "Extensions/claster.h" +#include "iai.h" +#include "iworld.h" +#include "iworlditem.h" +#include +#include +#include "groundclaster.h" +#include "defaultcontrol.h" +#include "worldstatus.h" +#include "iai.h" +#include "clasteritem.h" +#include "thread" +#include "chrono" +#include "diff.h" +#include "eventserver.h" +#include "player.h" +#include + +namespace CRAWL { + + +IWorld::IWorld() { + qRegisterMetaType("WorldRule::const_iterator"); + connect(this, &IWorld::sigWorldChanged, this, &IWorld::worldChanged, Qt::QueuedConnection); + + _eventServer = new EventServer(this); + + connect(_eventServer, &EventServer::sigIntersect, this, &IWorld::onIntersects); + connect(this, &IWorld::sigOBjctsListChanged, _eventServer, &EventServer::handleAvailableObjectChanges); + +} + +IWorld::~IWorld() { + disconnect(); + reset(); + delete _eventServer; +} + +QString IWorld::itemTextType() const { + return IWorld::typeText(); +} + +unsigned int IWorld::type() { + return qHash(IWorld::typeText()); +} + +QString IWorld::typeText() { + return "WorldObject"; +} + +void IWorld::init() { +} + +IControl *IWorld::initUserInterface() const { + return new DefaultControl; +} + +void IWorld::render(unsigned int tbfMsec) { + + _ItemsMutex.lock(); + QList toRemove; + for (auto i = _items.begin(); i != _items.end(); ++i) { + if ((*i)->destroyIsScheduled()) + toRemove.push_back((*i)->guiId()); + + (*i)->render(tbfMsec); + } + + _ItemsMutex.unlock(); + + for (int id: toRemove) { + if (id == static_cast(player())->guiId()) { + playerIsDead(static_cast(player())); + } + + removeItem(id); + } + + updateWorld(); + + int waitTime = 1000 / targetFps() - tbfMsec; + if (waitTime > 0) + std::this_thread::sleep_for(std::chrono::milliseconds(waitTime)); +} + +void IWorld::initControl(IControl *control) { + auto controlObject = dynamic_cast(control); + + if (controlObject) { + connect(controlObject, &DefaultControl::backToMenu, this, &IWorld::handleStop); + } +} + +bool IWorld::start(const StartData& config) { + + auto player = dynamic_cast(userInterface()); + if (!player) { + QuasarAppUtils::Params::log("Failed to start world. T userIterface control should be children class of the Palyer class", + QuasarAppUtils::Error); + + return false; + } + + setWorldStatus(WorldStatus::Game); + backgroundAI()->stopAI(); + setPlayer(initPlayer(config.snakeType())); + + player->setUserData(config.player()); + + worldChanged(worldRules()->cbegin()); + setTargetFps(60); + _eventServer->start(); + setVisible(true); + + startRenderLoop(); + + return true; +} + +QObject *IWorld::player() const { + return _player; +} + +void IWorld::setPlayer(QObject *newPlayer) { + if (_player == newPlayer) + return; + + auto newPlayerObject = dynamic_cast(newPlayer); + if (!newPlayerObject) { + QuasarAppUtils::Params::log("Failed to set player object. The input object is not player.", + QuasarAppUtils::Error); + return; + } + + if (_player) + removeItem(_player->guiId()); + + _player = newPlayerObject; + _player->setposition({0,0,0}); + _player->setControl(userInterface()); + + addItem(_player); + + emit playerChanged(); +} + +IWorldItem *IWorld::generate(const QString &objectType) const { + return _registeredTypes.value(objectType, [](){return nullptr;}).operator()(); +} + +bool IWorld::stop() { + _eventServer->stop(); + + stopRenderLoopWithClearItems(); + setVisible(false); + + emit sigGameFinished(); + return true; +} + +IAI *IWorld::initBackGroundAI() const { + return new DefaultBackgroundAI(); +} + +IWorldItem *IWorld::getItem(int id) const { + QMutexLocker lock(&_ItemsMutex); + + return _items.value(id, nullptr); +} + +void IWorld::clearItems() { + + while (_items.cbegin() != _items.cend()) { + removeItem(*_items.cbegin()); + } + + _items.clear(); +} + +void IWorld::addItem(IWorldItem *obj, QList *addedObjectsList) { + if (!obj) + return; + + obj->init(); + Diff diff; + + // Work wih claster + if (auto claster = dynamic_cast(obj)) { + for (auto item : claster->objects()) { + addAtomicItem(item); + if (item) { + diff.addedIds.push_back(item->guiId()); + } + } + } + + addAtomicItem(obj); + diff.addedIds.push_back(obj->guiId()); + + if (addedObjectsList) + *addedObjectsList = diff.addedIds; + + emit sigOBjctsListChanged(diff); + +} + +void IWorld::removeItem(int id, QList *removedObjectsList) { + removeItem(getItem(id), removedObjectsList); +} + +void IWorld::removeItem(IWorldItem* item, QList *removedObjectsList) { + + if (!item) + return; + + Diff diff; + + // Work wih claster + if (auto claster = dynamic_cast(item)) { + const auto copyOfObjectsList = claster->objects(); + for (auto item : copyOfObjectsList) { + auto clasterItem = dynamic_cast(item); + if (!clasterItem || clasterItem->parentClastersCount() > 1) + continue; + + int id = item->guiId(); + + removeAtomicItem(item); + if (removedObjectsList) + diff.removeIds.push_back(id); + + } + } + + removeAtomicItem(item); + diff.removeIds.push_back(item->guiId()); + + if (removedObjectsList) + *removedObjectsList = diff.removeIds; + + emit sigOBjctsListChanged(diff); +} + +void IWorld::reset() { + + stop(); + + if (_player) { + _player = nullptr; + } + + if (_worldRules) { + delete _worldRules; + _worldRules = nullptr; + } + + if (_userInterface) { + delete _userInterface; + _userInterface = nullptr; + } + + if (_backgroundAI) { + delete _backgroundAI; + _backgroundAI = nullptr; + } + + setHdr(""); + +} + + +void IWorld::addAtomicItem(IWorldItem* obj) { + if (!obj) + return; + + QMutexLocker lock(&_ItemsMutex); + + _items.insert(obj->guiId(), obj); + _itemsGroup.insert(obj->className(), obj->guiId()); + + obj->initOnWorld(this); +} + +bool IWorld::removeAtomicItem(int id) { + QMutexLocker lock(&_ItemsMutex); + + auto obj = _items.value(id); + + if (!obj) { + return false; + } + + _itemsGroup.remove(obj->className(), id); + _items.remove(id); + + obj->deleteLater(); + + return true; +} + +bool IWorld::removeAtomicItem(IWorldItem *obj) { + if (!obj) { + return false; + } + + QMutexLocker lock(&_ItemsMutex); + + _itemsGroup.remove(obj->className(), obj->guiId()); + _items.remove(obj->guiId()); + + obj->deleteLater(); + + return true; +} + +void IWorld::removeAnyItemFromGroup(const QString &group, + QList *removedObjectsList) { + int anyObjectId = _itemsGroup.value(group); + removeItem(anyObjectId, removedObjectsList); +} + +void IWorld::startRenderLoop() { + if (isRendering()) + return; + + _renderLoop = true; + _renderLoopFuture = QtConcurrent::run([this](){renderLoop();}); +} + +void IWorld::stopRenderLoopWithClearItems() { + stopRenderLoop(); + clearItems(); +} + +void IWorld::stopRenderLoop() { + _renderLoop = false; + _renderLoopFuture.waitForFinished(); +} + +bool IWorld::isRendering() const { + return _renderLoopFuture.isRunning(); +} + +void IWorld::renderLoop() { + + while (_renderLoop) { + + quint64 currentTime = QDateTime::currentMSecsSinceEpoch(); + + if (!_oldTimeRender) { + _oldTimeRender = currentTime; + continue; + } + + render(currentTime - _oldTimeRender); + _oldTimeRender = currentTime; + } +} + +const WorldRule *IWorld::worldRules() { + + if (!_worldRules) + _worldRules = initWorldRules(); + + return _worldRules; +} + +void IWorld::setVisible(bool visible) { + if (_visible == visible) { + return; + } + + _visible = visible; + emit visibleChanged(); +} + +void IWorld::playerIsDead(PlayableObject *) { + stop(); +} + +int IWorld::targetFps() const { + return _targetFps; +} + +void IWorld::setTargetFps(int newTargetFps) { + _targetFps = newTargetFps; +} + +void IWorld::setHdr(const QString &hdr) { + if (hdr == _hdrMap) + return; + + _hdrMap = hdr; + emit hdrChanged(); +} + +void IWorld::updateWorld() { + + if (_currendWorldLevel->isEmpty() || !_player) + return; + + float distance = _player->position().x(); + auto nextLevel = std::next(_currendWorldLevel); + if (nextLevel != _worldRules->cend() && distance > nextLevel.key()) { + emit sigWorldChanged(nextLevel); + } +} + +void IWorld::onIntersects(const IWorldItem *trigger, QList list) { + + for (const IWorldItem* item : list) { + const_cast(item)->action(const_cast(trigger)); + } +} + +const QQuaternion &IWorld::cameraRotation() const { + return _cameraRotation; +} + +void IWorld::setCameraRotation(const QQuaternion &newCameraRotation) { + if (_cameraRotation == newCameraRotation) + return; + _cameraRotation = newCameraRotation; + emit cameraRotationChanged(); +} + +IAI *IWorld::backgroundAI() { + + if (!_backgroundAI) { + _backgroundAI = initBackGroundAI(); + initControl(dynamic_cast(_backgroundAI)); + } + + return _backgroundAI; +} + +IControl *IWorld::userInterface() { + + if (!_userInterface) { + _userInterface = initUserInterface(); + initControl(_userInterface); + } + + return _userInterface; +} + +void IWorld::setCameraReleativePosition(const QVector3D &newCameraReleativePosition) { + if (_cameraReleativePosition == newCameraReleativePosition) + return; + + _cameraReleativePosition = newCameraReleativePosition; + emit cameraReleativePositionChanged(); +} + +void IWorld::handleStop() { + stop(); +} + +const QVector3D &IWorld::cameraReleativePosition() const { + return _cameraReleativePosition; +} + +void IWorld::worldChanged(WorldRule::const_iterator iterator) { + + if (_currendWorldLevel == iterator) + return; + + auto objects = iterator.value(); + objects[_player->className()] = 1; + + for (auto it = objects.begin(); it != objects.end(); ++it) { + + int count = it.value() - _itemsGroup.count(it.key()); + + if (count > 0) { + for ( int i = 0; i < count; ++i ) { + addItem(generate(it.key())); + } + } else { + for (; count < 0; ++count ) { + removeAnyItemFromGroup(it.key()); + } + } + } + + _currendWorldLevel = iterator; +} + +int IWorld::wordlStatus() const { + return _worldStatus; +} + +void IWorld::setWorldStatus(int newWorldStatus) { + if (_worldStatus == newWorldStatus) { + return; + } + _worldStatus = newWorldStatus; + emit worldStatusChanged(); +} + + +const QString &IWorld::hdr() { + if (_hdrMap.isEmpty()) + setHdr(initHdrBackGround()); + + return _hdrMap; +} + +void IWorld::runAsBackGround() { + StartData data(nullptr, 0); + start(data); + + setWorldStatus(WorldStatus::Background); + _player->setControl(dynamic_cast(_backgroundAI)); + + _backgroundAI->startAI(); + + setTargetFps(30); +} + +QObject *IWorld::getMenu() { + return userInterface(); +} + +bool IWorld::visible() const { + return _visible; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/iworld.h b/src/engine/src/public/ButterflyEngine/core/iworld.h new file mode 100644 index 0000000..30e97e8 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iworld.h @@ -0,0 +1,582 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CRAWL_IWORLD_H +#define CRAWL_IWORLD_H + +#include "gameresult.h" +#include "iitem.h" +#include "playableobject.h" +#include "startdata.h" + +#include +#include +#include +#include +#include +#include +#include +#include "irender.h" +#include "global.h" +#include +#include "Crawl/diff.h" + +class ClastersTest; + +namespace CRAWL { + +/** + * @brief The Events enum contains availabele events of the World. + */ +enum Events { + /// If object support this event then for them will be check intersection with all not decorative objects. + Intersects = 0x01, +}; + +class IWorldItem; +class PlayableObject; +class GroundClaster; +class IControl; +class IAI; +class IWorldLight; +class EventServer; +class Player; + +/** + * @brief WorldObjects This is map list of the avalable objects and its count on a lvl-long point. + */ +typedef QMap WorldObjects; + +/** + * @brief WorldRule This is list of the lvl-long points and its rules. For get more information see the WorldOBjects typedef. + */ +typedef QMap WorldRule; + +/** + * @brief The IWorld class use this interface for implementation your own game levels + */ +class CRAWL_EXPORT IWorld : public QObject, public IRender, public IItem +{ + Q_OBJECT + Q_PROPERTY(QVector3D cameraReleativePosition READ cameraReleativePosition NOTIFY cameraReleativePositionChanged) + Q_PROPERTY(QQuaternion cameraRotation READ cameraRotation NOTIFY cameraRotationChanged) + Q_PROPERTY(QObject * player READ player WRITE setPlayer NOTIFY playerChanged) + + /** + * @brief menu This propertye contains user interface model that initialised on the IWorld::userInterface method. For get more information see the IContol class. + * @see IWorld::getMenu + * @see IWorld::userInterface + */ + Q_PROPERTY(QObject * menu READ getMenu NOTIFY menuChanged) + Q_PROPERTY(QString hdr READ hdr NOTIFY hdrChanged) + Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged) + + Q_PROPERTY(int worldStatus READ wordlStatus WRITE setWorldStatus NOTIFY worldStatusChanged) + +public: + IWorld(); + ~IWorld() override; + + QString itemTextType() const override; + + /** + * @brief type This method return const string value of the all world types. + * @return const string value of the all world types. + * @see IItem::itemTextType + * @see IItem::type + */ + static QString typeText(); + + /** + * @brief type This is wrapper of the IWorld::typeText method that invoke the qHash function for results string. + * @return integer type object id. + */ + static unsigned int type(); + + void init() override; + + /** + * @brief initPlayer The implementation of This interface must be return playerObject by type. + * @param objectType This is type of requried snake object. + * @return raw pointer to the player object. + * @note The Palyer object will be deleted when wold distroed. + * So do not delete your created player pbject yuorself. + */ + virtual PlayableObject* initPlayer(int objectType) const = 0; + + /** + * @brief initWorldRules The implementation of this interface must be retun initialized list of the world rules. + * For more information see the WorldRules map. + * + * Example of use : + * + * ```cpp + * WorldRule *World::initWorldRules() { + * return new WorldRule { + * { + * 0, {{registerObject(), 10}}, + * 100, {{registerObject(), 10}, {registerObject(), 1}}, + * } + * }; + * } + * ``` + * + * @return a raw pointer to world a rules map. + * @note The Palyer object will be deleted when wold distroed. + * So do not delete your created player pbject yuorself. + * + * + */ + virtual WorldRule* initWorldRules() = 0; + + /** + * @brief initUserInterface This method should be return point to userInterface object. + * @note The base implementation return default user interface. + * @return pointer to userInterface. + */ + virtual IControl *initUserInterface() const; + + /** + * @brief initHdrBackGround The implementation of this method must be return valid path to the hdr image map. + * The hdr image map it is background jpeg image. + * @return path to hfr map. + */ + virtual QString initHdrBackGround() const = 0; + + /** + * @brief render this method recursive invoke all render functions of the all world items. + * The render function is main function of the SnakeEngine This method recal all propertys of all objects. + */ + virtual void render(unsigned int tbfMsec) override; + + /** + * @brief initControl This method should be configure all connections of @a control object. + * @param control This is control object + * @note override this method if you have own IControl object. + */ + virtual void initControl(IControl* control); + + /** + * @brief start This method will be invoked when user click start button. + * @param config This is initialize level arguments. + * @note The Default implementation reset all positions for all objects. + * @return true if game started successful. + */ + virtual bool start(const StartData &config); + + /** + * @brief stop This methos will be invoked when user click to return to main menu button. + * @note The default implementation sets new status of the world WordlStatus::Background. + * @return true if aworld stoped successful + */ + virtual bool stop(); + + /** + * @brief backGroundAI This method shuld be return pointer to control object for background AI. + * @return raw pointer of backgroundAI. + */ + virtual IAI *initBackGroundAI() const; + + /** + * @brief getItem This method return raw pointer to object by id. + * @param id This is id of a required object. + * @return pointe to requaried object. + * @note if you want to get ovject in the render function of another ItemWorld object then use the IWorldItem::getItem method. + */ + Q_INVOKABLE IWorldItem *getItem(int id) const; + + /** + * @brief cameraReleativePosition return a releative of player camera position. + * @return + */ + const QVector3D &cameraReleativePosition() const; + + /** + * @brief userInterface This method return pointer to userinterface. + * @return pointer to user interface + */ + IControl *userInterface(); + + /** + * @brief wordlStatus This method return current world status. + * @return integer code of the status. + */ + int wordlStatus() const; + + /** + * @brief setWorldStatus This method sets new status of world. + * @param newWorldStatus new status of world + */ + void setWorldStatus(int newWorldStatus); + + /** + * @brief backgroundAI This method return current backgroundAI. + * @return Raw pointer to background AI object + */ + IAI *backgroundAI(); + + /** + * @brief cameraRotation This method return curent camera rotation. + * @return Quaternion of camera rotation + */ + const QQuaternion &cameraRotation() const; + + /** + * @brief player This method return player object + * @return player object + */ + QObject *player() const; + + /** + * @brief hdr This method return path to hdr map of the lvl. + * @return path to hdr map of this lvl. + */ + const QString &hdr(); + + /** + * @brief runAsBackGround This method run this world as a backgroud. + * The player start new game and sets new control from the backgroundAI method. + */ + void runAsBackGround(); + + /** + * @brief menu This method return current pointer to the user interface of this world. + * @return pointer of the user Interface of this world. + * @see IWorld::menu + * @see IWorld::userInterface + */ + QObject *getMenu(); + + /** + * @brief reset This method reset all world objects. + */ + void reset(); + + /** + * @brief visible This metohd retunr current value of the visible object. + * @return true if view is visible else false. + */ + bool visible() const; + +signals: + /** + * @brief sigGameFinished This signal emit when game are finished + */ + void sigGameFinished() const; + + /** + * @brief sigOBjctsListChanged This signal emited when lvel status are changed. + * @brief diff This is list of removed and addeds items + */ + void sigOBjctsListChanged(CRAWL::Diff diff); + + /** + * @brief cameraReleativePositionChanged This signal emot when releative position of camera cahged. + */ + void cameraReleativePositionChanged(); + + /** + * @brief sigLoadProgressChanged This signal emit when progress of the loading lvl changed. + * @brief progress - This is integer value of the loading progress. (availabel ranges: 0% - 100%) + */ + void sigLoadProgressChanged(int progress); + + /** + * @brief worldStatusChanged This signal emited when world status has been changed + */ + void worldStatusChanged(); + + /** + * @brief cameraRotationChanged This method emited when rotation of the camera cahnged + */ + void cameraRotationChanged(); + + /** + * @brief playerChanged This signal eited when player are changed. + */ + void playerChanged(); + + /** + * @brief hdrChanged This signal emited when the hdr map are changed. + */ + void hdrChanged(); + + /** + * @brief sigWorldChanged emit this signal if you want to change level of the world. + * @note this signal needed for the move WorldChange method into main thread. + * @param objects this is iterator of the world rule object. + */ + void sigWorldChanged(WorldRule::const_iterator objects); + + /** + * @brief menuChanged This signal emited when user interface is changed. + */ + void menuChanged(); + + /** + * @brief visibleChanged This signal emited when visible of the view changed. + */ + void visibleChanged(); + +protected: + + /** + * @brief setPlayer This method sets new player object + * @param newPlayer This is new player object. + * @note This method remove old player object if it exists + */ + void setPlayer(QObject *newPlayer); + + /** + * @brief generate This method shold be generate object from the @a objectType. + * Override this method for add support yourown objects. + * @note If your objects not requre custom setting then use the default implementation of the generate method. + * @param objectType This is string type name of the object, + * @return pointer to the object. + * + * **Example** + * ```cpp + * IWorldItem* generate(const QString& objectType)) const { + * auto registeredObject = IWorld::generate(objectType); + * if (registeredObject) { + * // process creating of object. + * } + * return registeredObject; + * } + * ``` + */ + virtual IWorldItem* generate(const QString& objectType) const; + + /** + * @brief setCameraReleativePosition This method update camera position + * @param newCameraReleativePosition This is new camera position releative of player. + */ + void setCameraReleativePosition(const QVector3D &newCameraReleativePosition); + + /** + * @brief setCameraRotation This method sets new rotation of the camera. + * @param newCameraRotation new rotation of the camera. + */ + void setCameraRotation(const QQuaternion &newCameraRotation); + + /** + * @brief targetFps This method return current targetFps; + * @return current target FPS. + */ + int targetFps() const; + + /** + * @brief setTargetFps This method sets new targetFps. + * @param newTargetFps This is new value of target Fps; + */ + void setTargetFps(int newTargetFps); + + /** + * @brief setHdr This method sets new path to hdr map of this lvl. + * @param hdr path to hdr map. + */ + void setHdr(const QString& hdr); + + template + + /** + * @brief registerObject This method will register object type for generation on the world. + * + * Example of use: + * + * ```cpp + * ... + * QString className = registerObject(); + * ... + * ``` + * + * @return name of registered class. + */ + QString registerObject() { + + static_assert(std::is_base_of_v, + "You try register no IWorldItem class. Please inherit of IWorldItem class and try again"); + + QString type = Type().className(); + + if (!_registeredTypes.contains(type)) { + + auto wraper = []() { + return new Type(); + }; + + _registeredTypes.insert(type, wraper); + } + + return type; + } + + /** + * @brief updateWorld This method check current distance and load neede level and level objects. + */ + void updateWorld(); + + /** + * @brief worldRules This method return world cure map. + * @return world rule map. + */ + const WorldRule *worldRules(); + + /** + * @brief setVisible This method sets visible propertye for the qml view. + * @param visible This is new value of a property + */ + void setVisible(bool visible); + + /** + * @brief playerIsDead This method will be invoked when player object get signal dead. + */ + virtual void playerIsDead(PlayableObject*); + + /** + * @brief isRendering This method erturn true if the render loop is working else false. + * @return true if the render loop is working else false. + * @see IWorld::stopRenderLoop + * @see IWorld::startRenderLoop + */ + bool isRendering() const; + + /** + * @brief stopRenderLoop This method stop render loop in engine. + * @see IWorld::isRendering + * @see IWorld::startRenderLoop + */ + void stopRenderLoop(); + + /** + * @brief startRenderLoop This method start render loop in engine. + * @see IWorld::stopRenderLoop + * @see IWorld::isRendering + */ + void startRenderLoop(); + + /** + * @brief stopRenderLoopWithClearItems This method stoped render loop and clear all created items. + * @see IWorld::stopRenderLoop + */ + void stopRenderLoopWithClearItems(); + +protected slots: + virtual void onIntersects(const IWorldItem * trigger, QList list); + + /** + * @brief worldChanged This method generate diff for the qml + * @param objects This is iterator of the world rules object that contains list of object on lvl + * @note This method addd player object to this list. + */ + void worldChanged(WorldRule::const_iterator objects); + +private slots: + + /** + * @brief handleStop This slot invoked when user click return main menu button. + */ + void handleStop(); + +private: + /** + * @brief clearItems This method remove all created items from world. + */ + void clearItems(); + + /** + * @brief addItem This method remove object from the scane. If object are calster then this method remove all child objects. + * @param obj pointer to any engine object. + * @param addedObjectsList This is list of added items into world. + */ + void addItem(IWorldItem *obj, + QList* addedObjectsList = nullptr); + + /** + * @brief removeItem This method remove item from the world. If the @a id are id of the claster object then its child object will be removed too. + * @param id This is id of removed object. + * @param removedObjectsList This is list of removed objects. Leave this argument nullptr for ignore this argument. + * @note this is wrapper of the removeItem(IWorldItem*, QList*); + */ + void removeItem(int id, + QList* removedObjectsList = nullptr); + + /** + * @brief removeItem This method remove item from the world. If the @a id are id of the claster object then its child object will be removed too. + * @param item This is object than will be removed. + * @param removedObjectsList This is list of removed objects. Leave this argument nullptr for ignore this argument. + */ + void removeItem(IWorldItem* item, + QList* removedObjectsList = nullptr); + + /** + * @brief addAtomicItem This method execure atomic operation of add new item. This method support only atomic objects. (not clasters) + * @param obj This is pointer to the atomic object. If the object are claster then it will be added without childs objects. + */ + void addAtomicItem(IWorldItem *obj); + + /** + * @brief removeAtomicItem This method remove object with @a id. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. + * @param id This is id of removed objects. + * @return return true if object remove successul + */ + bool removeAtomicItem(int id); + + /** + * @brief removeAtomicItem This method remove object @a obj. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. + * @param obj This is id of removed objects. + * @return return true if object remove successul + */ + bool removeAtomicItem(IWorldItem *obj); + + /** + * @brief removeAnyItemFromGroup This method remove any object from group and return id of removed object. If The objec are claster then this method remove all child objects. + * @param group This is name of the objects group + * @param removedObjectsList This is list of removed objcts. + * @return id of removed object. + */ + void removeAnyItemFromGroup(const QString &group, + QList* removedObjectsList = nullptr); + + void renderLoop(); + QFuture _renderLoopFuture; + + EventServer * _eventServer = nullptr; + + QHash _items; + QMultiHash _itemsGroup; + QMultiHash _lastItemsGroup; + + mutable QMutex _ItemsMutex; + + QVector3D _cameraReleativePosition; + QQuaternion _cameraRotation; + + QString _hdrMap; + WorldRule *_worldRules = nullptr; + WorldRule::const_iterator _currendWorldLevel; + + PlayableObject *_player = nullptr; + IAI *_backgroundAI = nullptr; + IControl *_userInterface = nullptr; + + int _worldStatus = 0; + QHash> _registeredTypes; + + int _targetFps = 60; + quint64 _oldTimeRender = 0; + + bool _visible = true; + bool _renderLoop = false; + + // testing + friend ClastersTest; + +}; + +} +#endif // CRAWL_IWORLD_H diff --git a/src/engine/src/public/ButterflyEngine/core/iworlditem.cpp b/src/engine/src/public/ButterflyEngine/core/iworlditem.cpp new file mode 100644 index 0000000..d08a21d --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iworlditem.cpp @@ -0,0 +1,126 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iworlditem.h" +#include "iworld.h" +#include "quasarapp.h" + +namespace CRAWL { + + +IWorldItem::IWorldItem(const QString& name, + const QString& viewTempalte, + QObject *ptr): + GuiObject(name, viewTempalte, ptr) { + +} + +const IWorldItem *IWorldItem::getItem(int id) const { + if (!_world) { + QuasarAppUtils::Params::log("You try get object in the no initialized _itemWorld object.", + QuasarAppUtils::Error); + return nullptr; + } + + return _world->getItem(id); +} + +const IWorldItem *IWorldItem::getPlayer() const { + if (!_world) + return nullptr; + return static_cast(_world->player()); +} + +void IWorldItem::render(unsigned int) { + auto _playerObject = getPlayer(); + + if (!_playerObject) + return; + + if (_fFirstRenderIteration) { + firstSpawn(); + _fFirstRenderIteration = false; + } + + if (_playerObject->position().distanceToPoint(position()) > + _world->cameraReleativePosition().z() * 3) { + respawn(); + } +} + +void IWorldItem::init() {} + +void IWorldItem::initOnWorld(const IWorld *world) { + _world = world; +} + +int IWorldItem::supportedEvents() const { + return _supportedEvents; +} + +bool IWorldItem::isSopportEvent(int event) const { + return (_supportedEvents & event) == event; +} + +void IWorldItem::destroy() { + _fDistroy = true; +} + +void IWorldItem::respawn() { + auto _playerObject = getPlayer(); + + if (!_playerObject) + return; + + float dX = _world->cameraReleativePosition().z() * 2 + + (rand() % static_cast(_world->cameraReleativePosition().z())); + + setX(_playerObject->position().x() + dX); + + float dY = (rand() % static_cast(_world->cameraReleativePosition().z() * 3) + - _world->cameraReleativePosition().z() * 1.5); + + setY(_playerObject->position().y() + dY); +} + +void IWorldItem::firstSpawn() { + +} + +bool IWorldItem::destroyIsScheduled() const { + return _fDistroy; +} + +void IWorldItem::action(IWorldItem *) { + +} + +void IWorldItem::setSupportedEvents(int newSupportedEvents) { + _supportedEvents = newSupportedEvents; +} + +void IWorldItem::addSupportOfEvent(int newSupportedEvent) { + _supportedEvents = _supportedEvents | newSupportedEvent; +} + +void IWorldItem::dropSupportOfEvent(int depricatedEvent) { + _supportedEvents = _supportedEvents & (~depricatedEvent); +} + +bool IWorldItem::isDecorative() const { + return _fDecorative; +} + +void IWorldItem::setFDecorative(bool newFDecorative) { + _fDecorative = newFDecorative; +} + +const IWorld *IWorldItem::world() const { + return _world; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/iworlditem.h b/src/engine/src/public/ButterflyEngine/core/iworlditem.h new file mode 100644 index 0000000..e069165 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iworlditem.h @@ -0,0 +1,155 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef IWORLDITEM_H +#define IWORLDITEM_H + +#include +#include "global.h" + +namespace CRAWL { + +class IWorld; +/** + * @brief The IWorldItem class This is World item. This class contains functions for control event system. + */ +class CRAWL_EXPORT IWorldItem: public GuiObject { + Q_OBJECT + +public: + IWorldItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + const IWorld *world() const; + + /** + * @brief render This implementation move objects from end of scane to begin. + * @param tbfMsec + * @note new position = playerPosition + scaneSize; + */ + void render(unsigned int tbfMsec) override; + void init() override; + + /** + * @brief isDecorative This method return true if the object is decarative. + * The decorative objects not patricipate in event process. + * @return true if this ovjects is decorative. + */ + bool isDecorative() const; + + /** + * @brief supportedEvents This method return mask of the supported events. For get more information about events see the CRAWL::Events enum. + * @return integer mask of the supported events. + * @see IWorldItem::setSupportedEvents + * @see IWorldItem::addSupportOfEvent + * @see IWorldItem::dropSupportOfEvent + * @see IWorldItem::supportedEvents + */ + int supportedEvents() const; + + /** + * @brief isSopportEvent This method return true ithis objects support a @a event.f + * @return true if this objects support a @a event else false. + * @note If a @a event is mask with multiple events the this method return true if this objects support all events from a @a event mask. + */ + bool isSopportEvent(int event) const; + + /** + * @brief destroy this method will schedule a destroing of this object on the world. + * @see IWorldItem::destroyIsScheduled + */ + virtual void destroy(); + + /** + * @brief respawn this method will schedule a repawning of this object on the world. + */ + virtual void respawn(); + + /** + * @brief firstSpawn This method is respawn this object on the world when it created. By Default this method do nothing. + */ + virtual void firstSpawn(); + + /** + * @brief destroyIsScheduled This method return true if the current object has been scheduled to destroy. + * @return true if the current object has been scheduled to destroy, else false. + * @see IWorldItem::destroy + */ + bool destroyIsScheduled() const; + + /** + * @brief action This method contains actions releative another game objects. + * @param item This is pointer to item that will be interaction with this object. + * @note The default implementation do nothing. + */ + virtual void action(IWorldItem* item); + +protected: + + /** + * @brief getItem This method return item world by id. If object is not exits then return nullptr. + * @return constant pointer tot the item world. + */ + const IWorldItem * getItem(int id) const; + + /** + * @brief getPlayer This method return pointer to player object. + * @return raw pointer to playerObject + */ + const IWorldItem * getPlayer() const; + + /** + * @brief setFDecorative This method sets if object declarative or physical. + * @param newFDecorative new value of the fDecorative property + */ + void setFDecorative(bool newFDecorative); + + /** + * @brief setSupportedEvents This method overwrite the mask og the supported events. + * @param newSupportedEvents This is new value of the supported events mask. + * @see IWorldItem::setSupportedEvents + * @see IWorldItem::addSupportOfEvent + * @see IWorldItem::dropSupportOfEvent + * @see IWorldItem::supportedEvents + */ + void setSupportedEvents(int newSupportedEvents); + + /** + * @brief addSupportOfEvent This method add support of a @a newSupportedEvent. + * @param newSupportedEvent This is new value of a supported event. + * @see IWorldItem::setSupportedEvents + * @see IWorldItem::addSupportOfEvent + * @see IWorldItem::dropSupportOfEvent + * @see IWorldItem::supportedEvents + */ + void addSupportOfEvent(int newSupportedEvent); + + /** + * @brief dropSupportOfEvent This method drop support of a @a depricatedEvent + * @param depricatedEvent This is event that will be dropped. + * @see IWorldItem::setSupportedEvents + * @see IWorldItem::addSupportOfEvent + * @see IWorldItem::dropSupportOfEvent + * @see IWorldItem::supportedEvents + */ + void dropSupportOfEvent(int depricatedEvent); + +private: + void initOnWorld(const IWorld* world); + + const IWorld* _world = nullptr; + + bool _fDecorative = true; + bool _fDistroy = false; + bool _fFirstRenderIteration = true; + int _supportedEvents; + + friend class IWorld; +}; +} +#endif // IWORLDITEM_H diff --git a/src/engine/src/public/ButterflyEngine/core/iworldlight.cpp b/src/engine/src/public/ButterflyEngine/core/iworldlight.cpp new file mode 100644 index 0000000..c2c6f04 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iworldlight.cpp @@ -0,0 +1,84 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iworldlight.h" +namespace CRAWL { + +IWorldLight::IWorldLight(const QString &name, + const QString &viewTempalte, + QObject *ptr): + ClasterItem(name, viewTempalte, ptr) { + +} + +int IWorldLight::lightForce() const { + return _lightForce; +} + +void IWorldLight::setLightForce(int newLightForce) { + if (_lightForce == newLightForce) + return; + _lightForce = newLightForce; + emit lightForceChanged(); +} + +bool IWorldLight::castsShadow() const { + return _castsShadow; +} + +void IWorldLight::setCastsShadow(bool newCastsShadow) { + if (_castsShadow == newCastsShadow) + return; + _castsShadow = newCastsShadow; + emit castsShadowChanged(); +} + +float IWorldLight::shadowFactor() const { + return _shadowFactor; +} + +void IWorldLight::setShadowFactor(float newShadowFactor) { + if (qFuzzyCompare(_shadowFactor, newShadowFactor)) + return; + _shadowFactor = newShadowFactor; + emit shadowFactorChanged(); +} + +float IWorldLight::shadowFilter() const { + return _shadowFilter; +} + +void IWorldLight::setShadowFilter(float newShadowFilter) { + if (qFuzzyCompare(_shadowFilter, newShadowFilter)) + return; + _shadowFilter = newShadowFilter; + emit shadowFilterChanged(); +} + +float IWorldLight::shadowMapFar() const { + return _shadowMapFar; +} + +void IWorldLight::setShadowMapFar(float newShadowMapFar) { + if (qFuzzyCompare(_shadowMapFar, newShadowMapFar)) + return; + _shadowMapFar = newShadowMapFar; + emit shadowMapFarChanged(); +} + +float IWorldLight::shadowBias() const { + return _shadowBias; +} + +void IWorldLight::setShadowBias(float newShadowBias) { + if (qFuzzyCompare(_shadowBias, newShadowBias)) + return; + _shadowBias = newShadowBias; + emit shadowBiasChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/iworldlight.h b/src/engine/src/public/ButterflyEngine/core/iworldlight.h new file mode 100644 index 0000000..0ca1568 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/iworldlight.h @@ -0,0 +1,177 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clasteritem.h" + +#ifndef IWORLDLIGHT_H +#define IWORLDLIGHT_H + +namespace CRAWL { + +/** + * @brief The IWorldLight class Is base interaface of the light object. + * Override this class for the create own light system for level. + * You need to create own qml file with light. + * + * @note If you wnat to create a new qml file the you need to inherit from the Light.qml file. + * + * ### Integration on the world. + * You need to add one object of this class in the IWorld::initWorldRules method. + * **Example:** + * + * ```cpp + * CRAWL::WorldRule *World::initWorldRules() { + + return new CRAWL::WorldRule { + {0, { + {registerObject(), 1}, + } + }, + {1000, { + {registerObject(), 1}, + } + }, + }; +} + * ``` + * + * For integration This object you world see the IWorld::initWorldRules method + */ +class CRAWL_EXPORT IWorldLight: public ClasterItem +{ + Q_OBJECT + Q_PROPERTY(int lightForce READ lightForce WRITE setLightForce NOTIFY lightForceChanged) + Q_PROPERTY(bool castsShadow READ castsShadow WRITE setCastsShadow NOTIFY castsShadowChanged) + Q_PROPERTY(float shadowFactor READ shadowFactor WRITE setShadowFactor NOTIFY shadowFactorChanged) + Q_PROPERTY(float shadowFilter READ shadowFilter WRITE setShadowFilter NOTIFY shadowFilterChanged) + Q_PROPERTY(float shadowMapFar READ shadowMapFar WRITE setShadowMapFar NOTIFY shadowMapFarChanged) + Q_PROPERTY(float shadowBias READ shadowBias WRITE setShadowBias NOTIFY shadowBiasChanged) + +public: + + IWorldLight(const QString& name, + const QString& viewTempalte = "qrc:/CrawlModule/Light.qml", + QObject *ptr = nullptr); + + /** + * @brief lightForce This method return light force + * @return light force value. + */ + int lightForce() const; + + /** + * @brief setLightForce This method sets new value for the light force. + * @param newLightForce this is new value of the light force. + */ + void setLightForce(int newLightForce); + + /** + * @brief castsShadow When this property is enabled, the light will cast shadows. The default value is false. + * @return current value of the castsShadow property. + */ + bool castsShadow() const; + + /** + * @brief setCastsShadow This method sets new value of the castsShadow property. for get more information see the castsShadow method. + * @param newCastsShadow this is new value of the castsShadow property. + */ + void setCastsShadow(bool newCastsShadow); + + /** + * @brief shadowFactor This property determines how dark the cast shadows should be. The value range is [0, 100], where 0 mean no shadows and 100 means the light is fully shadowed. The default value is 5. + * @return current value of the shadow factor + */ + float shadowFactor() const; + + /** + * @brief setShadowFactor This method return current value of the shadow factor. + * @param newShadowFactor This is new value of the shadow factor property. + * @note for get more information see the shadowFactor method. + */ + void setShadowFactor(float newShadowFactor); + + /** + * @brief shadowFilter This property sets how much blur is applied to the shadows. The default value is 5. + * @return current value of the shadow filter property. + */ + float shadowFilter() const; + + /** + * @brief setShadowFilter This method return current value of the shadow filter property. + * @param newShadowFilter This is new value of the shadow filter property. + * @note for get more information see the shadowFilter method. + */ + void setShadowFilter(float newShadowFilter); + + /** + * @brief shadowMapFar The property determines the maximum distance for the shadow map. Smaller values improve the precision and effects of the map. The default value is 5000. + * @return current value of the shadow map far property. + */ + float shadowMapFar() const; + + /** + * @brief setShadowMapFar This method return current value of the shadow map far property. + * @param newShadowMapFar This is new value of the shadow map far property. + * @note for get more information see the shadowMapFar method. + */ + void setShadowMapFar(float newShadowMapFar); + + /** + * @brief shadowBias This property is used to tweak the shadowing effect when when objects are casting shadows on themselves. The value range is [-1.0, 1.0]. Generally value inside [-0.1, 0.1] is sufficient. The default value is 0. + * @return current value of the shadow bias property. + */ + float shadowBias() const; + + /** + * @brief setShadowBias This method return current value of the shadow bias property. + * @param newShadowBias This is new value of the shadow bias property. + * @note for get more information see the shadowBias method. + */ + void setShadowBias(float newShadowBias); + +signals: + + /** + * @brief lightForceChanged This signal emits when light force has changed. + */ + void lightForceChanged(); + + /** + * @brief castsShadowChanged This signal emits when the castsShadow property has changed. + */ + void castsShadowChanged(); + + /** + * @brief shadowFactorChanged This signal emits when the shadowFactor property has changed. + */ + void shadowFactorChanged(); + + /** + * @brief shadowFilterChanged This signal emits when the shadowFilter property has changed. + */ + void shadowFilterChanged(); + + /** + * @brief shadowMapFarChanged This signal emits when the shadowMapFar property has changed. + */ + void shadowMapFarChanged(); + + /** + * @brief shadowBiasChanged This signal emits when the shadowBias property has changed. + */ + void shadowBiasChanged(); + +private: + int _lightForce = 100; + bool _castsShadow = false; + float _shadowFactor = 5; + float _shadowFilter = 5; + float _shadowMapFar = 5000; + float _shadowBias = 0; +}; +} +#endif // IWORLDLIGHT_H diff --git a/src/engine/src/public/ButterflyEngine/core/layout.cpp b/src/engine/src/public/ButterflyEngine/core/layout.cpp new file mode 100644 index 0000000..a08db99 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/layout.cpp @@ -0,0 +1,125 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "layout.h" +#include "clasteritem.h" +#include + +namespace CRAWL { + +Layout::Layout() { + +} + +void Layout::add(ClasterItem *object) { + + Claster::add(object); + updatePosition(); + +} + +void Layout::remove(ClasterItem *object) { + + Claster::remove(object); + updatePosition(); + +} + +void Layout::changeLayout(const LayoutType &fig) { + _shape = fig; + updatePosition(); +} + +void Layout::setDistance(int dist) { + _distance = dist; + updatePosition(); +} + +void Layout::updatePosition() { + + switch (_shape) { + case CIRCLE: + drawCircle(); + break; + + case SQUARE: + drawSquare(); + break; + + case LINE: + drawLine(); + break; + + default: + break; + } + +} + +void Layout::drawCircle() { + + if (objects().size() == 0) { + QuasarAppUtils::Params::log(QString("The number of objects is zero. Add object."), QuasarAppUtils::Error); + return; + } + + float step = 360 / objects().size(); + int temp = 0; + + for (ClasterItem* object: objects()) { + + float x = _distance * qCos(step*temp); + float y = _distance * qSin(step*temp); + GroupObject::updatePosition(object->guiId(), {x, y, 0}); + + temp++; + } + +} + +void Layout::drawSquare() { + + if (objects().size() == 0) { + QuasarAppUtils::Params::log(QString("The number of objects is zero. Add object."), QuasarAppUtils::Error); + return; + } + + int height = qFloor(qSqrt(objects().size())); + int width = qFloor(objects().size() / height); + + int indObject = 0; + for (auto idObj = objects().keyBegin(); idObj != objects().keyEnd(); idObj++) { + + float x = indObject % height; + float y = qCeil(indObject / height); + + GroupObject::updatePosition(*idObj, {(x * _distance) - (height * _distance / 2), + (y * _distance) - (width * _distance / 2), 0}); + indObject++; + + } + +} + +void Layout::drawLine() { + + if (objects().size() == 0) { + QuasarAppUtils::Params::log(QString("The number of objects is zero. Add object."), QuasarAppUtils::Error); + return; + } + + float xObject = 0; + float height = objects().size() * _distance; + for (auto idObj = objects().keyBegin(); idObj != objects().keyEnd(); idObj++) { + + GroupObject::updatePosition(*idObj, {(xObject * _distance) - (height/2 * _distance), 0, 0}); + + xObject++; + } +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/layout.h b/src/engine/src/public/ButterflyEngine/core/layout.h new file mode 100644 index 0000000..502bbfa --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/layout.h @@ -0,0 +1,127 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef LAYOUT_H +#define LAYOUT_H + +#include + + +namespace CRAWL { + +/** + * @brief The LayoutType enum Lists the shapes to convert the group object to. + */ +enum LayoutType { + /// The circle property calls the drawCircle method, which recalculates and updates + /// the coordinates of the passed object's positions. + CIRCLE, + + /// The square property calls the drawSquare method, which updates the coordinates of + /// the objects' positions, giving them the shape of a square. + SQUARE, + + /// The LINE property calls the drawLine method, which updates the coordinates of the + /// objects' positions, giving it a line shape. + LINE +}; + +/** + * @brief The Layout class The class that control position of group objects. + * ### Requried child classes: IWorldItem + * + * This class overloads the add() and remove() methods, which add objects to the cluster while updating positions according to the selected LayoutType. + * Has two public methods for setting the distance to the object and selecting the grouping of objects. + * + * ## Example of use + * + * ### For what this object uses + * This object is convenient to use if you want to create a cluster object directly, within which subobjects are grouped into a circle or square, depending on the selected property. + * For example : snake obstacle. + * + * ### Example of use + * + * 1. Create the GroupObjObstacle class. + * + * ```cpp + * + * class GroupObjObstacle: public CRAWL::Layout, public CRAWL::IWorldItem { + * + * // sets the distance to the object from the center. + * setDistance(20); + * + * // Set the property of grouping objects + * changeLayout(CRAWL::LayoutType::CIRCLE); + * + * for(int i(0); i < 20; i++) { + * add(new BoxItem); + * } + * + * }; + * ``` + * + * @note The added object must inherit from ClasterItem and have a child class required for overloading software renderers. + * + * All done. Now the added objects will be grouped into a circle shape. + * + * You can change the center-to-object distance and the shape of a group of objects using the setDistance and changeLayout methods. + * + * @note This class requried the GuiObject functions as a parent class. + * @note This class requires an overload of the render method; The implementation must call the render methods of the parent classes. + * + */ +class Layout: public GroupObject { +public: + Layout(); + +// Claster interface +public: + void add(ClasterItem *object); + void remove(ClasterItem *object); + + /** + * @brief changeLayout This method defines the shape of the group object. + * @param fig This is the name of the figure to change the group object. + */ + void changeLayout(const LayoutType &fig); + + /** + * @brief setDistance This method sets, depending on the shape selected, the radius for the circle or the indentation for the square. + * @param dist This is the radius or margin. + */ + void setDistance(int dist); + +private: + + + /** + * @brief updatePosition This method updates the coordinates of the positions of all objects. + */ + void updatePosition(); + + /** + * @brief drawCircle This method updates the coordinates to a circle shape. + */ + void drawCircle(); + + /** + * @brief drawSquare This method updates the coordinates to a square shape. + */ + void drawSquare(); + + /** + * @brief drawLine This method updates the coordinates to a line shape. + */ + void drawLine(); + + int _distance; + LayoutType _shape; + +}; + +} +#endif // LAYOUT_H diff --git a/src/engine/src/public/ButterflyEngine/core/moon.cpp b/src/engine/src/public/ButterflyEngine/core/moon.cpp new file mode 100644 index 0000000..298a185 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/moon.cpp @@ -0,0 +1,21 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# +#include "moon.h" + +namespace CRAWL { + +Moon::Moon(const QVector3D* center): + DayItem(center, AUTO_CLASS_NAME) { + setColor("#6177ff"); + +} + +void Moon::init() {} + +void Moon::onIntersects(const IWorldItem *) {} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/moon.h b/src/engine/src/public/ButterflyEngine/core/moon.h new file mode 100644 index 0000000..6764f83 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/moon.h @@ -0,0 +1,31 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef MOON_H +#define MOON_H + +#include "Crawl/dayitem.h" + + +namespace CRAWL { + +/** + * @brief The Moon class This is default implementation of the moon for the Dat class. + */ +class CRAWL_EXPORT Moon: public DayItem { + Q_OBJECT +public: + Moon(const QVector3D *center); + + void init(); + + // IWorldItem interface +protected: + void onIntersects(const IWorldItem *item); +}; +} +#endif // MOON_H diff --git a/src/engine/src/public/ButterflyEngine/core/particleeffect.cpp b/src/engine/src/public/ButterflyEngine/core/particleeffect.cpp new file mode 100644 index 0000000..e998e11 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/particleeffect.cpp @@ -0,0 +1,275 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "particleeffect.h" +#include "targetdirection.h" +#include "vectordirection.h" +namespace CRAWL { + + +ParticleEffect::ParticleEffect(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { + + setFDecorative(true); +} + +bool ParticleEffect::enabled() const { + return _enabled; +} + +void ParticleEffect::setEnabled(bool newEnabled) { + if (_enabled == newEnabled) + return; + _enabled = newEnabled; + emit enabledChanged(); +} + +float ParticleEffect::emitRate() const { + return _emitRate; +} + +void ParticleEffect::setEmitRate(float newEmitRate) { + if (qFuzzyCompare(_emitRate, newEmitRate)) + return; + _emitRate = newEmitRate; + emit emitRateChanged(); +} + +float ParticleEffect::depthBias() const { + return _depthBias; +} + +void ParticleEffect::setDepthBias(float newDepthBias) { + if (qFuzzyCompare(_depthBias, newDepthBias)) + return; + _depthBias = newDepthBias; + emit depthBiasChanged(); +} + +int ParticleEffect::lifeSpan() const { + return _lifeSpan; +} + +void ParticleEffect::setLifeSpan(int newLifeSpan) { + if (_lifeSpan == newLifeSpan) + return; + _lifeSpan = newLifeSpan; + emit lifeSpanChanged(); +} + +int ParticleEffect::lifeSpanVariation() const { + return _lifeSpanVariation; +} + +void ParticleEffect::setLifeSpanVariation(int newLifeSpanVariation) { + if (_lifeSpanVariation == newLifeSpanVariation) + return; + _lifeSpanVariation = newLifeSpanVariation; + emit lifeSpanVariationChanged(); +} + +float ParticleEffect::particleEndScale() const { + return _particleEndScale; +} + +void ParticleEffect::setParticleEndScale(float newParticleEndScale) { + if (qFuzzyCompare(_particleEndScale, newParticleEndScale)) + return; + _particleEndScale = newParticleEndScale; + emit particleEndScaleChanged(); +} + +const QVector3D &ParticleEffect::particleRotationVariation() const { + return _particleRotationVariation; +} + +void ParticleEffect::setParticleRotationVariation(const QVector3D &newParticleRotationVariation) { + if (_particleRotationVariation == newParticleRotationVariation) + return; + _particleRotationVariation = newParticleRotationVariation; + emit particleRotationVariationChanged(); +} + +const QVector3D &ParticleEffect::particleRotationVelocity() const { + return _particleRotationVelocity; +} + +void ParticleEffect::setParticleRotationVelocity(const QVector3D &newParticleRotationVelocity) { + if (_particleRotationVelocity == newParticleRotationVelocity) + return; + _particleRotationVelocity = newParticleRotationVelocity; + emit particleRotationVelocityChanged(); +} + +const QVector3D &ParticleEffect::particleRotationVelocityVariation() const { + return _particleRotationVelocityVariation; +} + +void ParticleEffect::setParticleRotationVelocityVariation(const QVector3D &newParticleRotationVelocityVariation) { + if (_particleRotationVelocityVariation == newParticleRotationVelocityVariation) + return; + _particleRotationVelocityVariation = newParticleRotationVelocityVariation; + emit particleRotationVelocityVariationChanged(); +} + +float ParticleEffect::particleScale() const { + return _particleScale; +} + +void ParticleEffect::setParticleScale(float newParticleScale) { + if (qFuzzyCompare(_particleScale, newParticleScale)) + return; + _particleScale = newParticleScale; + emit particleScaleChanged(); +} + +float ParticleEffect::particleScaleVariation() const { + return _particleScaleVariation; +} + +void ParticleEffect::setParticleScaleVariation(float newParticleScaleVariation) { + if (qFuzzyCompare(_particleScaleVariation, newParticleScaleVariation)) + return; + _particleScaleVariation = newParticleScaleVariation; + emit particleScaleVariationChanged(); +} + +const QString &ParticleEffect::particleDelegate() const { + return _particleDelegate; +} + +void ParticleEffect::setParticleDelegate(const QString &newParticleDelegate) { + if (_particleDelegate == newParticleDelegate) + return; + _particleDelegate = newParticleDelegate; + emit particleDelegateChanged(); +} + +QObject *ParticleEffect::velocity() const { + return _velocity; +} + +QVector3D ParticleEffect::brust(int count, + int duration, + const QVector3D &position) const { + QVector3D result = {0,0,0}; + + if (!viewObject()) { + QuasarAppUtils::Params::log("Failed to brust particles because the viewObject is empty."); + return result; + } + + QMetaObject::invokeMethod(viewObject(), + "brust", + Qt::DirectConnection, + Q_RETURN_ARG(QVector3D, result), + Q_ARG(int, count), + Q_ARG(int, duration), + Q_ARG(QVector3D, position)); + + return result; +} + +QVector3D ParticleEffect::brust(int count, int duration) const { + + QVector3D result = {0,0,0}; + + if (!viewObject()) { + QuasarAppUtils::Params::log("Failed to brust particles because the viewObject is empty."); + return result; + } + + QMetaObject::invokeMethod(viewObject(), + "brust", + Qt::DirectConnection, + Q_RETURN_ARG(QVector3D, result), + Q_ARG(int, count), + Q_ARG(int, duration)); + + return result; +} + +QVector3D ParticleEffect::brust(int count) const { + + QVector3D result = {0,0,0}; + + if (!viewObject()) { + QuasarAppUtils::Params::log("Failed to brust particles because the viewObject is empty."); + return result; + } + + QMetaObject::invokeMethod(viewObject(), + "brust", + Qt::DirectConnection, + Q_RETURN_ARG(QVector3D, result), + Q_ARG(int, count)); + + return result; +} + +void ParticleEffect::setVelocity(QObject *newVelocity) { + if (_velocity == newVelocity) + return; + _velocity = newVelocity; + emit velocityChanged(); +} + +const QVector3D &ParticleEffect::particleRotation() const { + return _particleRotation; +} + +void ParticleEffect::setParticleRotation(const QVector3D &newParticleRotation) { + if (_particleRotation == newParticleRotation) + return; + _particleRotation = newParticleRotation; + emit particleRotationChanged(); +} + +const QString &ParticleEffect::particleShape() const { + return _particleShape; +} + +void ParticleEffect::setParticleShape(const QString &newParticleShape) { + if (_particleShape == newParticleShape) + return; + _particleShape = newParticleShape; + emit particleShapeChanged(); +} + +void ParticleEffect::useDirectionVelosity( + const QVector3D& velosityDirection, + const QVector3D& velosityDirectionValatility) { + + if (_velocity) { + _velocity->deleteLater(); + } + + setVelocity(new VectorDirection(velosityDirection, velosityDirectionValatility)); +} + +void ParticleEffect::useTargetVelosity( + float velosityMagnitude, + float velosityMagnitudeVariation, + bool velosityNormalized, + const QVector3D& velosityTargetPosition, + const QVector3D& velosityTargetPositionVariation) { + + if (_velocity) { + _velocity->deleteLater(); + } + + setVelocity(new TargetDirection(velosityMagnitude, + velosityMagnitudeVariation, + velosityNormalized, + velosityTargetPosition, + velosityTargetPositionVariation)); +}; + +} diff --git a/src/engine/src/public/ButterflyEngine/core/particleeffect.h b/src/engine/src/public/ButterflyEngine/core/particleeffect.h new file mode 100644 index 0000000..23d8d42 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/particleeffect.h @@ -0,0 +1,570 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef PARTICLEEFFECT_H +#define PARTICLEEFFECT_H + +#include "iworlditem.h" + +namespace CRAWL { + + +/** + * @brief The ParticleEffect class This element emits logical particles into the ParticleSystem, with the given starting attributes. +At least one emitter is required to have particles in the ParticleSystem3D. + Please see the [qt](https://doc.qt.io/qt-6/qtquick3d-index.html) documentation for get more inforamtion + + @note if you want that this effect alway shows then set the enabled property to true or invoke the brust method for singel show. + + ### Example: + + @code{cpp} + + Fire::Fire(): ParticleEffect(AUTO_CLASS_NAME, "qrc:/CrawlModule/particles/Fire.qml") { + + useDirectionVelosity({0, 0 , 10}, {10, 10, 0}); + setParticleScale(4); + setParticleEndScale(12); + setParticleScaleVariation(3); + setLifeSpanVariation(500); + setColor("#ffaf2c"); + setSize({1, 1, 1}); + setposition({0,0,10}); + setEnabled(true); + + setParticleDelegate("qrc:/CrawlModule/particles/FireParticel.qml"); + + setFireStrength(100); + } + + @endcode + */ +class CRAWL_EXPORT ParticleEffect : public IWorldItem +{ + Q_OBJECT + /** + * @brief enabled if enabled is set to false, this emitter will not emit any particles. + * Usually this is used to conditionally turn an emitter on or off. If you want to continue emitting burst, + * keep emitRate at 0 instead of toggling this to false. The default value is false. + */ + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + + /** + * @brief emitRate This property defines the constant emitting rate in particles per second. For example, if the emitRate is 120 and system animates at 60 frames per second, 2 new particles are emitted at every frame. + * The default value is 0. + */ + Q_PROPERTY(float emitRate READ emitRate WRITE setEmitRate NOTIFY emitRateChanged) + + /** + * @brief depthBias Holds the depth bias of the emitter. Depth bias is added to the object distance from camera when sorting objects. This can be used to force rendering order between objects close to each other, that might otherwise be rendered in different order in different frames. Negative values cause the sorting value to move closer to the camera while positive values move it further from the camera. + */ + Q_PROPERTY(float depthBias READ depthBias WRITE setDepthBias NOTIFY depthBiasChanged) + + /** + * @brief lifeSpan This property defines the lifespan of a single particle in milliseconds. + * The default value is 1000. + * See also the lifeSpanVariation property. + */ + Q_PROPERTY(int lifeSpan READ lifeSpan WRITE setLifeSpan NOTIFY lifeSpanChanged) + + /** + * @brief lifeSpanVariation This property defines the lifespan variation of a single particle in milliseconds. + * For example, to emit particles which will exist between 3 and 4 seconds: + * @code + lifeSpan: 3500 + lifeSpanVariation: 500 + @endcode + * The default value is 0. + */ + Q_PROPERTY(int lifeSpanVariation READ lifeSpanVariation WRITE setLifeSpanVariation NOTIFY lifeSpanVariationChanged) + + /** + * @brief particleEndScale This property defines the scale multiplier of the particles at the end of particle lifeSpan. + * To have variation in the particle end sizes, use ParticleEffect::particleScaleVariation. + * When the value is negative, end scale is the same as the particleScale, + * so scale doesn't change during the particle lifeSpan. + * The default value is -1.0. + * See also ParticleEffect::particleScale and ParticleEffect::particleScaleVariation. + */ + Q_PROPERTY(float particleEndScale READ particleEndScale WRITE setParticleEndScale NOTIFY particleEndScaleChanged) + + /** + * @brief particleRotationVariation This property defines the rotation variation of the particles in the beginning. Rotation variation is defined as degrees in euler angles. + * For example, to emit particles in fully random rotations: Qt.vector3d(180, 180, 180) + * See also ParticleEffect::particleRotation. + */ + Q_PROPERTY(QVector3D particleRotationVariation READ particleRotationVariation WRITE setParticleRotationVariation NOTIFY particleRotationVariationChanged) + + /** + * @brief particleRotationVelocity This property defines the rotation velocity of the particles in the beginning. + * Rotation velocity is defined as degrees per second in euler angles. + * See also ParticleEffect::particleRotationVelocityVariation. + */ + Q_PROPERTY(QVector3D particleRotationVelocity READ particleRotationVelocity WRITE setParticleRotationVelocity NOTIFY particleRotationVelocityChanged) + + /** + * @brief particleRotationVelocityVariation This property defines the rotation velocity variation of the particles. + * Rotation velocity variation is defined as degrees per second in euler angles. + * For example, to emit particles in random rotations which have random rotation velocity between -100 and 100 + * degrees per second into any directions: + + @code + particleRotationVariation: Qt.vector3d(180, 180, 180) + particleRotationVelocityVariation: Qt.vector3d(100, 100, 100) + @endcode + * See also ParticleEffect::particleRotationVelocity. + */ + Q_PROPERTY(QVector3D particleRotationVelocityVariation READ particleRotationVelocityVariation WRITE setParticleRotationVelocityVariation NOTIFY particleRotationVelocityVariationChanged) + + /** + * @brief particleScale This property defines the scale multiplier of the particles at the beginning. + * To have variation in the particle sizes, use particleScaleVariation. + * The default value is 1.0. + * See also ParticleEffect::particleEndScale and ParticleEffect::particleScaleVariation. + */ + Q_PROPERTY(float particleScale READ particleScale WRITE setParticleScale NOTIFY particleScaleChanged) + + /** + * @brief particleScaleVariation This property defines the scale variation of the particles. + * This variation is used for both particleScale and particleEndScale. + * For example, to emit particles which start at scale 0.5 - 1.5 and end at 2.5 - 3.5: + * @code + particleScale: 1.0 + particleEndScale: 3.0 + particleScaleVariation: 0.5 + @endcode + * The default value is 0.0. + * See also ParticleEffect::particleScale and ParticleEffect::particleScaleVariation. + */ + Q_PROPERTY(float particleScaleVariation READ particleScaleVariation WRITE setParticleScaleVariation NOTIFY particleScaleVariationChanged) + + /** + * @brief velocity can be used to set a starting velocity for emitted particles. If velocity is not set, particles start motionless and velocity comes from affectors if they are used. + * @note For the initialisation of this property use ParticleEffect::useTargetVelosity and ParticleEffect::useDirectionVelosity methods + */ + Q_PROPERTY(QObject *velocity READ velocity NOTIFY velocityChanged) + + /** + * @brief particleDelegate This is path yo the qml delegate file of the particle object. + * @return path to delegate of the particle object. + */ + Q_PROPERTY(QString particleDelegate READ particleDelegate WRITE setParticleDelegate NOTIFY particleDelegateChanged) + + /** + * @brief particleShape This property defines optional shape for the emitting area. + * Shape is scaled, positioned and rotated based on the emitter node properties. + * When the Shape fill property is set to false, + * emitting happens only from the surface of the shape. When the shape is not defined, emitting is done from the center point of the emitter node. + */ + Q_PROPERTY(QString particleShape READ particleShape WRITE setParticleShape NOTIFY particleShapeChanged) + + /** + * @brief particleRotation This property defines the rotation of the particles in the beginning. Rotation is defined as degrees in euler angles. + */ + Q_PROPERTY(QVector3D particleRotation READ particleRotation WRITE setParticleRotation NOTIFY particleRotationChanged) + +public: + ParticleEffect(const QString& name, + const QString& viewTempalte = "qrc:/CrawlModule/particles/ParticleEffect.qml", + QObject *ptr = nullptr); + + /** + * @brief enabled if enabled is set to false, this emitter will not emit any particles. + * Usually this is used to conditionally turn an emitter on or off. If you want to continue emitting burst, + * keep emitRate at 0 instead of toggling this to false. The default value is true. + * @return true if this effect is enabled. + */ + bool enabled() const; + + /** + * @brief setEnabled This method sets new value of the ParticleEffect::enabled property. + * @param newEnabled This is a new value of the ParticleEffect::enabled property + */ + void setEnabled(bool newEnabled); + + /** + * @brief emitRate This property defines the constant emitting rate in particles per second. For example, if the emitRate is 120 and system animates at 60 frames per second, 2 new particles are emitted at every frame. + * The default value is 0. + * @return current value of the emitRate property + */ + float emitRate() const; + + /** + * @brief setEmitRate This method sets new value of the ParticleEffect::emitRate property. + * @param newEmitRate This is a new value of the ParticleEffect::emitRate property + */ + void setEmitRate(float newEmitRate); + + /** + * @brief depthBias Holds the depth bias of the emitter. Depth bias is added to the object distance from camera when sorting objects. This can be used to force rendering order between objects close to each other, that might otherwise be rendered in different order in different frames. Negative values cause the sorting value to move closer to the camera while positive values move it further from the camera. + * @return current value of the depthBias property + */ + float depthBias() const; + + /** + * @brief setDepthBias This method sets new value of the ParticleEffect::depthBias property. + * @param newDepthBias This is a new value of the ParticleEffect::depthBias property + */ + void setDepthBias(float newDepthBias); + + /** + * @brief lifeSpan This property defines the lifespan of a single particle in milliseconds. + * The default value is 1000. + * See also the lifeSpanVariation property. + * @return current value of the lifeSpan property + */ + int lifeSpan() const; + + /** + * @brief setLifeSpan This method sets new value of the ParticleEffect::lifeSpan property. + * @param newLifeSpan This is a new value of the ParticleEffect::lifeSpan property + */ + void setLifeSpan(int newLifeSpan); + + /** + * @brief lifeSpanVariation This property defines the lifespan variation of a single particle in milliseconds. + * For example, to emit particles which will exist between 3 and 4 seconds: + * @code + lifeSpan: 3500 + lifeSpanVariation: 500 + @endcode + * The default value is 0. + * @return current value of the lifeSpanVariation property + */ + int lifeSpanVariation() const; + + /** + * @brief setLifeSpanVariation This method sets new value of the ParticleEffect::lifeSpanVariation property. + * @param newLifeSpanVariation This is a new value of the ParticleEffect::lifeSpanVariation property + */ + void setLifeSpanVariation(int newLifeSpanVariation); + + /** + * @brief particleEndScale This property defines the scale multiplier of the particles at the end of particle lifeSpan. + * To have variation in the particle end sizes, use ParticleEffect::particleScaleVariation. + * When the value is negative, end scale is the same as the particleScale, + * so scale doesn't change during the particle lifeSpan. + * The default value is -1.0. + * See also ParticleEffect::particleScale and ParticleEffect::particleScaleVariation. + * @return current value of the particleEndScale property + */ + float particleEndScale() const; + + /** + * @brief setParticleEndScale This method sets new value of the ParticleEffect::particleEndScale property. + * @param newParticleEndScale This is a new value of the ParticleEffect::particleEndScale property + */ + void setParticleEndScale(float newParticleEndScale); + + /** + * @brief particleRotationVariation This property defines the rotation variation of the particles in the beginning. Rotation variation is defined as degrees in euler angles. + * For example, to emit particles in fully random rotations: Qt.vector3d(180, 180, 180) + * See also ParticleEffect::particleRotation. + * @return current value of the particleRotationVariation property + */ + const QVector3D &particleRotationVariation() const; + + /** + * @brief setParticleRotationVariation This method sets new value of the ParticleEffect::particleRotationVariation property. + * @param newParticleRotationVariation This is a new value of the ParticleEffect::particleRotationVariation property + */ + void setParticleRotationVariation(const QVector3D &newParticleRotationVariation); + + /** + * @brief particleRotationVelocity This property defines the rotation velocity of the particles in the beginning. + * Rotation velocity is defined as degrees per second in euler angles. + * See also ParticleEffect::particleRotationVelocityVariation. + * @return current value of the particleRotationVelocity property + */ + const QVector3D &particleRotationVelocity() const; + + /** + * @brief setParticleRotationVelocity This method sets new value of the ParticleEffect::particleRotationVelocity property. + * @param newParticleRotationVelocity This is a new value of the ParticleEffect::particleRotationVelocity property + */ + void setParticleRotationVelocity(const QVector3D &newParticleRotationVelocity); + + /** + * @brief particleRotationVelocityVariation This property defines the rotation velocity variation of the particles. + * Rotation velocity variation is defined as degrees per second in euler angles. + * For example, to emit particles in random rotations which have random rotation velocity between -100 and 100 + * degrees per second into any directions: + + @code + particleRotationVariation: Qt.vector3d(180, 180, 180) + particleRotationVelocityVariation: Qt.vector3d(100, 100, 100) + @endcode + * See also ParticleEffect::particleRotationVelocity. + * @return current value of the particleRotationVelocityVariation property + */ + const QVector3D &particleRotationVelocityVariation() const; + + /** + * @brief setParticleRotationVelocityVariation This method sets new value of the ParticleEffect::particleRotationVelocityVariation property. + * @param newParticleRotationVelocityVariation This is a new value of the ParticleEffect::particleRotationVelocityVariation property + */ + void setParticleRotationVelocityVariation(const QVector3D &newParticleRotationVelocityVariation); + + /** + * @brief particleScale This property defines the scale multiplier of the particles at the beginning. + * To have variation in the particle sizes, use particleScaleVariation. + * The default value is 1.0. + * See also ParticleEffect::particleEndScale and ParticleEffect::particleScaleVariation. + * @return current value of the particleScale property + */ + float particleScale() const; + + /** + * @brief setParticleScale This method sets new value of the ParticleEffect::particleScale property. + * @param newParticleScale This is a new value of the ParticleEffect::particleScale property + */ + void setParticleScale(float newParticleScale); + + /** + * @brief particleScaleVariation This property defines the scale variation of the particles. + * This variation is used for both particleScale and particleEndScale. + * For example, to emit particles which start at scale 0.5 - 1.5 and end at 2.5 - 3.5: + * @code + particleScale: 1.0 + particleEndScale: 3.0 + particleScaleVariation: 0.5 + @endcode + * The default value is 0.0. + * See also ParticleEffect::particleScale and ParticleEffect::particleScaleVariation. + * @return current value of the ParticleEffect::particleScaleVariation property + */ + float particleScaleVariation() const; + + /** + * @brief setParticleScaleVariation This method sets new value of the ParticleEffect::particleScaleVariation property. + * @param newParticleScaleVariation This is a new value of the ParticleEffect::particleScaleVariation property + */ + void setParticleScaleVariation(float newParticleScaleVariation); + + /** + * @brief particleDelegate This is path yo the qml delegate file of the particle object. + * @return path to delegate of the particle object. + */ + const QString &particleDelegate() const; + + /** + * @brief setParticleDelegate This method sets new value of the path to qml particle object. + * @param newParticleDelegate This is new value of the path to particle object. + */ + void setParticleDelegate(const QString &newParticleDelegate); + + /** + * @brief velocity This property can be used to set a starting velocity for emitted particles. If velocity is not set, particles start motionless and velocity comes from affectors if they are used. + * @return current value of the ParticleEffect::velocity property + */ + QObject *velocity() const; + + /** + * @brief brust This method emits count amount of particles from this emitter during the next duration milliseconds. + * The particles are emitted as if the emitter was at position but all other properties are the same. + * @param count This is count of emited particles + * @param duration This ducration of the emitting particles. + * @param position This is position wher the emiter should emit particles. + * @return + */ + QVector3D brust(int count, + int duration, + const QVector3D& position) const; + + /** + * @brief brust This method emits count amount of particles from this emitter during the next duration milliseconds. + * @param count This is count of emited particles + * @param duration This ducration of the emitting particles. + * @return + */ + QVector3D brust(int count, + int duration) const; + + /** + * @brief brust This method emits count amount of particles from this emitter immediately. + * @param count This is count of emited particles + * @return + */ + QVector3D brust(int count) const; + + /** + * @brief particleShape The ParticleShape3D element supports shapes like Cube, + * Sphere and Cylinder for particles needs. + * For example, emitter can use shape property to emit particles from the shape area. + * Shapes don't have position, scale or rotation. + * Instead, they use parent node for these properties. + * @return path to qml shape element. + */ + const QString &particleShape() const; + + /** + * @brief setParticleShape This method set new path to shape element + * @param newParticleShape This is new value of the path to qml shape element. + */ + void setParticleShape(const QString &newParticleShape); + + /** + * @brief particleRotation This property defines the rotation of the particles in the beginning. Rotation is defined as degrees in euler angles. + * @return current value of the particleRotation property + */ + const QVector3D &particleRotation() const; + + /** + * @brief setParticleRotationVelocity This method sets new value of the ParticleEffect::particleRotation property. + * @param newParticleRotationVelocity This is a new value of the ParticleEffect::particleRotation property + */ + void setParticleRotation(const QVector3D &newParticleRotation); + +signals: + + /** + * @brief enabledChanged This signal emited when the enabled property changed. + */ + void enabledChanged(); + + /** + * @brief emitRateChanged This signal emited when the emitRate property changed. + */ + void emitRateChanged(); + + /** + * @brief depthBiasChanged This signal emited when the depthBias property changed. + */ + void depthBiasChanged(); + + /** + * @brief lifeSpanChanged This signal emited when the lifeSpan property changed. + */ + void lifeSpanChanged(); + + /** + * @brief lifeSpanVariationChanged This signal emited when the ifeSpanVariation property changed. + */ + void lifeSpanVariationChanged(); + + /** + * @brief particleEndScaleChanged This signal emited when the particleEndScale property changed. + */ + void particleEndScaleChanged(); + + /** + * @brief particleRotationVariationChanged This signal emited when the particleRotationVariation property changed. + */ + void particleRotationVariationChanged(); + + /** + * @brief particleRotationVelocityChanged This signal emited when the particleRotationVelocity property changed. + */ + void particleRotationVelocityChanged(); + + /** + * @brief particleRotationVelocityVariationChanged This signal emited when the particleRotationVelocityVariation property changed. + */ + void particleRotationVelocityVariationChanged(); + + /** + * @brief particleScaleChanged This signal emited when the particleScale property changed. + */ + void particleScaleChanged(); + + /** + * @brief particleScaleVariationChanged This signal emited when the particleScaleVariation property changed. + */ + void particleScaleVariationChanged(); + + /** + * @brief particleDelegateChanged This signal emited when the particleDelegate property changed. + */ + void particleDelegateChanged(); + + /** + * @brief velocityChanged This signal emited when the velocity property changed. + */ + void velocityChanged(); + + /** + * @brief particleShapeChanged This signal emited when the shape property changed. + */ + void particleShapeChanged(); + + /** + * @brief particleShapeChanged This signal emited when the particleRotation property changed. + */ + void particleRotationChanged(); + +protected: + + /** + * @brief useDirectionVelosity This method can be invoked a starting velocity for emitted particles. If velocity is not set, particles start motionless and velocity comes from affectors if they are used. + * This element sets emitted particle velocity towards the target direction vector. + * The length of the direction vector is used as the velocity magnitude. + * For example, to emit particles towards some random direction within x: 50..150, y: -20..20, z: 0: + * @code + * velositydirection: Qt.vector3d(100, 0, 0) + velositydirectionVariation: Qt.vector3d(50, 20, 0) + * @endcode + * @param velosityDirection see the ParticleEffect::velosityDirection property + * @param velosityDirectionValatility see the ParticleEffect::velosityDirectionValatility property + * @note This and useTargetVelosity method is not compatible. If you invoke them together then will works correctly will be only last invoked method. + */ + void useDirectionVelosity(const QVector3D& velosityDirection, + const QVector3D& velosityDirectionValatility = {}); + + /** + * @brief useTargetVelosity This method can be invoked a starting velocity for emitted particles. If velocity is not set, particles start motionless and velocity comes from affectors if they are used. + * This element sets emitted particle velocity towards the target position. + * For example, to emit particles towards position (100, 0, 0) with random magnitude between 10..20: + * @code + velosityposition: Qt.vector3d(100, 0, 0) + velositynormalized: true + velositymagnitude: 15.0 + velositymagnitudeVariation: 5.0 + + * @endcode + + + * @param velosityMagnitude see the ParticleEffect::velosityMagnitude property + * @param velosityMagnitudeVariation see the ParticleEffect::velosityMagnitudeVariation property + * @param velosityNormalized see the ParticleEffect::velosityNormalized property + * @param velosityTargetPosition see the ParticleEffect::velosityTargetPosition property + * @param velosityTargetPositionVariation see the ParticleEffect::velosityTargetPositionVariation property + * @note This and useDirectionVelosity method is not compatible. If you invoke them together then will works correctly will be only last invoked method. + */ + void useTargetVelosity(float velosityMagnitude, + float velosityMagnitudeVariation, + bool velosityNormalized, + const QVector3D& velosityTargetPosition, + const QVector3D& velosityTargetPositionVariation); + + /** + * @brief setVelocity This method sets new value of ParticleEffect::velocity property. + * @param newVelocity This is new value of the ParticleEffect::velocity property. + */ + void setVelocity(QObject *newVelocity); + +private: + bool _enabled = false; + float _emitRate = 0; + float _depthBias = 0; + int _lifeSpan = 1000; + int _lifeSpanVariation = 0; + float _particleEndScale = -1.0; + QVector3D _particleRotation = {}; + QVector3D _particleRotationVariation = {}; + QVector3D _particleRotationVelocity = {}; + QVector3D _particleRotationVelocityVariation = {}; + float _particleScale = 1; + float _particleScaleVariation = 0; + + QObject* _velocity = nullptr; + + QString _particleDelegate; + QString _particleShape; +}; +} +#endif // PARTICLEEFFECT_H diff --git a/src/engine/src/public/ButterflyEngine/core/playableobject.cpp b/src/engine/src/public/ButterflyEngine/core/playableobject.cpp new file mode 100644 index 0000000..a9f187e --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/playableobject.cpp @@ -0,0 +1,45 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "defaultcontrol.h" +#include "playableobject.h" + +namespace CRAWL { + + +PlayableObject::PlayableObject(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { + + setFDecorative(false); +} + +void PlayableObject::render(unsigned int tbfMsec) { + MovableObject::render(tbfMsec); +} + +const IControl *PlayableObject::currentControl() const { + return _currentControl; +} + +void PlayableObject::setControl(const IControl *control) { + + + if (auto oldControl = dynamic_cast(_currentControl)) { + disconnect(oldControl, &DefaultControl::userTap, this, &PlayableObject::onTap); + } + + auto defaultControl = dynamic_cast(control); + _currentControl = defaultControl; + + if (_currentControl) { + connect(defaultControl, &DefaultControl::userTap, this, &PlayableObject::onTap); + } +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/playableobject.h b/src/engine/src/public/ButterflyEngine/core/playableobject.h new file mode 100644 index 0000000..e6a39f6 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/playableobject.h @@ -0,0 +1,84 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef PLAYABLEOBJECT_H +#define PLAYABLEOBJECT_H + +#include "global.h" +#include "iworlditem.h" +#include "Extensions/movableobject.h" + +namespace CRAWL { + + +class IControl; + +/** + * @brief The PlayableObject class support works withe the IControl child classes. + * **How to is works**? You need to override the PlayableObject::setControl method for adding your own cpntroll classes. By Default This class use The DefaultControl class. + */ +class CRAWL_EXPORT PlayableObject: public IWorldItem, public MovableObject { + Q_OBJECT +public: + PlayableObject(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + /** + * @brief setControl This method should be connect player object with control object. + * @param control This is control object. + * @note This method can invoked two or more times, for example connect with AI control object and player control object. So your implementation should be contains disconnect methods. + * + * ### Example of use + * + * @code{cpp} + void MyPlayableObject::setControl(const IControl *control) { + + + if (auto oldControl = dynamic_cast(_currentControl)) { + disconnect(oldControl, &DefaultControl::userTap, this, &PlayableObject::onTap); + // some disconnect methodots + } + + auto defaultControl = dynamic_cast(control); + _currentControl = defaultControl; + + if (_currentControl) { + connect(defaultControl, &DefaultControl::userTap, this, &PlayableObject::onTap); + // some connect methodots + + } + } + * @endcode + */ + virtual void setControl(const IControl* control); + + /** + * @brief currentControl This method return pointer to current control + * @return + */ + const IControl *currentControl() const; + +protected: + void render(unsigned int tbfMsec) override; + +protected slots: + /** + * @brief onTap This method invoked when user tap on screen. + * @note method connected in the IPlayer::setControl function. So if you overrid the IPlayer::setControl method then please invoke method of a parent class. + */ + virtual void onTap() = 0; + + +private: + const IControl * _currentControl = nullptr; + +}; + +} + +#endif // PLAYABLEOBJECT_H diff --git a/src/engine/src/public/ButterflyEngine/core/player.cpp b/src/engine/src/public/ButterflyEngine/core/player.cpp new file mode 100644 index 0000000..0bb6bdf --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/player.cpp @@ -0,0 +1,34 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "player.h" +#include + +namespace CRAWL { + +Player::Player() { + +} + +void Player::addXp(int newXp) { + if (_userData) + _userData->setXp(_userData->getXp() + newXp); +} + +void Player::addMoney(int money) { + if (_userData) + _userData->setMoney(_userData->getMoney() + money); +} + +User *Player::userData() const { + return _userData; +} + +void Player::setUserData(User *newUserData) { + _userData = newUserData; +} +} diff --git a/src/engine/src/public/ButterflyEngine/core/player.h b/src/engine/src/public/ButterflyEngine/core/player.h new file mode 100644 index 0000000..5808846 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/player.h @@ -0,0 +1,57 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef PLAYER_H +#define PLAYER_H + +#include "icontrol.h" + + +namespace CRAWL { + +class User; + +/** + * @brief The Player class is main class of users. + */ +class CRAWL_EXPORT Player: public IControl +{ + Q_OBJECT +public: + Player(); + + /** + * @brief addXp This method add new xp to palyer. + * @param newXp this is value of experience + */ + void addXp(int newXp); + + /** + * @brief addMoney This method add money to user. + * @param money added amount of money + */ + void addMoney(int money); + + /** + * @brief userData This method sets user that control this object. + * @return current control user. + */ + User *userData() const; + + /** + * @brief setUserData This method sets user that control this object. + * @param newUserData This is new pointer of the new user. + */ + void setUserData(User *newUserData); + +private: + + User *_userData = nullptr; +}; +} +#endif // PLAYER_H diff --git a/src/engine/src/public/ButterflyEngine/core/previewcontrol.cpp b/src/engine/src/public/ButterflyEngine/core/previewcontrol.cpp new file mode 100644 index 0000000..3d89dbe --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/previewcontrol.cpp @@ -0,0 +1,21 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "previewcontrol.h" + +namespace CRAWL { + +PreviewControl::PreviewControl() { + +} + +QString PreviewControl::initQmlView() const { + return "qrc:/CrawlModule/PreviewControl.qml"; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/previewcontrol.h b/src/engine/src/public/ButterflyEngine/core/previewcontrol.h new file mode 100644 index 0000000..cc18584 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/previewcontrol.h @@ -0,0 +1,48 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef PREVIEWCONTROL_H +#define PREVIEWCONTROL_H + +#include "icontrol.h" + +namespace CRAWL { + +/** + * @brief The PreviewControl class This is base class of the preview popup control. + */ +class CRAWL_EXPORT PreviewControl: public IControl +{ + Q_OBJECT +public: + PreviewControl(); + QString initQmlView() const override; + +signals: + + /** + * @brief start emited when user click start button from the preview menu. + */ + void start(); + + /** + * @brief mousePositionChanged This signal emited when user true change the preview postion + * @param x delta by x axis + * @param y delta by y axis + */ + void mousePositionChanged(double x, double y); + + /** + * @brief select This signal emited when user select new item on hew own inventary. + * @param id This is id of the selected item + * @param isSelected this is bool option for set selected or diselected. + */ + void select(int id, bool isSelected); + +}; +} +#endif // PREVIEWCONTROL_H diff --git a/src/engine/src/public/ButterflyEngine/core/singleclasterworlditem.cpp b/src/engine/src/public/ButterflyEngine/core/singleclasterworlditem.cpp new file mode 100644 index 0000000..6e2f22f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/singleclasterworlditem.cpp @@ -0,0 +1,41 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "Extensions/claster.h" +#include "singleclasterworlditem.h" +#include "quasarapp.h" + +namespace CRAWL { + + +SingleClasterWorldItem::SingleClasterWorldItem(const QString &name, + const QString &viewTempalte, + QObject *ptr): + ClasterItem(name, viewTempalte, ptr) { + +} + +void SingleClasterWorldItem::setClaster(Claster *claster) { + if (parentClasters().size() > 0) { + Claster* parent = *parentClasters().begin(); + parent->remove(this); + removeClaster(parent); + } + + ClasterItem::setClaster(claster); +} + +Claster *SingleClasterWorldItem::parentClaster() const { + if (parentClastersCount() <= 0 ) { + return nullptr; + } + + return *ClasterItem::parentClasters().begin(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/singleclasterworlditem.h b/src/engine/src/public/ButterflyEngine/core/singleclasterworlditem.h new file mode 100644 index 0000000..1a05d72 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/singleclasterworlditem.h @@ -0,0 +1,48 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef SINGLECLASTERWORLDITEM_H +#define SINGLECLASTERWORLDITEM_H + +#include "clasteritem.h" + +namespace CRAWL { + +class Claster; + +/** + * @brief The SingleClasterWorldItem class This is wraper of the OWorldOitem for the controll parent clasters. + * This object can belong to only one cluster in one time + */ +class CRAWL_EXPORT SingleClasterWorldItem: public ClasterItem +{ + Q_OBJECT +public: + SingleClasterWorldItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); +protected: + + /** + * @brief setClaster invoked when object added to new claster. + * @param claster pointer to invoker claster object. + * @note This implementation can be sets only one object as a parent. + */ + void setClaster(Claster *claster) override; + + /** + * @brief parentClaster This method is wraper of the ClasterItem::parentClasters method. + * @return pointer to the parent claster object. + */ + Claster* parentClaster() const; + + friend class Claster; +}; +} + +#endif // SINGLECLASTERWORLDITEM_H diff --git a/src/engine/src/public/ButterflyEngine/core/snake.cpp b/src/engine/src/public/ButterflyEngine/core/snake.cpp new file mode 100644 index 0000000..d50538d --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/snake.cpp @@ -0,0 +1,200 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "snake.h" +#include "snakeitem.h" +#include +#include +#include +#include "iworld.h" + +namespace CRAWL { + + +Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr): + PlayableObject (name, viewTempalte, ptr) { + + _vectors = new QVector3D[2]; + setAngularVelocity(100); + + setLengthBetwinItems(1); + setSpeed(100); + + _clickIndex = 0; + + setScales({{0, 0.8}, + {0.4, 1.2}, + {1, 0.5}}); + + setLengthBetwinItemsMap({{0, 0.8}, + {0.4, 1.2}, + {1, 0.5}}); + + addSupportOfEvent(Events::Intersects); +} + +Snake::~Snake( ){ + delete [] _vectors; +} + +QString Snake::itemTextType() const { + return Snake::typeText(); +} + +QString Snake::typeText() { + return "PlayableObject"; +} + +unsigned int Snake::type() { + return qHash(typeText()); +} + +void Snake::render(unsigned int tbfMsec) { + PlayableObject::render(tbfMsec); +} + +void Snake::add(ClasterItem *object) { + if (auto snakeItem = dynamic_cast(object)) { + + if (_lastSnakeItem) { + snakeItem->setPrev(_lastSnakeItem); + } else { + snakeItem->setPrev(this); + } + + snakeItem->setBreakingForce(breakingForce()); + + _lastSnakeItem = static_cast(snakeItem); + + Claster::add(object); + return ; + } + + QuasarAppUtils::Params::log("Failed to add item to Snake." + " You need to use the SnakeItem child class as a argument", + QuasarAppUtils::Error); +} + +void Snake::remove(ClasterItem *object) { + + if (_lastSnakeItem == object) { + _lastSnakeItem = static_cast(_lastSnakeItem)->prev(); + } + + return Claster::remove(object); +} + +void Snake::remove(int id) { + if (_lastSnakeItem->guiId() == id) { + _lastSnakeItem = static_cast(_lastSnakeItem)->prev(); + } + + return Claster::remove(id); +} + +void Snake::init() { + generateItems(); +} + +void Snake::onTap() { + setMovableVector(_vectors[_clickIndex++ % 2]); +} + +float CRAWL::Snake::getValueFromMap(const QMap &map, + float position, + float defaultValue) { + auto it = map.cbegin(); + + float from = 0, fromKey = 0; + float to = it.value(), toKey = it.key(); + + if (it != _scales.cend()) { + while (position >= it.key() && it != _scales.cend()) { + it++; + + if (it != _scales.cend()) { + from = to; + to = it.value(); + fromKey = toKey; + toKey = it.key(); + } + } + + float localPosition = (position - fromKey) / (fromKey - toKey); + float valueDiff = from - to; + + return from + localPosition * valueDiff; + } + + return defaultValue; +} + +void Snake::generateItems() { + + for(unsigned int i = 0; i < itemsCount(); ++i) { + + SnakeItem* item = dynamic_cast(factory()); + + if (!item) { + QuasarAppUtils::Params::log("The snake item class should be child class" + " of the SnakeItem class.", + QuasarAppUtils::Error); + return; + } + + float scale = getValueFromMap(_scales, + static_cast(i) / itemsCount()); + float lengthBIt = getValueFromMap(_lengthBetwinItemsMap, + static_cast(i) / itemsCount()); + + item->setSize(item->size() * scale); + item->setLengthBetwinItems(lengthBIt); + + add(item); + } +} + +const QMap &Snake::lengthBetwinItemsMap() const { + return _lengthBetwinItemsMap; +} + +void Snake::setLengthBetwinItemsMap(const QMap &newLengthBetwinItemsMap) { + _lengthBetwinItemsMap = newLengthBetwinItemsMap; +} + +float Snake::speed() const { + return _speed; +} + +void Snake::setSpeed(float newSpeed) { + _speed = newSpeed; + float asixPos = std::sqrt(std::pow(_speed, 2.0) / 2); + _vectors[0] = QVector3D(asixPos, asixPos,0); // left tap + _vectors[1] = QVector3D(asixPos,-asixPos,0); // right tap +} + +unsigned int Snake::itemsCount() const { + return 50; +} + +const QMap &Snake::scales() const { + return _scales; +} + +void Snake::setScales(const QMap &newScales) { + _scales = newScales; +} + +float Snake::lengthBetwinItems() const{ + return _lengthBetwinItems; +} + +void Snake::setLengthBetwinItems(float newLengthBetwinItems) { + _lengthBetwinItems = newLengthBetwinItems; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/snake.h b/src/engine/src/public/ButterflyEngine/core/snake.h new file mode 100644 index 0000000..6afa0de --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/snake.h @@ -0,0 +1,156 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CRAWL_SNAKE_H +#define CRAWL_SNAKE_H + +#include "iitem.h" +#include "playableobject.h" +#include "Extensions/autogenerateclaster.h" + +namespace CRAWL { + +class SnakeItem; + +/** + * @brief The Snake class This class implement render mehod for snake object. + */ +class CRAWL_EXPORT Snake : public PlayableObject, public AutoGenerateClaster, public IItem +{ + Q_OBJECT +public: + Snake(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + ~Snake() override; + + QString itemTextType() const override; + + /** + * @brief type This method return const string value of the all world types. + * @return const string value of the all world types. + * @see IItem::itemTextType + * @see IItem::type + */ + static QString typeText(); + + /** + * @brief type This is wrapper of the IWorld::typeText method that invoke the qHash function for results string. + * @return integer type object id. + */ + static unsigned int type(); + + void render(unsigned int tbfMsec) override; + + void add(ClasterItem *object) override; + void remove(ClasterItem *object) override; + void remove(int id) override; + void init() override; + + // IPlayer interface + /** + * @brief lengthBetwinItems This method return length betwin snake items; + * @return length betwin snake items + */ + float lengthBetwinItems() const; + + /** + * @brief setLengthBetwinItems This method sets length betwin snake items. + * @param newLengthBetwinItems This is new value of the length betwin snake items. + */ + void setLengthBetwinItems(float newLengthBetwinItems); + + /** + * @brief scales This method return the map of the snake body scales. + * The key of map are position of snake Body and the value are scale factor of current body item. + * The default scales map of snake are: + * ``` + * 0.0 - 0.8 + * 0.6 - 1.2 + * 1 - 0.5 + * ``` + * @return scales map of snake body. + */ + const QMap &scales() const; + + /** + * @brief setScales This method sets new scales map for snake body. + * @param newScales This is new value of the scales map. + */ + void setScales(const QMap &newScales); + + /** + * @brief speed This method return current speed snake speed. + * @return snake speed + */ + float speed() const; + + /** + * @brief setSpeed This method sets new current speed of the snake. + * @param newSpeed new value of the snake speed. + */ + void setSpeed(float newSpeed); + + unsigned int itemsCount() const override; + + /** + * @brief lengthBetwinItemsMap This method return map with lengths betwin items. + * The key of map are position of snake Body and the value are length betwin this current and parent items. + * The default map of snake are: + * ``` + * 0.0 - 0.8 + * 0.6 - 1.2 + * 1 - 0.5 + * ``` + * @return length betwin items map of snake body. + */ + const QMap &lengthBetwinItemsMap() const; + + /** + * @brief setLengthBetwinItemsMap This method sets new valud of the length betwin items map. + * @param newLengthBetwinItemsMap this is new value of the length betwin tems map. + * @note for get more information see the lengthBetwinItemsMap method. + */ + void setLengthBetwinItemsMap(const QMap &newLengthBetwinItemsMap); + + /** + * @brief getValueFromMap This method return near value from the map by position. + * @param map This is map that contains list of the values. + * @param position This requried position from map. + * @param defaultValue This value will be returned when map are empty. + * @return near value of the requried position. + * + * @note This function works as a gradient. + */ + float getValueFromMap(const QMap &map, + float position, + float defaultValue = 1); + +protected slots: + void onTap() override; + + +private: + void generateItems() override; + + + QMap _scales; + QMap _lengthBetwinItemsMap; + + float _lengthBetwinItems; + const IWorldItem* _lastSnakeItem = nullptr; + unsigned int _clickIndex; + QVector3D* _vectors; + float _speed; + + int _hp = 100; + +}; + +} + +#endif // CRAWL_SNAKE_H diff --git a/src/engine/src/public/ButterflyEngine/core/snakeitem.cpp b/src/engine/src/public/ButterflyEngine/core/snakeitem.cpp new file mode 100644 index 0000000..1be6f53 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/snakeitem.cpp @@ -0,0 +1,57 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "snake.h" +#include "snakeitem.h" + +namespace CRAWL { + + +SnakeItem::SnakeItem(const QString &name, const QString &viewTempalte, QObject *ptr): + SingleClasterWorldItem(name, viewTempalte, ptr) { + setAngularVelocity(-1); + setFDecorative(true); + +} + +void SnakeItem::setPrev(const IWorldItem * newPrev) { + _prevObject = newPrev; +} + +void SnakeItem::render(unsigned int tbfMsec) { + + if (!_prevObject) { + return; + } + + auto rotationVector = (_prevObject->position() - position()); + + if (auto claster = static_cast(parentClaster())) { + float rotationLength = rotationVector.length(); + + if (rotationLength > lengthBetwinItems() * 10) { + setposition(_prevObject->position()); + } else if (rotationLength > lengthBetwinItems()) { + setMovableVector(rotationVector.normalized() * claster->currentMovableVector().length()); + } + } + + MovableObject::render(tbfMsec); +} + +const IWorldItem * SnakeItem::prev() const { + return _prevObject; +} + +float SnakeItem::lengthBetwinItems() const { + return _lengthBetwinItems; +} + +void SnakeItem::setLengthBetwinItems(float newLengthBetwinItems) { + _lengthBetwinItems = newLengthBetwinItems; +} +} diff --git a/src/engine/src/public/ButterflyEngine/core/snakeitem.h b/src/engine/src/public/ButterflyEngine/core/snakeitem.h new file mode 100644 index 0000000..ea7eac4 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/snakeitem.h @@ -0,0 +1,60 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef SNAKEITEM_H +#define SNAKEITEM_H + +#include "iworlditem.h" +#include "singleclasterworlditem.h" +#include "Extensions/movableobject.h" + +namespace CRAWL { + + +class CRAWL_EXPORT SnakeItem: public SingleClasterWorldItem, public MovableObject +{ + Q_OBJECT +public: + SnakeItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + /** + * @brief setPrev This method sets id of the previous snake item. + * @param newPrev this is new value of the previous snake item. + */ + void setPrev(const IWorldItem * newPrev); + void render(unsigned int tbfMsec) override; + + /** + * @brief prev This method return prev object of snake + * @return the prev objects of the snake + */ + const IWorldItem * prev() const; + + /** + * @brief lengthBetwinItems This method return current length betwin current and parew item. + * @return current length betwin current and parew item. + * @note See also the setPrev method. + */ + float lengthBetwinItems() const; + + /** + * @brief setLengthBetwinItems This method sets new valeu of the length betwin current and parew item. + * @param newLengthBetwinItems This is new value of the length betwin current and parew item. + */ + void setLengthBetwinItems(float newLengthBetwinItems); + +private: + const IWorldItem *_prevObject = nullptr; + float _lengthBetwinItems = 1; +}; + +} + +#endif // SNAKEITEM_H diff --git a/src/engine/src/public/ButterflyEngine/core/startdata.cpp b/src/engine/src/public/ButterflyEngine/core/startdata.cpp new file mode 100644 index 0000000..f0c3e12 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/startdata.cpp @@ -0,0 +1,46 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "startdata.h" + +namespace CRAWL { + +StartData::StartData() { + +} + +StartData::StartData(User *player, int snake) { + setPlayer(player); + setSnakeType(snake); +} + + +User *StartData::player() const{ + return _player; +} + +void StartData::setPlayer(User *newPlayer) { + _player = newPlayer; +} + +int StartData::snakeType() const { + return _snakeType; +} + +void StartData::setSnakeType(int newSnake) { + _snakeType = newSnake; +} + +const QSet &StartData::snakePerks() const { + return _snakePerks; +} + +void StartData::setSnakePerks(const QSet &newSnakePerks) { + _snakePerks = newSnakePerks; +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/startdata.h b/src/engine/src/public/ButterflyEngine/core/startdata.h new file mode 100644 index 0000000..3320f48 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/startdata.h @@ -0,0 +1,80 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include +#include +#include "global.h" + +#ifndef STARTDATA_H +#define STARTDATA_H + +namespace CRAWL { + +class User; +class PlayableObject; + +/** + * @brief The StartData class This class contains arguments for starting new game session. + */ +class CRAWL_EXPORT StartData +{ +public: + StartData(); + + StartData(User * player, int snake); + + /** + * @brief player This method return pointer to user that will be control player snake. + * @return pointer to user that will be control player snake. + * @see StartData::setPlayer + */ + User *player() const; + + /** + * @brief setPlayer This method sets + * @param newPlayer This is new object of the user. + * @see StartData::player + */ + void setPlayer(User *newPlayer); + + /** + * @brief snakeType This method return select for game snake object type. + * @return select for game snake object. + * @see StartData::setSnakeType + */ + int snakeType() const; + + /** + * @brief setSnakeType This method sets new selected for game object type, + * @param newSnake This is new selected for game object + * @see StartData::snakeType + */ + void setSnakeType(int newSnake); + + /** + * @brief snakePerks This method return the list of the used snake upgrades. + * @return list of the used upgrades of the snake. + * @see StartData::setSnakePerks + */ + const QSet &snakePerks() const; + + /** + * @brief setSnakePerks This method sets new list of the used upgrades. + * @param newSnakePerks This is list of the used upgrades. + * @see StartData::snakePerks + */ + void setSnakePerks(const QSet &newSnakePerks); + +private: + User *_player = nullptr; + int _snakeType; + QSet _snakePerks; +}; + +} + +#endif // STARTDATA_H diff --git a/src/engine/src/public/ButterflyEngine/core/sun.cpp b/src/engine/src/public/ButterflyEngine/core/sun.cpp new file mode 100644 index 0000000..6788cea --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/sun.cpp @@ -0,0 +1,22 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "sun.h" + +namespace CRAWL { + +Sun::Sun(const QVector3D* center): + DayItem(center, AUTO_CLASS_NAME) { + setColor("#fff6d0"); + +} + +void Sun::onIntersects(const IWorldItem *) {} + +void Sun::init() {} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/sun.h b/src/engine/src/public/ButterflyEngine/core/sun.h new file mode 100644 index 0000000..913c5bd --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/sun.h @@ -0,0 +1,35 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef SUN_H +#define SUN_H + +#include "Crawl/dayitem.h" + +namespace CRAWL { + +/** + * @brief The Sun class This is default implementation of the sun for the Day class. + */ +class CRAWL_EXPORT Sun: public DayItem +{ + Q_OBJECT +public: + Sun(const QVector3D* center); + + // IWorldItem interface +protected: + void onIntersects(const IWorldItem *item); + + // IRender interface +public: + void init(); +}; + +} +#endif // SUN_H diff --git a/src/engine/src/public/ButterflyEngine/core/viewtemaplatemodel.cpp b/src/engine/src/public/ButterflyEngine/core/viewtemaplatemodel.cpp new file mode 100644 index 0000000..16f8534 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/viewtemaplatemodel.cpp @@ -0,0 +1,32 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "viewtemaplatemodel.h" + +namespace CRAWL { + +ViewTemaplateModel::ViewTemaplateModel(const QString &viewTempalte, QObject *ptr): QObject(ptr) { + _viewTemplate = viewTempalte; +} + +const QString &ViewTemaplateModel::viewTemplate() const { + return _viewTemplate; +} + +QObject *ViewTemaplateModel::viewObject() const { + return _viewObject; +} + +void ViewTemaplateModel::setViewObject(QObject *newViewObject) { + if (_viewObject == newViewObject) + return; + _viewObject = newViewObject; + emit viewObjectChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/viewtemaplatemodel.h b/src/engine/src/public/ButterflyEngine/core/viewtemaplatemodel.h new file mode 100644 index 0000000..d39a9c5 --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/viewtemaplatemodel.h @@ -0,0 +1,72 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef VIEWTEMAPLATEMODEL_H +#define VIEWTEMAPLATEMODEL_H + +#include "global.h" +#include + +namespace CRAWL { + +/** + * @brief The ViewTemaplateModel class This is base class for supporting model view template in qml. + * This class is base model og the view objects. + * All qml viewObjects will be generated using the ViewTemaplateModel::viewTemplate method on The main QML scane. + * + */ +class CRAWL_EXPORT ViewTemaplateModel: public QObject +{ + Q_OBJECT + + /** + * @brief viewTemplate This is path to the qml file with gui implementation of this model class. + */ + Q_PROPERTY(QString viewTemplate READ viewTemplate) + + /** + * @brief viewObject This is object of view companent. + * @note If the object not inited and the model propetye of the view is empty then this property will be equals nullptr + */ + Q_PROPERTY(QObject *viewObject READ viewObject WRITE setViewObject NOTIFY viewObjectChanged) +public: + + ViewTemaplateModel(const QString& viewTempalte, + QObject *ptr = nullptr); + + /** + * @brief viewTemplate This is path to the qml file with gui implementation of this model class. + * @return path to the qml file with gui implementation of this model class. + */ + const QString& viewTemplate() const; + + /** + * @brief viewObject This is object of view companent. + * @note For working with the view propertys use the QOBject::getproperty and QObject::setproperty methods. For invoke view method use the "QMetaObject::invokeMethod" method. + * For get more inforamtion about qt method see the Qt documentation. + * @return pointer to view object. + * @note If the object not inited and the model propetye of the view is empty then this property will be equals nullptr + */ + QObject *viewObject() const; + + /** + * @brief setViewObject This method sets new value of the ViewObject. This method will be invoked automaticly. + * @param newViewObject This is new valur of the view object. + */ + void setViewObject(QObject *newViewObject); + +signals: + void viewObjectChanged(); + +private: + QString _viewTemplate; + QObject *_viewObject = nullptr; +}; + +} +#endif // VIEWTEMAPLATEMODEL_H diff --git a/src/engine/src/public/ButterflyEngine/core/wint.cpp b/src/engine/src/public/ButterflyEngine/core/wint.cpp new file mode 100644 index 0000000..19cbc1e --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/wint.cpp @@ -0,0 +1,38 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "wint.h" + +namespace CRAWL { + +Wint::Wint(): Affector(AUTO_CLASS_NAME, "qrc:/CrawlModule/particles/Wint.qml") { +} + +float Wint::magnitude() const { + return _magnitude; +} + +void Wint::setMagnitude(float newMagnitude) { + if (qFuzzyCompare(_magnitude, newMagnitude)) + return; + _magnitude = newMagnitude; + emit magnitudeChanged(); +} + +const QVector3D &Wint::direction() const { + return _direction; +} + +void Wint::setDirection(const QVector3D &newDirection) { + if (_direction == newDirection) + return; + _direction = newDirection; + emit directionChanged(); +} + +} diff --git a/src/engine/src/public/ButterflyEngine/core/wint.h b/src/engine/src/public/ButterflyEngine/core/wint.h new file mode 100644 index 0000000..c3cb74f --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/core/wint.h @@ -0,0 +1,75 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef WINT_H +#define WINT_H + +#include "affector.h" +#include "Extensions/rotationaroundaxis.h" + +namespace CRAWL { + +/** + * @brief The Wint class This is example of the using Affector class. + * implementation of the wint. + */ +class CRAWL_EXPORT Wint: public Affector +{ + Q_OBJECT + + + /** + * @brief direction This property defines the direction the gravity will affect toward. Values will be automatically normalized to a unit vector. + */ + Q_PROPERTY(QVector3D direction READ direction WRITE setDirection NOTIFY directionChanged) + + /** + * @brief magnitude This property defines the magnitude in position change per second. Negative magnitude accelerates the opposite way from the direction. +The default value is 100.0. + */ + Q_PROPERTY(float magnitude READ magnitude WRITE setMagnitude NOTIFY magnitudeChanged) + +public: + Wint(); + + // IWorldItem interface + /** + * @brief direction This method return current direction of the wint. + * @return direction of the wint. + */ + const QVector3D &direction() const; + + /** + * @brief setDirection This method sets new direction of the wint. + * @param newDirection new value of the direction of the wint. + */ + void setDirection(const QVector3D &newDirection); + + /** + * @brief magnitude This property defines the magnitude in position change per second. Negative magnitude accelerates the opposite way from the direction. +The default value is 10.0. + * @return current value of the magnitude. + */ + float magnitude() const; + + /** + * @brief setMagnitude This method sets new vlaue of the magnitucde of this object. + * @param newMagnitude Tis is new value of the magnitude property + */ + void setMagnitude(float newMagnitude); + +signals: + void directionChanged(); + void magnitudeChanged(); + +private: + + QVector3D _direction = {1, 0, 0}; + float _magnitude = 10; +}; +} +#endif // WINT_H diff --git a/src/Library/src/public/ButterflyEngine/global.h.in b/src/engine/src/public/ButterflyEngine/global.h similarity index 50% rename from src/Library/src/public/ButterflyEngine/global.h.in rename to src/engine/src/public/ButterflyEngine/global.h index 30b265a..c3cfcfb 100644 --- a/src/Library/src/public/ButterflyEngine/global.h.in +++ b/src/engine/src/public/ButterflyEngine/global.h @@ -5,18 +5,18 @@ //# of this license document, but changing it is not allowed. //# -#ifndef ButterflyEngine_GLOBAL_H -#define ButterflyEngine_GLOBAL_H +#ifndef BUTTERFLY_ENGINE_GLOBAL_H +#define BUTTERFLY_ENGINE_GLOBAL_H #include -#define ButterflyEngine_VERSION "@ButterflyEngine_VERSION@" +#define BUTTERFLY_ENGINE_VERSION "0.2.c7fbe94" -#if defined(ButterflyEngine_LIBRARY) -# define ButterflyEngine_EXPORT Q_DECL_EXPORT +#if defined(BUTTERFLY_ENGINE_LIBRARY) +# define BUTTERFLY_ENGINE_EXPORT Q_DECL_EXPORT #else -# define ButterflyEngine_EXPORT Q_DECL_IMPORT +# define BUTTERFLY_ENGINE_EXPORT Q_DECL_IMPORT #endif -#endif //ButterflyEngine_GLOBAL_H +#endif //BUTTERFLY_ENGINE_GLOBAL_H diff --git a/src/engine/src/public/ButterflyEngine/global.h.in b/src/engine/src/public/ButterflyEngine/global.h.in new file mode 100644 index 0000000..84666ed --- /dev/null +++ b/src/engine/src/public/ButterflyEngine/global.h.in @@ -0,0 +1,22 @@ +//# +//# Copyright (C) 2018-2023 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef BUTTERFLY_ENGINE_GLOBAL_H +#define BUTTERFLY_ENGINE_GLOBAL_H + +#include + +#define BUTTERFLY_ENGINE_VERSION "@BUTTERFLY_ENGINE_VERSION@" + +#if defined(BUTTERFLY_ENGINE_LIBRARY) +# define BUTTERFLY_ENGINE_EXPORT Q_DECL_EXPORT +#else +# define BUTTERFLY_ENGINE_EXPORT Q_DECL_IMPORT +#endif + +#endif //BUTTERFLY_ENGINE_GLOBAL_H + diff --git a/src/Example/CMakeLists.txt b/src/example/CMakeLists.txt similarity index 92% rename from src/Example/CMakeLists.txt rename to src/example/CMakeLists.txt index a42005b..6d3048b 100644 --- a/src/Example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -58,7 +58,7 @@ if (ANDROID) set(ANDROID_API_VERSION $ENV{ANDROID_API_VERSION}) set(OPENSSL_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}") - set(ButterflyEngine_EXTRA_LIBS + set(BUTTERFLY_ENGINE_EXTRA_LIBS ${PROJECT_NAME}Library # libName ) @@ -74,7 +74,7 @@ if (ANDROID) "${SIGPATH}/quasarapp.keystore" "${SIGPASS_QUASARAPP}" "${TARGET_DIR}" - "${ButterflyEngine_EXTRA_LIBS}") + "${BUTTERFLY_ENGINE_EXTRA_LIBS}") else() message("NO_SIGN_APP") @@ -82,7 +82,7 @@ if (ANDROID) addDeployAPK(${CURRENT_PROJECT} "${CMAKE_CURRENT_LIST_DIR}/android" "${TARGET_DIR}" - "${ButterflyEngine_EXTRA_LIBS}") + "${BUTTERFLY_ENGINE_EXTRA_LIBS}") endif() set(manifest_file "${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml") @@ -108,9 +108,9 @@ elseif(IOS) # set_xcode_property(${CURRENT_PROJECT} PRODUCT_BUNDLE_IDENTIFIER ${CHEATCARD_PACKAGE_ID} All) set_target_properties(${CURRENT_PROJECT} PROPERTIES - MACOSX_BUNDLE_GUI_IDENTIFIER ${ButterflyEngine_PACKAGE_ID} - MACOSX_BUNDLE_BUNDLE_VERSION ${ButterflyEngine_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${ButterflyEngine_VERSION} + MACOSX_BUNDLE_GUI_IDENTIFIER ${BUTTERFLY_ENGINE_PACKAGE_ID} + MACOSX_BUNDLE_BUNDLE_VERSION ${BUTTERFLY_ENGINE_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${BUTTERFLY_ENGINE_VERSION} ) else() # Desctop deploying diff --git a/src/example/Deploy/ButterflyEngine.json b/src/example/Deploy/ButterflyEngine.json new file mode 100644 index 0000000..a991fea --- /dev/null +++ b/src/example/Deploy/ButterflyEngine.json @@ -0,0 +1,27 @@ +{ + "bin": [ + "src/build/Debug/ButterflyEngineEaxample", + "src/build/Debug/ButterflyEngineEaxample.exe" + ], + "clear": true, + "binPrefix": "/home/andrei/gitHub/build-ButterflyEngine-Desktop_Qt_6_5_1_GCC_64bit-Debug", + "libDir": [ + "/home/andrei/gitHub/ButterflyEngine", + "/home/andrei/Qt/6.5.1/gcc_64", + "/home/andrei/gitHub/build-ButterflyEngine-Desktop_Qt_6_5_1_GCC_64bit-Debug" + ], + "recursiveDepth": "10", + "deploySystem": false, + "qmlDir": "../", + "deb": true, + "qif": true, + "zip": true, + "ignoreEnv": [ + "/home/andrei/gitHub/ButterflyEngine/Distro" + ], + "extraLib": "crypto", + "targetDir": "/home/andrei/gitHub/ButterflyEngine/Distro", + "deployVersion": "0.2.c7fbe94", + +} + diff --git a/src/Example/Deploy/ButterflyEngine.json.in b/src/example/Deploy/ButterflyEngine.json.in similarity index 91% rename from src/Example/Deploy/ButterflyEngine.json.in rename to src/example/Deploy/ButterflyEngine.json.in index a7f1b90..a3f75ff 100644 --- a/src/Example/Deploy/ButterflyEngine.json.in +++ b/src/example/Deploy/ButterflyEngine.json.in @@ -21,7 +21,7 @@ ], "extraLib": "crypto", "targetDir": "@CMAKE_SOURCE_DIR@/Distro", - "deployVersion": "@ButterflyEngine_VERSION@", + "deployVersion": "@BUTTERFLY_ENGINE_VERSION@", } diff --git a/src/Example/android/AndroidManifest.xml.in b/src/example/android/AndroidManifest.xml.in similarity index 100% rename from src/Example/android/AndroidManifest.xml.in rename to src/example/android/AndroidManifest.xml.in diff --git a/src/Example/android/build.gradle.in b/src/example/android/build.gradle.in similarity index 100% rename from src/Example/android/build.gradle.in rename to src/example/android/build.gradle.in diff --git a/src/Example/android/gradle.properties b/src/example/android/gradle.properties similarity index 100% rename from src/Example/android/gradle.properties rename to src/example/android/gradle.properties diff --git a/src/Example/android/gradle/wrapper/gradle-wrapper.jar b/src/example/android/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from src/Example/android/gradle/wrapper/gradle-wrapper.jar rename to src/example/android/gradle/wrapper/gradle-wrapper.jar diff --git a/src/Example/android/gradle/wrapper/gradle-wrapper.properties b/src/example/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from src/Example/android/gradle/wrapper/gradle-wrapper.properties rename to src/example/android/gradle/wrapper/gradle-wrapper.properties diff --git a/src/Example/android/gradlew b/src/example/android/gradlew similarity index 100% rename from src/Example/android/gradlew rename to src/example/android/gradlew diff --git a/src/Example/android/gradlew.bat b/src/example/android/gradlew.bat similarity index 100% rename from src/Example/android/gradlew.bat rename to src/example/android/gradlew.bat diff --git a/src/Example/android/res/drawable/splashscreen.xml b/src/example/android/res/drawable/splashscreen.xml similarity index 100% rename from src/Example/android/res/drawable/splashscreen.xml rename to src/example/android/res/drawable/splashscreen.xml diff --git a/src/Example/android/res/drawable/splashscreen_land.xml b/src/example/android/res/drawable/splashscreen_land.xml similarity index 100% rename from src/Example/android/res/drawable/splashscreen_land.xml rename to src/example/android/res/drawable/splashscreen_land.xml diff --git a/src/Example/android/res/drawable/splashscreen_port.xml b/src/example/android/res/drawable/splashscreen_port.xml similarity index 100% rename from src/Example/android/res/drawable/splashscreen_port.xml rename to src/example/android/res/drawable/splashscreen_port.xml diff --git a/src/Example/android/res/values-land/splashscreentheme.xml b/src/example/android/res/values-land/splashscreentheme.xml similarity index 100% rename from src/Example/android/res/values-land/splashscreentheme.xml rename to src/example/android/res/values-land/splashscreentheme.xml diff --git a/src/Example/android/res/values-port/splashscreentheme.xml b/src/example/android/res/values-port/splashscreentheme.xml similarity index 100% rename from src/Example/android/res/values-port/splashscreentheme.xml rename to src/example/android/res/values-port/splashscreentheme.xml diff --git a/src/Example/android/res/values/libs.xml b/src/example/android/res/values/libs.xml similarity index 100% rename from src/Example/android/res/values/libs.xml rename to src/example/android/res/values/libs.xml diff --git a/src/Example/android/res/values/splashscreentheme.xml b/src/example/android/res/values/splashscreentheme.xml similarity index 100% rename from src/Example/android/res/values/splashscreentheme.xml rename to src/example/android/res/values/splashscreentheme.xml diff --git a/src/Example/android/src/com/quasarapp/androidtools/MainActivity.java b/src/example/android/src/com/quasarapp/androidtools/MainActivity.java similarity index 100% rename from src/Example/android/src/com/quasarapp/androidtools/MainActivity.java rename to src/example/android/src/com/quasarapp/androidtools/MainActivity.java diff --git a/src/Example/languages/de.ts b/src/example/languages/de.ts similarity index 100% rename from src/Example/languages/de.ts rename to src/example/languages/de.ts diff --git a/src/Library/languages/en.ts b/src/example/languages/en.ts similarity index 100% rename from src/Library/languages/en.ts rename to src/example/languages/en.ts diff --git a/src/Example/languages/es.ts b/src/example/languages/es.ts similarity index 100% rename from src/Example/languages/es.ts rename to src/example/languages/es.ts diff --git a/src/Example/languages/fr.ts b/src/example/languages/fr.ts similarity index 100% rename from src/Example/languages/fr.ts rename to src/example/languages/fr.ts diff --git a/src/Example/languages/ja.ts b/src/example/languages/ja.ts similarity index 100% rename from src/Example/languages/ja.ts rename to src/example/languages/ja.ts diff --git a/src/Example/languages/pl.ts b/src/example/languages/pl.ts similarity index 100% rename from src/Example/languages/pl.ts rename to src/example/languages/pl.ts diff --git a/src/Example/languages/ru.ts b/src/example/languages/ru.ts similarity index 100% rename from src/Example/languages/ru.ts rename to src/example/languages/ru.ts diff --git a/src/Example/languages/tr.ts b/src/example/languages/tr.ts similarity index 100% rename from src/Example/languages/tr.ts rename to src/example/languages/tr.ts diff --git a/src/Example/languages/uk.ts b/src/example/languages/uk.ts similarity index 100% rename from src/Example/languages/uk.ts rename to src/example/languages/uk.ts diff --git a/src/Example/languages/zh.ts b/src/example/languages/zh.ts similarity index 100% rename from src/Example/languages/zh.ts rename to src/example/languages/zh.ts diff --git a/src/Example/main.cpp b/src/example/main.cpp similarity index 100% rename from src/Example/main.cpp rename to src/example/main.cpp