From 9cb69736598fb4d08ff02c525adb87ddb75525a0 Mon Sep 17 00:00:00 2001 From: fredboy Date: Mon, 30 Jun 2025 01:10:39 +0700 Subject: [PATCH] Refactor menu --- .../cavedroid/AndroidPreferencesStore.kt | 2 +- assets/json/menu.json | 55 ++++++ assets/json/menu_main_buttons.json | 15 -- assets/json/menu_new_game_buttons.json | 11 -- assets/json/menu_options_buttons.json | 14 -- .../kotlin/DependencyHandlerExtentions.kt | 6 + core/build.gradle.kts | 1 + .../cavedroid/common/CaveDroidConstants.kt | 7 + .../cavedroid/common/api/GameController.kt | 8 + .../cavedroid/common/api}/PreferencesStore.kt | 4 +- .../fredboy/cavedroid/common/di/MenuScope.kt | 7 + .../repository/GameContextRepositoryImpl.kt | 6 + core/data/menu/build.gradle.kts | 18 ++ .../cavedroid/data/menu/di/DataMenuModule.kt | 14 ++ .../data/menu/mapper/MenuButtonMapper.kt | 52 ++++++ .../data/menu/model/MenuButtonDto.kt | 13 ++ .../menu/model/MenuButtonVisibilityDto.kt | 9 + .../repository/MenuButtonRepositoryImpl.kt | 88 ++++++++++ core/domain/menu/build.gradle.kts | 13 ++ .../cavedroid/domain/menu/model/MenuButton.kt | 25 +++ .../menu/repository/MenuButtonRepository.kt | 18 ++ .../ru/deadsoftware/cavedroid/MainConfig.java | 59 +------ .../cavedroid/menu/MenuComponent.java | 16 +- .../deadsoftware/cavedroid/menu/MenuProc.java | 166 ------------------ .../cavedroid/menu/MenuScope.java | 10 -- .../cavedroid/menu/MenuScreen.java | 23 ++- .../cavedroid/menu/objects/Button.java | 72 -------- .../menu/objects/ButtonEventListener.java | 13 -- .../menu/objects/ButtonRenderer.java | 7 - .../cavedroid/menu/submenus/Menu.java | 152 ---------------- .../cavedroid/menu/submenus/MenuMain.java | 53 ------ .../cavedroid/menu/submenus/MenuNewGame.java | 38 ---- .../deadsoftware/cavedroid/misc/Assets.java | 26 --- .../deadsoftware/cavedroid/misc/Renderer.java | 109 ------------ .../ru/deadsoftware/cavedroid/CaveGame.kt | 32 ++-- .../deadsoftware/cavedroid/MainComponent.kt | 5 +- .../menu/objects/BooleanOptionButton.kt | 29 --- .../cavedroid/menu/submenus/MenuOptions.kt | 29 --- .../cavedroid/menu/submenus/MenusFactory.kt | 75 -------- .../cavedroid/misc/utils/AssetLoader.kt | 26 --- core/zygote/build.gradle.kts | 21 +++ .../zygote/menu/action/ExitGameAction.kt | 21 +++ .../zygote/menu/action/IMenuAction.kt | 9 + .../zygote/menu/action/LoadGameAction.kt | 29 +++ .../menu/action/NewGameCreativeAction.kt | 21 +++ .../menu/action/NewGameSurvivalAction.kt | 21 +++ .../zygote/menu/action/OpenMainMenuAction.kt | 21 +++ .../menu/action/OpenNewGameMenuAction.kt | 21 +++ .../menu/action/OpenOptionsMenuAction.kt | 21 +++ .../menu/action/annotation/BindsMenuAction.kt | 12 ++ .../zygote/menu/input/MenuInputProcessor.kt | 120 +++++++++++++ .../annotation/BindsMenuBooleanOption.kt | 12 ++ .../bool/DynamicCameraMenuBooleanOption.kt | 25 +++ .../bool/FullscreenMenuBooleanOption.kt | 25 +++ .../menu/option/bool/IMenuBooleanOption.kt | 9 + .../zygote/menu/renderer/MenuRenderer.kt | 155 ++++++++++++++++ .../desktop/DesktopPreferencesStore.kt | 2 +- settings.gradle.kts | 7 + 58 files changed, 943 insertions(+), 935 deletions(-) create mode 100644 assets/json/menu.json delete mode 100644 assets/json/menu_main_buttons.json delete mode 100644 assets/json/menu_new_game_buttons.json delete mode 100644 assets/json/menu_options_buttons.json create mode 100644 core/common/src/main/kotlin/ru/fredboy/cavedroid/common/CaveDroidConstants.kt rename core/{src/main/kotlin/ru/deadsoftware/cavedroid/prefs => common/src/main/kotlin/ru/fredboy/cavedroid/common/api}/PreferencesStore.kt (75%) create mode 100644 core/common/src/main/kotlin/ru/fredboy/cavedroid/common/di/MenuScope.kt create mode 100644 core/data/menu/build.gradle.kts create mode 100644 core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/di/DataMenuModule.kt create mode 100644 core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/mapper/MenuButtonMapper.kt create mode 100644 core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonDto.kt create mode 100644 core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonVisibilityDto.kt create mode 100644 core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/repository/MenuButtonRepositoryImpl.kt create mode 100644 core/domain/menu/build.gradle.kts create mode 100644 core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/model/MenuButton.kt create mode 100644 core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/repository/MenuButtonRepository.kt delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuProc.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScope.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/Button.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonEventListener.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonRenderer.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/Menu.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuMain.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuNewGame.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/misc/Assets.java delete mode 100644 core/src/main/java/ru/deadsoftware/cavedroid/misc/Renderer.java delete mode 100644 core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/objects/BooleanOptionButton.kt delete mode 100644 core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenuOptions.kt delete mode 100644 core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenusFactory.kt delete mode 100644 core/src/main/kotlin/ru/deadsoftware/cavedroid/misc/utils/AssetLoader.kt create mode 100644 core/zygote/build.gradle.kts create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/ExitGameAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/IMenuAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/LoadGameAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameCreativeAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameSurvivalAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenMainMenuAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenNewGameMenuAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenOptionsMenuAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/annotation/BindsMenuAction.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/input/MenuInputProcessor.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/annotation/BindsMenuBooleanOption.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/DynamicCameraMenuBooleanOption.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/FullscreenMenuBooleanOption.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/IMenuBooleanOption.kt create mode 100644 core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/renderer/MenuRenderer.kt diff --git a/android/src/main/kotlin/ru/deadsoftware/cavedroid/AndroidPreferencesStore.kt b/android/src/main/kotlin/ru/deadsoftware/cavedroid/AndroidPreferencesStore.kt index 4b16659..d334cfe 100644 --- a/android/src/main/kotlin/ru/deadsoftware/cavedroid/AndroidPreferencesStore.kt +++ b/android/src/main/kotlin/ru/deadsoftware/cavedroid/AndroidPreferencesStore.kt @@ -1,7 +1,7 @@ package ru.deadsoftware.cavedroid import android.content.Context -import ru.deadsoftware.cavedroid.prefs.PreferencesStore +import ru.fredboy.cavedroid.common.api.PreferencesStore class AndroidPreferencesStore( private val context: Context diff --git a/assets/json/menu.json b/assets/json/menu.json new file mode 100644 index 0000000..974fb30 --- /dev/null +++ b/assets/json/menu.json @@ -0,0 +1,55 @@ +{ + "main": { + "new_game": { + "label": "New Game", + "actionKey": "new_game_action" + }, + "load_game": { + "label": "Load Game", + "actionKey": "load_game_action" + }, + "options": { + "label": "Settings", + "actionKey": "options_action" + }, + "quit": { + "label": "Quit", + "actionKey": "exit_game_action" + } + }, + "new_game": { + "creative": { + "label": "Creative", + "actionKey": "new_game_creative_action" + }, + "survival": { + "label": "Survival", + "actionKey": "new_game_survival_action" + }, + "back": { + "label": "Back", + "actionKey": "menu_main_action" + } + }, + "options": { + "dyncam": { + "type": "boolean_option", + "label": "Dynamic Camera: %s", + "actionKey": "toggle_dyncam_action", + "options": ["dyncam"] + }, + "fullscreen": { + "type": "boolean_option", + "label": "Fullscreen: %s", + "actionKey": "toggle_fullscreen_action", + "options": ["fullscreen"], + "visibility": { + "android": false + } + }, + "back": { + "label": "Back", + "actionKey": "menu_main_action" + } + } +} \ No newline at end of file diff --git a/assets/json/menu_main_buttons.json b/assets/json/menu_main_buttons.json deleted file mode 100644 index 97d0938..0000000 --- a/assets/json/menu_main_buttons.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "new_game": { - "label": "New Game" - }, - "load_game": { - "label": "Load Game", - "type": 0 - }, - "options": { - "label": "Settings" - }, - "quit": { - "label": "Quit" - } -} \ No newline at end of file diff --git a/assets/json/menu_new_game_buttons.json b/assets/json/menu_new_game_buttons.json deleted file mode 100644 index ca4c404..0000000 --- a/assets/json/menu_new_game_buttons.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "creative": { - "label": "Creative" - }, - "survival": { - "label": "Survival" - }, - "back": { - "label": "Back" - } -} \ No newline at end of file diff --git a/assets/json/menu_options_buttons.json b/assets/json/menu_options_buttons.json deleted file mode 100644 index bb956cd..0000000 --- a/assets/json/menu_options_buttons.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "dyncam": { - "option_type": "boolean", - "label": "Dynamic Camera: %%value%%" - }, - "fullscreen": { - "option_type": "boolean", - "label": "Fullscreen: %%value%%", - "visible_on_android": false - }, - "back": { - "label": "Back" - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/DependencyHandlerExtentions.kt b/buildSrc/src/main/kotlin/DependencyHandlerExtentions.kt index 87a16b3..030f783 100644 --- a/buildSrc/src/main/kotlin/DependencyHandlerExtentions.kt +++ b/buildSrc/src/main/kotlin/DependencyHandlerExtentions.kt @@ -19,6 +19,7 @@ fun DependencyHandler.useDataModules() { useModule(":core:data:assets") useModule(":core:data:configuration") useModule(":core:data:items") + useModule(":core:data:menu") useModule(":core:data:save") } @@ -27,6 +28,7 @@ fun DependencyHandler.useDomainModules() { useModule(":core:domain:configuration") useModule(":core:domain:items") useModule(":core:domain:save") + useModule(":core:domain:menu") useModule(":core:domain:world") } @@ -50,6 +52,10 @@ fun DependencyHandler.useUxModules() { useModule(":core:ux:rendering") } +fun DependencyHandler.useZygoteModule() { + useModule(":core:zygote") +} + fun DependencyHandler.useAutomultibind() { implementation(Dependencies.Automultibind.annotations) ksp(Dependencies.Automultibind.ksp) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index d6f312d..1dec1e4 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { useEntityModules() useGameModules() useUxModules() + useZygoteModule() implementation(Dependencies.jetbrainsAnnotations) } diff --git a/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/CaveDroidConstants.kt b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/CaveDroidConstants.kt new file mode 100644 index 0000000..180b694 --- /dev/null +++ b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/CaveDroidConstants.kt @@ -0,0 +1,7 @@ +package ru.fredboy.cavedroid.common + +object CaveDroidConstants { + + const val VERSION = "alpha 0.9.2" + +} \ No newline at end of file diff --git a/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/GameController.kt b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/GameController.kt index 78f3e57..4574485 100644 --- a/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/GameController.kt +++ b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/GameController.kt @@ -4,4 +4,12 @@ interface GameController { fun quitGame() + fun newGameCreative() + + fun newGameSurvival() + + fun loadGame() + + fun exitGame() + } \ No newline at end of file diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/prefs/PreferencesStore.kt b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/PreferencesStore.kt similarity index 75% rename from core/src/main/kotlin/ru/deadsoftware/cavedroid/prefs/PreferencesStore.kt rename to core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/PreferencesStore.kt index edc9517..9b48604 100644 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/prefs/PreferencesStore.kt +++ b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/api/PreferencesStore.kt @@ -1,4 +1,4 @@ -package ru.deadsoftware.cavedroid.prefs +package ru.fredboy.cavedroid.common.api interface PreferencesStore { @@ -6,4 +6,4 @@ interface PreferencesStore { fun setPreference(key: String, value: String?) -} +} \ No newline at end of file diff --git a/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/di/MenuScope.kt b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/di/MenuScope.kt new file mode 100644 index 0000000..52de4fe --- /dev/null +++ b/core/common/src/main/kotlin/ru/fredboy/cavedroid/common/di/MenuScope.kt @@ -0,0 +1,7 @@ +package ru.fredboy.cavedroid.common.di + +import javax.inject.Scope + +@Scope +@Retention(AnnotationRetention.RUNTIME) +annotation class MenuScope diff --git a/core/data/configuration/src/main/kotlin/ru/fredboy/cavedroid/data/configuration/repository/GameContextRepositoryImpl.kt b/core/data/configuration/src/main/kotlin/ru/fredboy/cavedroid/data/configuration/repository/GameContextRepositoryImpl.kt index fb7b2a5..b3e2b12 100644 --- a/core/data/configuration/src/main/kotlin/ru/fredboy/cavedroid/data/configuration/repository/GameContextRepositoryImpl.kt +++ b/core/data/configuration/src/main/kotlin/ru/fredboy/cavedroid/data/configuration/repository/GameContextRepositoryImpl.kt @@ -1,5 +1,6 @@ package ru.fredboy.cavedroid.data.configuration.repository +import com.badlogic.gdx.Gdx import ru.fredboy.cavedroid.common.model.Joystick import ru.fredboy.cavedroid.data.configuration.store.GameContextStore import ru.fredboy.cavedroid.domain.configuration.model.CameraContext @@ -61,6 +62,11 @@ class GameContextRepositoryImpl @Inject constructor( } override fun setFullscreen(fullscreen: Boolean) { + if (fullscreen) { + Gdx.graphics.setFullscreenMode(Gdx.graphics.displayMode); + } else { + Gdx.graphics.setWindowedMode(getWidth().toInt(), getHeight().toInt()); + } gameContextStore.isFullscreen = fullscreen } diff --git a/core/data/menu/build.gradle.kts b/core/data/menu/build.gradle.kts new file mode 100644 index 0000000..73fdbcc --- /dev/null +++ b/core/data/menu/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + kotlin + ksp + kotlinxSerialization +} + +java.sourceCompatibility = ApplicationInfo.sourceCompatibility +java.targetCompatibility = ApplicationInfo.sourceCompatibility + +dependencies { + useCommonModule() + useLibgdx() + useKotlinxSerializationJson() + useDagger() + + useModule(":core:domain:assets") + useModule(":core:domain:menu") +} diff --git a/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/di/DataMenuModule.kt b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/di/DataMenuModule.kt new file mode 100644 index 0000000..621edeb --- /dev/null +++ b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/di/DataMenuModule.kt @@ -0,0 +1,14 @@ +package ru.fredboy.cavedroid.data.menu.di + +import dagger.Binds +import dagger.Module +import ru.fredboy.cavedroid.data.menu.repository.MenuButtonRepositoryImpl +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository + +@Module +abstract class DataMenuModule { + + @Binds + internal abstract fun bindMenuButtonsRepository(impl: MenuButtonRepositoryImpl): MenuButtonRepository + +} diff --git a/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/mapper/MenuButtonMapper.kt b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/mapper/MenuButtonMapper.kt new file mode 100644 index 0000000..9bafcc9 --- /dev/null +++ b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/mapper/MenuButtonMapper.kt @@ -0,0 +1,52 @@ +package ru.fredboy.cavedroid.data.menu.mapper + +import com.badlogic.gdx.Application +import com.badlogic.gdx.Gdx +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.data.menu.model.MenuButtonDto +import ru.fredboy.cavedroid.data.menu.model.MenuButtonVisibilityDto +import ru.fredboy.cavedroid.domain.menu.model.MenuButton +import javax.inject.Inject +import javax.inject.Singleton + +@MenuScope +class MenuButtonMapper @Inject constructor() { + + fun map(dto: MenuButtonDto): MenuButton { + return when (dto.type) { + "boolean_option" -> MenuButton.BooleanOption( + label = dto.label.toString(), + isVisible = mapVisibility(dto.visibility), + actionKey = dto.actionKey.orEmpty(), + optionKeys = dto.options.orEmpty(), + isEnabled = dto.enabled ?: true, + ) + + "default", null -> MenuButton.Simple( + label = dto.label.toString(), + isVisible = mapVisibility(dto.visibility), + actionKey = dto.actionKey.orEmpty(), + isEnabled = dto.enabled ?: true, + ) + + else -> + throw IllegalArgumentException("Unknown button type: ${dto.type}") + } + } + + fun setButtonEnabled(button: MenuButton, isEnabled: Boolean): MenuButton { + return when (button) { + is MenuButton.Simple -> button.copy(isEnabled = isEnabled) + is MenuButton.BooleanOption -> button.copy(isEnabled = isEnabled) + } + } + + private fun mapVisibility(dto: MenuButtonVisibilityDto?): Boolean { + dto ?: return true + + return when (Gdx.app.type) { + Application.ApplicationType.Android -> dto.android + else -> dto.desktop + } + } +} \ No newline at end of file diff --git a/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonDto.kt b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonDto.kt new file mode 100644 index 0000000..18819b1 --- /dev/null +++ b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonDto.kt @@ -0,0 +1,13 @@ +package ru.fredboy.cavedroid.data.menu.model + +import kotlinx.serialization.Serializable + +@Serializable +data class MenuButtonDto( + val label: String? = null, + val actionKey: String? = null, + val type: String? = null, + val enabled: Boolean? = null, + val visibility: MenuButtonVisibilityDto? = null, + val options: List? = null, +) diff --git a/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonVisibilityDto.kt b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonVisibilityDto.kt new file mode 100644 index 0000000..3704d65 --- /dev/null +++ b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/model/MenuButtonVisibilityDto.kt @@ -0,0 +1,9 @@ +package ru.fredboy.cavedroid.data.menu.model + +import kotlinx.serialization.Serializable + +@Serializable +data class MenuButtonVisibilityDto( + val android: Boolean = true, + val desktop: Boolean = true, +) diff --git a/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/repository/MenuButtonRepositoryImpl.kt b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/repository/MenuButtonRepositoryImpl.kt new file mode 100644 index 0000000..81b8a98 --- /dev/null +++ b/core/data/menu/src/main/kotlin/ru/fredboy/cavedroid/data/menu/repository/MenuButtonRepositoryImpl.kt @@ -0,0 +1,88 @@ +package ru.fredboy.cavedroid.data.menu.repository + +import com.badlogic.gdx.Gdx +import kotlinx.serialization.json.Json +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.data.menu.mapper.MenuButtonMapper +import ru.fredboy.cavedroid.data.menu.model.MenuButtonDto +import ru.fredboy.cavedroid.domain.menu.model.MenuButton +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository +import javax.inject.Inject + +@MenuScope +class MenuButtonRepositoryImpl @Inject constructor( + private val menuButtonMapper: MenuButtonMapper, +) : MenuButtonRepository { + + private var _initialized = false + + private val menuMap = LinkedHashMap>() + + private var currentMenu = "main" + + init { + initialize() + } + + override fun initialize() { + if (_initialized) { + Gdx.app.debug(TAG, "Attempted to init when already initialized") + return + } + + val jsonString = Gdx.files.internal("json/menu.json").readString() + + JsonFormat.decodeFromString>>(jsonString) + .forEach { (key, value) -> + menuMap[key] = value.mapValues { (_, dto) -> menuButtonMapper.map(dto) }.toMutableMap() + } + + _initialized = true + } + + override fun getButtonsForMenu(menuKey: String): Map? { + require(_initialized) { "$TAG was not initialized before access!" } + + return menuMap[menuKey].also { + if (it == null) { + Gdx.app.debug(TAG, "No buttons for $menuKey menu found") + } + } + } + + override fun setCurrentMenu(menuKey: String) { + currentMenu = menuKey + } + + override fun getCurrentMenuButtons(): Map? { + require(_initialized) { "$TAG was not initialized before access!" } + + return menuMap[currentMenu]?.filterValues { button -> button.isVisible } + } + + override fun setButtonEnabled(menuKey: String, buttonKey: String, enabled: Boolean) { + val menu = menuMap[menuKey] ?: run { + Gdx.app.error(TAG, "setButtonEnabled: menu with key '$menuKey' not found") + return + } + + val button = menu[buttonKey] ?: run { + Gdx.app.error(TAG, "setButtonEnabled: button with key '$buttonKey' not found") + return + } + + menu[buttonKey] = menuButtonMapper.setButtonEnabled(button, enabled) + } + + override fun dispose() { + menuMap.clear() + _initialized = false + } + + companion object { + private const val TAG = "MenuButtonsRepositoryImpl" + + private val JsonFormat = Json { ignoreUnknownKeys = true } + } + +} \ No newline at end of file diff --git a/core/domain/menu/build.gradle.kts b/core/domain/menu/build.gradle.kts new file mode 100644 index 0000000..9d3840d --- /dev/null +++ b/core/domain/menu/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + kotlin + ksp +} + +java.sourceCompatibility = ApplicationInfo.sourceCompatibility +java.targetCompatibility = ApplicationInfo.sourceCompatibility + +dependencies { + useCommonModule() + useLibgdx() + useDagger() +} diff --git a/core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/model/MenuButton.kt b/core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/model/MenuButton.kt new file mode 100644 index 0000000..63b4ec2 --- /dev/null +++ b/core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/model/MenuButton.kt @@ -0,0 +1,25 @@ +package ru.fredboy.cavedroid.domain.menu.model + +sealed class MenuButton { + + abstract val label: String + abstract val isVisible: Boolean + abstract val actionKey: String + abstract val isEnabled: Boolean + + + data class Simple( + override val label: String, + override val isVisible: Boolean, + override val actionKey: String, + override val isEnabled: Boolean, + ) : MenuButton() + + data class BooleanOption( + override val label: String, + override val isVisible: Boolean, + override val actionKey: String, + override val isEnabled: Boolean, + val optionKeys: List, + ) : MenuButton() +} diff --git a/core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/repository/MenuButtonRepository.kt b/core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/repository/MenuButtonRepository.kt new file mode 100644 index 0000000..775643b --- /dev/null +++ b/core/domain/menu/src/main/kotlin/ru/fredboy/cavedroid/domain/menu/repository/MenuButtonRepository.kt @@ -0,0 +1,18 @@ +package ru.fredboy.cavedroid.domain.menu.repository + +import com.badlogic.gdx.utils.Disposable +import ru.fredboy.cavedroid.domain.menu.model.MenuButton + +interface MenuButtonRepository : Disposable { + + fun initialize() + + fun getButtonsForMenu(menuKey: String): Map? + + fun setCurrentMenu(menuKey: String) + + fun getCurrentMenuButtons(): Map? + + fun setButtonEnabled(menuKey: String, buttonKey: String, enabled: Boolean) + +} \ No newline at end of file diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/MainConfig.java b/core/src/main/java/ru/deadsoftware/cavedroid/MainConfig.java index 2e40781..4f884c0 100644 --- a/core/src/main/java/ru/deadsoftware/cavedroid/MainConfig.java +++ b/core/src/main/java/ru/deadsoftware/cavedroid/MainConfig.java @@ -1,37 +1,18 @@ package ru.deadsoftware.cavedroid; import org.jetbrains.annotations.Nullable; -import ru.deadsoftware.cavedroid.prefs.PreferencesStore; import javax.inject.Inject; import javax.inject.Singleton; -import java.util.HashMap; @Singleton public class MainConfig { - private final HashMap mPreferencesCache = new HashMap<>(); - - @Nullable - private FullscreenToggleListener mFullscreenToggleListener = null; - - private final CaveGame mCaveGame; - private final PreferencesStore mPreferencesStore; - @Nullable private MainComponent mMainComponent; - @Nullable - private String mAssetsPackPath = null; - @Inject - public MainConfig(CaveGame caveGame, PreferencesStore preferencesStore) { - mCaveGame = caveGame; - mPreferencesStore = preferencesStore; - } - - public CaveGame getCaveGame() { - return mCaveGame; + public MainConfig() { } public MainComponent getMainComponent() { @@ -42,42 +23,4 @@ public class MainConfig { public void setMainComponent(MainComponent mainComponent) { mMainComponent = mainComponent; } - - @Nullable - public String getAssetsPackPath() { - return mAssetsPackPath; - } - - @Nullable - public String getPreference(String key) { - if (mPreferencesCache.containsKey(key)) { - return mPreferencesCache.get(key); - } - - String value = mPreferencesStore.getPreference(key); - mPreferencesCache.put(key, value); - - return value; - } - - public void setPreference(String key, String value) { - mPreferencesCache.put(key, value); - mPreferencesStore.setPreference(key, value); - - if (mFullscreenToggleListener != null && key.equals("fullscreen")) { - mFullscreenToggleListener.onFullscreenToggled(Boolean.parseBoolean(value)); - } - } - - public void setFullscreenToggleListener(@Nullable FullscreenToggleListener fullscreenToggleListener) { - mFullscreenToggleListener = fullscreenToggleListener; - } - - public boolean isUseDynamicCamera() { - return Boolean.parseBoolean(getPreference("dyncam")); - } - - public interface FullscreenToggleListener { - void onFullscreenToggled(boolean value); - } } diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuComponent.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuComponent.java index d7b51dc..9d7bec6 100644 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuComponent.java +++ b/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuComponent.java @@ -2,12 +2,24 @@ package ru.deadsoftware.cavedroid.menu; import dagger.Component; import ru.deadsoftware.cavedroid.MainComponent; +import ru.deadsoftware.cavedroid.generated.module.MenuActionsModule; +import ru.fredboy.cavedroid.common.di.MenuScope; +import ru.fredboy.cavedroid.data.menu.di.DataMenuModule; +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository; import ru.fredboy.cavedroid.game.controller.container.di.ControllerContainerModule; import ru.fredboy.cavedroid.game.controller.drop.di.ControllerDropModule; +import ru.fredboy.cavedroid.zygote.menu.input.MenuInputProcessor; +import ru.fredboy.cavedroid.zygote.menu.renderer.MenuRenderer; +import ru.deadsoftware.cavedroid.generated.module.MenuBooleanOptionsModule; @MenuScope @Component(dependencies = MainComponent.class, modules = {ControllerContainerModule.class, - ControllerDropModule.class}) + ControllerDropModule.class, DataMenuModule.class, MenuBooleanOptionsModule.class, MenuActionsModule.class}) public interface MenuComponent { - MenuProc getMenuProc(); + + public MenuRenderer menuRenderer(); + + public MenuInputProcessor menuInputProcessor(); + + public MenuButtonRepository menuButtonsRepository(); } diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuProc.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuProc.java deleted file mode 100644 index 5449437..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuProc.java +++ /dev/null @@ -1,166 +0,0 @@ -package ru.deadsoftware.cavedroid.menu; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.utils.ObjectMap; -import ru.deadsoftware.cavedroid.CaveGame; -import ru.deadsoftware.cavedroid.MainConfig; -import ru.deadsoftware.cavedroid.menu.objects.Button; -import ru.deadsoftware.cavedroid.menu.submenus.*; -import ru.deadsoftware.cavedroid.misc.Renderer; -import ru.fredboy.cavedroid.common.utils.RenderingUtilsKt; -import ru.fredboy.cavedroid.domain.assets.usecase.GetFontUseCase; -import ru.fredboy.cavedroid.domain.assets.usecase.GetStringHeightUseCase; -import ru.fredboy.cavedroid.domain.assets.usecase.GetStringWidthUseCase; -import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase; -import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository; - -import javax.inject.Inject; - -import java.lang.reflect.Method; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@MenuScope -public class MenuProc extends Renderer { - - public class Input { - private void startNewGame(int gameMode) { - mMainConfig.getCaveGame().newGame(gameMode); - } - - public void newGameClicked() { - mCurrentMenu = mMenuNewGame; - } - - public void loadGameClicked() { - mMainConfig.getCaveGame().loadGame(); - } - - public void optionsClicked() { - mCurrentMenu = mMenuOptions; - } - - public void quitClicked() { - Gdx.app.exit(); - } - - public void survivalClicked() { - startNewGame(0); - } - - public void creativeClicked() { - startNewGame(1); - } - - public void backClicked() { - mCurrentMenu = mMenuMain; - } - - public void setPreference(String key, Object value) { - mMainConfig.setPreference(key, value.toString()); - } - } - - private final MainConfig mMainConfig; - - private final GameContextRepository mGameContextRepository; - - private final MenuMain mMenuMain; - private final MenuNewGame mMenuNewGame; - private final MenuOptions mMenuOptions; - - private final GetFontUseCase mGetFontUseCase; - private final GetStringWidthUseCase mGetStringWidthUseCase; - private final GetStringHeightUseCase mGetStringHeightUseCase; - - private final GetTextureRegionByNameUseCase mGetTextureRegionByNameUseCase; - - private Menu mCurrentMenu; - - @Inject - public MenuProc( - MainConfig mainConfig, - GameContextRepository gameContextRepository, - MenusFactory menusFactory, - GetFontUseCase getFontUseCase, - GetStringWidthUseCase getStringWidthUseCase, - GetStringHeightUseCase getStringHeightUseCase, - GetTextureRegionByNameUseCase getTextureRegionByNameUseCase - ) { - super(gameContextRepository.getWidth(), gameContextRepository.getHeight()); - - mMainConfig = mainConfig; - mGameContextRepository = gameContextRepository; - mGetFontUseCase = getFontUseCase; - mGetStringWidthUseCase = getStringWidthUseCase; - mGetStringHeightUseCase = getStringHeightUseCase; - mGetTextureRegionByNameUseCase = getTextureRegionByNameUseCase; - - Input menuInput = new Input(); - - mMenuMain = menusFactory.getMainMenu(getWidth(), getHeight(), this::drawButton, menuInput); - mMenuNewGame = menusFactory.getMenuNewGame(getWidth(), getHeight(), this::drawButton, menuInput); - mMenuOptions = menusFactory.getMenuOptions(getWidth(), getHeight(), this::drawButton, menuInput); - - mCurrentMenu = mMenuMain; - } - - private String processVariables(String raw) { - final Pattern pattern = Pattern.compile("%%([A-Za-z]+)%%", Pattern.CASE_INSENSITIVE); - final Matcher matcher = pattern.matcher(raw); - while (matcher.find()) { - for (int i = 0; i < matcher.groupCount(); i++) { - try { - final String group = matcher.group(i); - final String name = group.replaceAll("%%", ""); - final Method method = mMainConfig.getClass().getMethod(name); - final String value = method.invoke(mMainConfig).toString(); - raw = raw.replace(group, value); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - return raw; - } - - private void drawButton(Button button) { - spriter.draw(mGetTextureRegionByNameUseCase.get("button_" + button.getType()), button.getX(), button.getY()); - - String label = processVariables(button.getLabel()); - - RenderingUtilsKt.drawString(spriter, mGetFontUseCase.invoke(), label, - (button.getX() + button.getWidth() / 2) - mGetStringWidthUseCase.invoke(label) / 2, - (button.getY() + button.getHeight() / 2) - mGetStringHeightUseCase.invoke(label) / 2); - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int mb) { - screenX *= getWidth() / Gdx.graphics.getWidth(); - screenY *= getHeight() / Gdx.graphics.getHeight(); - for (ObjectMap.Entry entry : mCurrentMenu.getButtons()) { - Button button = entry.value; - if (button.getRect().contains(screenX, screenY)) { - if (button.getType() > 0) { - button.clicked(); - } - break; - } - } - return false; - } - - @Override - public void render(float delta) { - spriter.begin(); - mCurrentMenu.draw(spriter); - RenderingUtilsKt.drawString(spriter, mGetFontUseCase.invoke(), "CaveDroid " + CaveGame.VERSION, 0, - getHeight() - mGetStringHeightUseCase.invoke("CaveDroid " + CaveGame.VERSION) * 1.5f); - spriter.end(); - } - - public void reset() { - mCurrentMenu = mMenuMain; - } -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScope.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScope.java deleted file mode 100644 index 3198af6..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScope.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.deadsoftware.cavedroid.menu; - -import javax.inject.Scope; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Scope -@Retention(RetentionPolicy.RUNTIME) -public @interface MenuScope { -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScreen.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScreen.java index 4b9c5e3..cdb9733 100644 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScreen.java +++ b/core/src/main/java/ru/deadsoftware/cavedroid/menu/MenuScreen.java @@ -3,6 +3,9 @@ package ru.deadsoftware.cavedroid.menu; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; import ru.deadsoftware.cavedroid.MainConfig; +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository; +import ru.fredboy.cavedroid.zygote.menu.input.MenuInputProcessor; +import ru.fredboy.cavedroid.zygote.menu.renderer.MenuRenderer; import javax.inject.Inject; import javax.inject.Singleton; @@ -10,24 +13,34 @@ import javax.inject.Singleton; @Singleton public class MenuScreen implements Screen { - private final MenuProc mMenuProc; + private final MenuRenderer mMenuRenderer; + + private final MenuInputProcessor mMenuInputProcessor; + + private final MenuButtonRepository mMenuButtonsRepository; @Inject public MenuScreen(MainConfig mainConfig) { MenuComponent menuComponent = DaggerMenuComponent.builder() .mainComponent(mainConfig.getMainComponent()).build(); - mMenuProc = menuComponent.getMenuProc(); + + mMenuRenderer = menuComponent.menuRenderer(); + mMenuInputProcessor = menuComponent.menuInputProcessor(); + mMenuButtonsRepository = menuComponent.menuButtonsRepository(); + } + + public void resetMenu() { + mMenuButtonsRepository.setCurrentMenu("main"); } @Override public void show() { - mMenuProc.reset(); - Gdx.input.setInputProcessor(mMenuProc); + Gdx.input.setInputProcessor(mMenuInputProcessor); } @Override public void render(float delta) { - mMenuProc.render(delta); + mMenuRenderer.render(delta); } @Override diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/Button.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/Button.java deleted file mode 100644 index bc78f21..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/Button.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.objects; - -import com.badlogic.gdx.math.Rectangle; - -public class Button { - - public static final int WIDTH = 200; - public static final int HEIGHT = 20; - - public static final int - DISABLED = 0, - NORMAL = 1, - SELECTED = 2; - private final Rectangle rect; - private final String label; - private ButtonEventListener listener; - private int type; - - /** - * @param label Label to be shown on button - * @param type Type of button where 0 - disabled, 1 - normal, 2 - selected. - * You should use these constants - * {@link #DISABLED} {@link #NORMAL} {@link #SELECTED} - */ - public Button(String label, int x, int y, int type, ButtonEventListener listener) { - this.label = label; - rect = new Rectangle(x, y, WIDTH, HEIGHT); - this.type = type; - this.listener = listener; - } - - public Rectangle getRect() { - return rect; - } - - public String getLabel() { - return label; - } - - public float getX() { - return rect.x; - } - - public float getY() { - return rect.y; - } - - public float getWidth() { - return rect.width; - } - - public float getHeight() { - return rect.height; - } - - public int getType() { - return type; - } - - public void setType(int type) { - this.type = type; - } - - public void draw(ButtonRenderer drawer) { - drawer.draw(this); - } - - public void clicked() { - listener.buttonClicked(); - } - -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonEventListener.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonEventListener.java deleted file mode 100644 index 3797295..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonEventListener.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.objects; - -/** - * A {@link Button} event listener. Should be sent as lambda to Button's constructor. - */ -public interface ButtonEventListener { - - /** - * Will be called by {@link Button} when clicked - */ - void buttonClicked(); - -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonRenderer.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonRenderer.java deleted file mode 100644 index 6a429f2..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/objects/ButtonRenderer.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.objects; - -public interface ButtonRenderer { - - void draw(Button button); - -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/Menu.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/Menu.java deleted file mode 100644 index 5f48fa4..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/Menu.java +++ /dev/null @@ -1,152 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.submenus; - -import com.badlogic.gdx.Application; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.utils.ArrayMap; -import com.badlogic.gdx.utils.JsonValue; -import ru.deadsoftware.cavedroid.MainConfig; -import ru.deadsoftware.cavedroid.menu.MenuProc; -import ru.deadsoftware.cavedroid.menu.objects.BooleanOptionButton; -import ru.deadsoftware.cavedroid.menu.objects.Button; -import ru.deadsoftware.cavedroid.menu.objects.ButtonEventListener; -import ru.deadsoftware.cavedroid.menu.objects.ButtonRenderer; -import ru.deadsoftware.cavedroid.misc.Assets; -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader; -import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase; - -import java.util.HashMap; - -public abstract class Menu { - - protected final MainConfig mMainConfig; - protected final MenuProc.Input mMenuInput; - protected final AssetLoader mAssetLoader; - - protected final GetTextureRegionByNameUseCase mGetTextureRegionByNameUseCase; - - private final ButtonRenderer mButtonRenderer; - - private final float mWidth; - private final float mHeight; - - /** - * {@link ArrayMap} of {@link Button Buttons} of this menu screen - */ - private ArrayMap buttons; - - /** - * @param width Viewport width - * @param height Viewport height - * @param buttonRenderer {@link ButtonRenderer} that will draw the buttons of this menu - */ - Menu(float width, - float height, - ButtonRenderer buttonRenderer, - MainConfig mainConfig, - MenuProc.Input menuInput, - AssetLoader assetLoader, - GetTextureRegionByNameUseCase getTextureRegionByNameUseCase) { - mWidth = width; - mHeight = height; - mButtonRenderer = buttonRenderer; - mMainConfig = mainConfig; - mMenuInput = menuInput; - mAssetLoader = assetLoader; - mGetTextureRegionByNameUseCase = getTextureRegionByNameUseCase; - } - - final void init() { - initButtons(); - } - - /** - * If you are loading buttons from json, - * override this method and create a HashMap with buttons' keys from json as keys - * and {@link ButtonEventListener ButtonEventListeners} as values. - * - * @return empty HashMap if not overridden - */ - protected HashMap getButtonEventListeners() { - return new HashMap<>(); - } - - /** - * You can call this from {@link #initButtons()} to load buttons from json - * - * @param jsonFile A {@link FileHandle} to json file - */ - void loadButtonsFromJson(FileHandle jsonFile) { - if (buttons == null) { - buttons = new ArrayMap<>(); - } - HashMap eventListeners = getButtonEventListeners(); - JsonValue json = Assets.jsonReader.parse(jsonFile); - int y = (int) mHeight / 4; - for (JsonValue key = json.child(); key != null; key = key.next(), y += Button.HEIGHT + 10) { - - if (Gdx.app.getType() == Application.ApplicationType.Android && - !Assets.getBooleanFromJson(key, "visible_on_android", true)) { - continue; - } - - String optionType = Assets.getStringFromJson(key, "option_type", ""); - String label = Assets.getStringFromJson(key, "label", ""); - int x = (int) mWidth / 2 - Button.WIDTH / 2; - int type = Assets.getIntFromJson(key, "type", Button.NORMAL); - String defaultValue = Assets.getStringFromJson(key, "default_value", ""); - - - Button button = switch (optionType) { - case "boolean" -> - new BooleanOptionButton(mMainConfig, key.name(), Boolean.parseBoolean(defaultValue), label, x, y, type); - default -> - new Button(label, x, y, type, eventListeners.containsKey(key.name()) ? eventListeners.get(key.name()) : () -> {}); - }; - - buttons.put(key.name(), button); - } - } - - /** - * Draws the menu with background, logo and it's buttons - * - * @param spriter {@link SpriteBatch} that will draw it. Should be already started. - */ - public void draw(SpriteBatch spriter) { - TextureRegion background = mGetTextureRegionByNameUseCase.get("background"); - TextureRegion gamelogo = mGetTextureRegionByNameUseCase.get("gamelogo"); - - for (int x = 0; x <= mWidth / 16; x++) { - for (int y = 0; y <= mHeight / 16; y++) { - spriter.draw(background, x * 16, y * 16); - } - } - spriter.draw(gamelogo, mWidth / 2 - (float) gamelogo.getRegionWidth() / 2, 8); - - float inputX = Gdx.input.getX() * mWidth / Gdx.graphics.getWidth(); - float inputY = Gdx.input.getY() * mHeight / Gdx.graphics.getHeight(); - for (Button button : buttons.values()) { - if (button.getType() > 0) { - if (button.getRect().contains(inputX, inputY) && (/*!CaveGame.TOUCH || */Gdx.input.isTouched())) { - button.setType(2); - } else { - button.setType(1); - } - } - button.draw(mButtonRenderer); - } - } - - public ArrayMap getButtons() { - return buttons; - } - - /** - * This method is called from constructor and should initialize {@link #buttons}
- * You can run {@link #loadButtonsFromJson(FileHandle)} from it - */ - protected abstract void initButtons(); -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuMain.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuMain.java deleted file mode 100644 index 24dc1da..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuMain.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.submenus; - -import ru.deadsoftware.cavedroid.MainConfig; -import ru.deadsoftware.cavedroid.menu.MenuProc; -import ru.deadsoftware.cavedroid.menu.objects.Button; -import ru.deadsoftware.cavedroid.menu.objects.ButtonEventListener; -import ru.deadsoftware.cavedroid.menu.objects.ButtonRenderer; -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader; -import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase; -import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository; -import ru.fredboy.cavedroid.domain.save.repository.SaveDataRepository; - -import java.util.HashMap; - -public class MenuMain extends Menu { - - private final SaveDataRepository mSaveDataRepository; - - private final GameContextRepository mGameContextRepository; - - public MenuMain(float width, - float height, - ButtonRenderer buttonRenderer, - MainConfig mainConfig, - MenuProc.Input menuInput, - AssetLoader assetLoader, - GetTextureRegionByNameUseCase getTextureRegionByNameUseCase, - SaveDataRepository saveDataRepository, - GameContextRepository gameContextRepository) { - super(width, height, buttonRenderer, mainConfig, menuInput, assetLoader, getTextureRegionByNameUseCase); - mSaveDataRepository = saveDataRepository; - mGameContextRepository = gameContextRepository; - } - - @Override - protected HashMap getButtonEventListeners() { - HashMap map = new HashMap<>(); - map.put("new_game", mMenuInput::newGameClicked); - map.put("load_game", mMenuInput::loadGameClicked); - map.put("options", mMenuInput::optionsClicked); - map.put("quit", mMenuInput::quitClicked); - return map; - } - - @Override - protected void initButtons() { - loadButtonsFromJson(mAssetLoader.getAssetHandle("json/menu_main_buttons.json")); - if (mSaveDataRepository.exists(mGameContextRepository.getGameDirectory())) { - getButtons().get("load_game").setType(Button.NORMAL); - } - } - -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuNewGame.java b/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuNewGame.java deleted file mode 100644 index e5ee093..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/menu/submenus/MenuNewGame.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.submenus; - -import ru.deadsoftware.cavedroid.MainConfig; -import ru.deadsoftware.cavedroid.menu.MenuProc; -import ru.deadsoftware.cavedroid.menu.objects.ButtonEventListener; -import ru.deadsoftware.cavedroid.menu.objects.ButtonRenderer; -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader; -import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase; - -import java.util.HashMap; - -public class MenuNewGame extends Menu { - - public MenuNewGame(float width, - float height, - ButtonRenderer buttonRenderer, - MainConfig mainConfig, - MenuProc.Input menuInput, - AssetLoader assetLoader, - GetTextureRegionByNameUseCase getTextureRegionByNameUseCase) { - super(width, height, buttonRenderer, mainConfig, menuInput, assetLoader, getTextureRegionByNameUseCase); - } - - @Override - protected HashMap getButtonEventListeners() { - HashMap map = new HashMap<>(); - map.put("survival", mMenuInput::survivalClicked); - map.put("creative", mMenuInput::creativeClicked); - map.put("back", mMenuInput::backClicked); - return map; - } - - @Override - protected void initButtons() { - loadButtonsFromJson(mAssetLoader.getAssetHandle("json/menu_new_game_buttons.json")); - } - -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/misc/Assets.java b/core/src/main/java/ru/deadsoftware/cavedroid/misc/Assets.java deleted file mode 100644 index 063fe30..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/misc/Assets.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.deadsoftware.cavedroid.misc; - -import com.badlogic.gdx.utils.JsonReader; -import com.badlogic.gdx.utils.JsonValue; - - -public class Assets { - - - public static final JsonReader jsonReader = new JsonReader(); - - - public static int getIntFromJson(JsonValue json, String name, int defaultValue) { - return json.has(name) ? json.getInt(name) : defaultValue; - } - - - public static String getStringFromJson(JsonValue json, String name, String defaultValue) { - return json.has(name) ? json.getString(name) : defaultValue; - } - - public static boolean getBooleanFromJson(JsonValue json, String name, boolean defaultValue) { - return json.has(name) ? json.getBoolean(name) : defaultValue; - } - -} diff --git a/core/src/main/java/ru/deadsoftware/cavedroid/misc/Renderer.java b/core/src/main/java/ru/deadsoftware/cavedroid/misc/Renderer.java deleted file mode 100644 index b74c3bf..0000000 --- a/core/src/main/java/ru/deadsoftware/cavedroid/misc/Renderer.java +++ /dev/null @@ -1,109 +0,0 @@ -package ru.deadsoftware.cavedroid.misc; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.InputProcessor; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; -import com.badlogic.gdx.math.Rectangle; - -public abstract class Renderer implements InputProcessor { - - protected final ShapeRenderer shaper; - protected final SpriteBatch spriter; - private final OrthographicCamera camera; - private final Rectangle mCameraViewport; - - protected Renderer() { - this(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - } - - protected Renderer(float width, float height) { - camera = new OrthographicCamera(); - camera.setToOrtho(true, width, height); - shaper = new ShapeRenderer(); - shaper.setProjectionMatrix(camera.combined); - spriter = new SpriteBatch(); - spriter.setProjectionMatrix(camera.combined); - - mCameraViewport = - new Rectangle(camera.position.x, camera.position.y, camera.viewportWidth, camera.viewportHeight); - } - - public float getWidth() { - return camera.viewportWidth; - } - - public float getHeight() { - return camera.viewportHeight; - } - - public float getCamX() { - return camera.position.x; - } - - public float getCamY() { - return camera.position.y; - } - - public void setCamPos(float x, float y) { - camera.position.set(x, y, 0); - mCameraViewport.x = x; - mCameraViewport.y = y; - } - - public OrthographicCamera getCamera() { - return camera; - } - - public Rectangle getCameraViewport() { - return mCameraViewport; - } - - public abstract void render(float delta); - - @Override - public boolean keyDown(int keycode) { - return false; - } - - @Override - public boolean keyUp(int keycode) { - return false; - } - - @Override - public boolean keyTyped(char character) { - return false; - } - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - return false; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { - return false; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - return false; - } - - @Override - public boolean mouseMoved(int screenX, int screenY) { - return false; - } - - @Override - public boolean scrolled(float amountX, float amountY) { - return false; - } - - @Override - public boolean touchCancelled(int i, int i1, int i2, int i3) { - return false; - } -} diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/CaveGame.kt b/core/src/main/kotlin/ru/deadsoftware/cavedroid/CaveGame.kt index 07c6e8f..7c1fcba 100644 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/CaveGame.kt +++ b/core/src/main/kotlin/ru/deadsoftware/cavedroid/CaveGame.kt @@ -4,8 +4,7 @@ import com.badlogic.gdx.Application import com.badlogic.gdx.Gdx import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.math.Rectangle -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader -import ru.deadsoftware.cavedroid.prefs.PreferencesStore +import ru.fredboy.cavedroid.common.api.PreferencesStore import ru.fredboy.cavedroid.common.utils.ratio import ru.fredboy.cavedroid.domain.configuration.model.CameraContext import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository @@ -22,8 +21,6 @@ class CaveGame( private val mGameContextRepository: GameContextRepository - private val assetLoader: AssetLoader - init { mainComponent = DaggerMainComponent.builder() .caveGame(this) @@ -31,7 +28,6 @@ class CaveGame( .build() mainConfig = mainComponent.mainConfig - assetLoader = mainComponent.assetLoader mGameContextRepository = mainComponent.gameContextRepository } @@ -59,27 +55,31 @@ class CaveGame( } Gdx.app.logLevel = if (isDebug) Application.LOG_DEBUG else Application.LOG_ERROR - - mainConfig.setFullscreenToggleListener { isFullscreen -> - if (isFullscreen) { - Gdx.graphics.setFullscreenMode(Gdx.graphics.displayMode); - } else { - Gdx.graphics.setWindowedMode(width.toInt(), height.toInt()); - } - } } fun newGame(gameMode: Int) { setScreen(mainComponent.gameScreen.apply { newGame(gameMode) }) } - fun loadGame() { + override fun newGameCreative() { + newGame(1) + } + + override fun newGameSurvival() { + newGame(0) + } + + override fun loadGame() { setScreen(mainComponent.gameScreen.apply { loadGame() }) } override fun quitGame() { screen?.dispose() - setScreen(mainComponent.menuScreen) + setScreen(mainComponent.menuScreen.apply { resetMenu() }) + } + + override fun exitGame() { + Gdx.app.exit() } override fun create() { @@ -99,8 +99,6 @@ class CaveGame( companion object { private const val TAG = "CaveGame" private const val DEFAULT_VIEWPORT_WIDTH = 480f - - const val VERSION = "alpha 0.9.2" } } \ No newline at end of file diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/MainComponent.kt b/core/src/main/kotlin/ru/deadsoftware/cavedroid/MainComponent.kt index b528e15..5448118 100644 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/MainComponent.kt +++ b/core/src/main/kotlin/ru/deadsoftware/cavedroid/MainComponent.kt @@ -3,8 +3,7 @@ package ru.deadsoftware.cavedroid import dagger.Component import ru.deadsoftware.cavedroid.game.GameScreen import ru.deadsoftware.cavedroid.menu.MenuScreen -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader -import ru.deadsoftware.cavedroid.prefs.PreferencesStore +import ru.fredboy.cavedroid.common.api.PreferencesStore import ru.fredboy.cavedroid.common.api.GameController import ru.fredboy.cavedroid.data.assets.di.DataAssetsModule import ru.fredboy.cavedroid.data.configuration.di.DataConfigurationModule @@ -31,8 +30,6 @@ interface MainComponent { val mainConfig: MainConfig - val assetLoader: AssetLoader - val initializeAssetsUseCase: InitializeAssetsUseCase val disposeAssetsUseCase: DisposeAssetsUseCase diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/objects/BooleanOptionButton.kt b/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/objects/BooleanOptionButton.kt deleted file mode 100644 index 56329d5..0000000 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/objects/BooleanOptionButton.kt +++ /dev/null @@ -1,29 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.objects - -import ru.deadsoftware.cavedroid.MainConfig - -class BooleanOptionButton( - private val mainConfig: MainConfig, - private val optionKey: String, - private val defaultValue: Boolean, - label: String, - x: Int, - y: Int, - type: Int, -) : Button( - label, - x, - y, - type, - { - val current = (mainConfig.getPreference(optionKey)?.toBooleanStrictOrNull()) ?: defaultValue - mainConfig.setPreference(optionKey, (!current).toString()) - } -) { - - override fun getLabel(): String { - val value = (mainConfig.getPreference(optionKey)?.toBooleanStrictOrNull()) ?: defaultValue - return super.getLabel().replace("%%value%%", value.toString()) - } - -} \ No newline at end of file diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenuOptions.kt b/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenuOptions.kt deleted file mode 100644 index 9ccc019..0000000 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenuOptions.kt +++ /dev/null @@ -1,29 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.submenus - -import ru.deadsoftware.cavedroid.MainConfig -import ru.deadsoftware.cavedroid.menu.MenuProc -import ru.deadsoftware.cavedroid.menu.objects.ButtonEventListener -import ru.deadsoftware.cavedroid.menu.objects.ButtonRenderer -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader -import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase - -class MenuOptions( - width: Float, - height: Float, - buttonRenderer: ButtonRenderer, - mainConfig: MainConfig, - menuInput: MenuProc.Input, - assetLoader: AssetLoader, - getTextureRegionByName: GetTextureRegionByNameUseCase, -) : Menu(width, height, buttonRenderer, mainConfig, menuInput, assetLoader, getTextureRegionByName) { - - override fun getButtonEventListeners(): HashMap { - val map = HashMap() - map["back"] = ButtonEventListener { mMenuInput.backClicked() } - return map - } - - override fun initButtons() { - loadButtonsFromJson(mAssetLoader.getAssetHandle("json/menu_options_buttons.json")) - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenusFactory.kt b/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenusFactory.kt deleted file mode 100644 index 85abca9..0000000 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/menu/submenus/MenusFactory.kt +++ /dev/null @@ -1,75 +0,0 @@ -package ru.deadsoftware.cavedroid.menu.submenus - -import ru.deadsoftware.cavedroid.MainConfig -import ru.deadsoftware.cavedroid.menu.MenuProc -import ru.deadsoftware.cavedroid.menu.MenuScope -import ru.deadsoftware.cavedroid.menu.objects.ButtonRenderer -import ru.deadsoftware.cavedroid.misc.utils.AssetLoader -import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase -import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository -import ru.fredboy.cavedroid.domain.save.repository.SaveDataRepository -import javax.inject.Inject - -@MenuScope -class MenusFactory @Inject constructor( - private val mainConfig: MainConfig, - private val assetLoader: AssetLoader, - private val getTextureRegionByName: GetTextureRegionByNameUseCase, - private val saveDataRepository: SaveDataRepository, - private val gameContextRepository: GameContextRepository, -) { - - fun getMainMenu( - width: Float, - height: Float, - buttonRenderer: ButtonRenderer, - menuInput: MenuProc.Input, - ): MenuMain { - return MenuMain( - width, - height, - buttonRenderer, - mainConfig, - menuInput, - assetLoader, - getTextureRegionByName, - saveDataRepository, - gameContextRepository, - ).apply { init() } - } - - fun getMenuNewGame( - width: Float, - height: Float, - buttonRenderer: ButtonRenderer, - menuInput: MenuProc.Input, - ): MenuNewGame { - return MenuNewGame( - width, - height, - buttonRenderer, - mainConfig, - menuInput, - assetLoader, - getTextureRegionByName - ).apply { init() } - } - - fun getMenuOptions( - width: Float, - height: Float, - buttonRenderer: ButtonRenderer, - menuInput: MenuProc.Input, - ): MenuOptions { - return MenuOptions( - width, - height, - buttonRenderer, - mainConfig, - menuInput, - assetLoader, - getTextureRegionByName - ).apply { init() } - } - -} \ No newline at end of file diff --git a/core/src/main/kotlin/ru/deadsoftware/cavedroid/misc/utils/AssetLoader.kt b/core/src/main/kotlin/ru/deadsoftware/cavedroid/misc/utils/AssetLoader.kt deleted file mode 100644 index 2e82ee1..0000000 --- a/core/src/main/kotlin/ru/deadsoftware/cavedroid/misc/utils/AssetLoader.kt +++ /dev/null @@ -1,26 +0,0 @@ -package ru.deadsoftware.cavedroid.misc.utils - -import com.badlogic.gdx.Gdx -import com.badlogic.gdx.files.FileHandle -import ru.deadsoftware.cavedroid.MainConfig -import java.io.File -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AssetLoader @Inject constructor( - private val mainConfig: MainConfig, -) { - - fun getAssetHandle(path: String): FileHandle { - val texturePackPath = - mainConfig.assetsPackPath?.let { if (!it.endsWith(File.separator)) "$it${File.separator}" else it } - - return if (texturePackPath == null) { - Gdx.files.internal(path) - } else { - Gdx.files.absolute("$texturePackPath$path") - } - } - -} diff --git a/core/zygote/build.gradle.kts b/core/zygote/build.gradle.kts new file mode 100644 index 0000000..26490ee --- /dev/null +++ b/core/zygote/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + kotlin + ksp +} + +java.sourceCompatibility = ApplicationInfo.sourceCompatibility +java.targetCompatibility = ApplicationInfo.sourceCompatibility + +dependencies { + useAutomultibind() + useLibgdx() + useDagger() + + useCommonModule() + useDomainModules() + useEntityModules() + useGameModules() + useUxModules() + + useModule(":core:domain:menu") +} diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/ExitGameAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/ExitGameAction.kt new file mode 100644 index 0000000..c84556c --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/ExitGameAction.kt @@ -0,0 +1,21 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.api.GameController +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(stringKey = ExitGameAction.KEY) +class ExitGameAction @Inject constructor( + private val gameController: GameController, +) : IMenuAction { + + override fun perform() { + gameController.exitGame() + } + + companion object { + const val KEY = "exit_game_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/IMenuAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/IMenuAction.kt new file mode 100644 index 0000000..da754fb --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/IMenuAction.kt @@ -0,0 +1,9 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +interface IMenuAction { + + fun perform() + + fun canPerform(): Boolean = true + +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/LoadGameAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/LoadGameAction.kt new file mode 100644 index 0000000..52d3411 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/LoadGameAction.kt @@ -0,0 +1,29 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.api.GameController +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository +import ru.fredboy.cavedroid.domain.save.repository.SaveDataRepository +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(stringKey = LoadGameAction.KEY) +class LoadGameAction @Inject constructor( + private val gameController: GameController, + private val saveDataRepository: SaveDataRepository, + private val gameContextRepository: GameContextRepository, +) : IMenuAction { + + override fun perform() { + gameController.loadGame() + } + + override fun canPerform(): Boolean { + return saveDataRepository.exists(gameContextRepository.getGameDirectory()) + } + + companion object { + const val KEY = "load_game_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameCreativeAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameCreativeAction.kt new file mode 100644 index 0000000..5e309b4 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameCreativeAction.kt @@ -0,0 +1,21 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.api.GameController +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(stringKey = NewGameCreativeAction.KEY) +class NewGameCreativeAction @Inject constructor( + private val gameController: GameController, +) : IMenuAction { + + override fun perform() { + gameController.newGameCreative() + } + + companion object { + const val KEY = "new_game_creative_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameSurvivalAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameSurvivalAction.kt new file mode 100644 index 0000000..13890bd --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/NewGameSurvivalAction.kt @@ -0,0 +1,21 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.api.GameController +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(stringKey = NewGameSurvivalAction.KEY) +class NewGameSurvivalAction @Inject constructor( + private val gameController: GameController, +) : IMenuAction { + + override fun perform() { + gameController.newGameSurvival() + } + + companion object { + const val KEY = "new_game_survival_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenMainMenuAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenMainMenuAction.kt new file mode 100644 index 0000000..3fc2eaf --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenMainMenuAction.kt @@ -0,0 +1,21 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(OpenMainMenuAction.KEY) +class OpenMainMenuAction @Inject constructor( + private val menuButtonRepository: MenuButtonRepository, +) : IMenuAction { + + override fun perform() { + menuButtonRepository.setCurrentMenu("main") + } + + companion object { + const val KEY = "menu_main_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenNewGameMenuAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenNewGameMenuAction.kt new file mode 100644 index 0000000..7aaafe4 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenNewGameMenuAction.kt @@ -0,0 +1,21 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(OpenNewGameMenuAction.KEY) +class OpenNewGameMenuAction @Inject constructor( + private val menuButtonRepository: MenuButtonRepository, +) : IMenuAction { + + override fun perform() { + menuButtonRepository.setCurrentMenu("new_game") + } + + companion object { + const val KEY = "new_game_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenOptionsMenuAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenOptionsMenuAction.kt new file mode 100644 index 0000000..9cb0490 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/OpenOptionsMenuAction.kt @@ -0,0 +1,21 @@ +package ru.fredboy.cavedroid.zygote.menu.action + +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository +import ru.fredboy.cavedroid.zygote.menu.action.annotation.BindsMenuAction +import javax.inject.Inject + +@MenuScope +@BindsMenuAction(OpenOptionsMenuAction.KEY) +class OpenOptionsMenuAction @Inject constructor( + private val menuButtonRepository: MenuButtonRepository, +) : IMenuAction { + + override fun perform() { + menuButtonRepository.setCurrentMenu("options") + } + + companion object { + const val KEY = "options_action" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/annotation/BindsMenuAction.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/annotation/BindsMenuAction.kt new file mode 100644 index 0000000..1a21e85 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/action/annotation/BindsMenuAction.kt @@ -0,0 +1,12 @@ +package ru.fredboy.cavedroid.zygote.menu.action.annotation + +import ru.fredboy.automultibind.annotations.BindsIntoMapStringKey +import ru.fredboy.cavedroid.common.automultibind.MultibindingConfig +import ru.fredboy.cavedroid.zygote.menu.action.IMenuAction + +@BindsIntoMapStringKey( + interfaceClass = IMenuAction::class, + modulePackage = MultibindingConfig.GENERATED_MODULES_PACKAGE, + moduleName = "MenuActionsModule", +) +annotation class BindsMenuAction(val stringKey: String) diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/input/MenuInputProcessor.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/input/MenuInputProcessor.kt new file mode 100644 index 0000000..b78bc21 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/input/MenuInputProcessor.kt @@ -0,0 +1,120 @@ +package ru.fredboy.cavedroid.zygote.menu.input + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.InputProcessor +import com.badlogic.gdx.math.Rectangle +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository +import ru.fredboy.cavedroid.domain.menu.model.MenuButton +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository +import ru.fredboy.cavedroid.zygote.menu.action.IMenuAction +import ru.fredboy.cavedroid.zygote.menu.option.bool.IMenuBooleanOption +import javax.inject.Inject + +@MenuScope +class MenuInputProcessor @Inject constructor( + private val gameContextRepository: GameContextRepository, + private val menuButtonRepository: MenuButtonRepository, + private val menuButtonActions: Map, + private val menuButtonBooleanOption: Map, +) : InputProcessor { + + override fun touchUp( + screenX: Int, + screenY: Int, + pointer: Int, + button: Int + ): Boolean { + val cameraContext = gameContextRepository.getCameraContext() ?: return false + + val (touchX, touchY) = cameraContext.getViewportCoordinates(screenX, screenY) + + menuButtonRepository.getCurrentMenuButtons()?.values?.forEachIndexed { index, button -> + if (!button.isEnabled) { + return@forEachIndexed + } + + // TODO: Fix magic numbers + val rect = Rectangle( + /* x = */ gameContextRepository.getWidth() / 2 - 100, + /* y = */ gameContextRepository.getHeight() / 4 + index * 30, + /* width = */ 200f, + /* height = */ 20f + ) + + if (rect.contains(touchX, touchY)) { + when (button) { + is MenuButton.Simple -> { + val action = menuButtonActions[button.actionKey] ?: run { + Gdx.app.error(TAG, "Menu handler for action '${button.actionKey}' not found") + return@forEachIndexed + } + + if (action.canPerform()) { + action.perform() + } else { + Gdx.app.debug(TAG, "Can't perform action ${button.actionKey}") + } + } + + is MenuButton.BooleanOption -> { + button.optionKeys.forEach { optionKey -> + menuButtonBooleanOption[optionKey]?.toggleOption() ?: run { + Gdx.app.error(TAG, "Menu option handler for option '$optionKey' not found") + } + } + } + } + + } + } + + return true + } + + override fun keyDown(keycode: Int): Boolean { + return false + } + + override fun keyUp(keycode: Int): Boolean { + return false + } + + override fun keyTyped(character: Char): Boolean { + return false + } + + override fun touchDown( + screenX: Int, + screenY: Int, + pointer: Int, + button: Int + ): Boolean { + return false + } + + override fun touchCancelled( + screenX: Int, + screenY: Int, + pointer: Int, + button: Int + ): Boolean { + return false + } + + override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean { + return false + } + + override fun mouseMoved(screenX: Int, screenY: Int): Boolean { + return false + } + + override fun scrolled(amountX: Float, amountY: Float): Boolean { + return false + } + + companion object { + private const val TAG = "MenuInputProcessor" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/annotation/BindsMenuBooleanOption.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/annotation/BindsMenuBooleanOption.kt new file mode 100644 index 0000000..685caa3 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/annotation/BindsMenuBooleanOption.kt @@ -0,0 +1,12 @@ +package ru.fredboy.cavedroid.zygote.menu.option.annotation + +import ru.fredboy.automultibind.annotations.BindsIntoMapStringKey +import ru.fredboy.cavedroid.common.automultibind.MultibindingConfig +import ru.fredboy.cavedroid.zygote.menu.option.bool.IMenuBooleanOption + +@BindsIntoMapStringKey( + interfaceClass = IMenuBooleanOption::class, + modulePackage = MultibindingConfig.GENERATED_MODULES_PACKAGE, + moduleName = "MenuBooleanOptionsModule", +) +annotation class BindsMenuBooleanOption(val stringKey: String) diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/DynamicCameraMenuBooleanOption.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/DynamicCameraMenuBooleanOption.kt new file mode 100644 index 0000000..2a137f2 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/DynamicCameraMenuBooleanOption.kt @@ -0,0 +1,25 @@ +package ru.fredboy.cavedroid.zygote.menu.option.bool + +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository +import ru.fredboy.cavedroid.zygote.menu.option.annotation.BindsMenuBooleanOption +import javax.inject.Inject + +@MenuScope +@BindsMenuBooleanOption(DynamicCameraMenuBooleanOption.KEY) +class DynamicCameraMenuBooleanOption @Inject constructor( + private val gameContextRepository: GameContextRepository, +) : IMenuBooleanOption { + + override fun getOption(): Boolean { + return gameContextRepository.useDynamicCamera() + } + + override fun toggleOption() { + gameContextRepository.setUseDynamicCamera(!getOption()) + } + + companion object { + const val KEY = "dyncam" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/FullscreenMenuBooleanOption.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/FullscreenMenuBooleanOption.kt new file mode 100644 index 0000000..3036ee0 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/FullscreenMenuBooleanOption.kt @@ -0,0 +1,25 @@ +package ru.fredboy.cavedroid.zygote.menu.option.bool + +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository +import ru.fredboy.cavedroid.zygote.menu.option.annotation.BindsMenuBooleanOption +import javax.inject.Inject + +@MenuScope +@BindsMenuBooleanOption(FullscreenMenuBooleanOption.KEY) +class FullscreenMenuBooleanOption @Inject constructor( + private val gameContextRepository: GameContextRepository, +) : IMenuBooleanOption { + + override fun getOption(): Boolean { + return gameContextRepository.isFullscreen() + } + + override fun toggleOption() { + gameContextRepository.setFullscreen(!getOption()) + } + + companion object { + const val KEY = "fullscreen" + } +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/IMenuBooleanOption.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/IMenuBooleanOption.kt new file mode 100644 index 0000000..ba6e30a --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/option/bool/IMenuBooleanOption.kt @@ -0,0 +1,9 @@ +package ru.fredboy.cavedroid.zygote.menu.option.bool + +interface IMenuBooleanOption { + + fun getOption(): Boolean + + fun toggleOption() + +} \ No newline at end of file diff --git a/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/renderer/MenuRenderer.kt b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/renderer/MenuRenderer.kt new file mode 100644 index 0000000..6d36e45 --- /dev/null +++ b/core/zygote/src/main/kotlin/ru/fredboy/cavedroid/zygote/menu/renderer/MenuRenderer.kt @@ -0,0 +1,155 @@ +package ru.fredboy.cavedroid.zygote.menu.renderer + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.math.Rectangle +import ru.fredboy.cavedroid.common.CaveDroidConstants +import ru.fredboy.cavedroid.common.di.MenuScope +import ru.fredboy.cavedroid.common.utils.drawString +import ru.fredboy.cavedroid.domain.assets.usecase.GetFontUseCase +import ru.fredboy.cavedroid.domain.assets.usecase.GetStringHeightUseCase +import ru.fredboy.cavedroid.domain.assets.usecase.GetStringWidthUseCase +import ru.fredboy.cavedroid.domain.assets.usecase.GetTextureRegionByNameUseCase +import ru.fredboy.cavedroid.domain.configuration.repository.GameContextRepository +import ru.fredboy.cavedroid.domain.menu.model.MenuButton +import ru.fredboy.cavedroid.domain.menu.repository.MenuButtonRepository +import ru.fredboy.cavedroid.zygote.menu.action.IMenuAction +import ru.fredboy.cavedroid.zygote.menu.option.bool.IMenuBooleanOption +import javax.inject.Inject + +@MenuScope +class MenuRenderer @Inject constructor( + private val menuButtonRepository: MenuButtonRepository, + private val gameContextRepository: GameContextRepository, + private val getTextureRegionByName: GetTextureRegionByNameUseCase, + private val menuButtonActions: Map, + private val buttonBooleanOptions: Map, + private val getFont: GetFontUseCase, + private val getStringWidth: GetStringWidthUseCase, + private val getStringHeight: GetStringHeightUseCase, +) { + private val spriter = SpriteBatch() + + init { + val cameraContext = requireNotNull(gameContextRepository.getCameraContext()) { + "$TAG: CameraContext was not set" + } + + spriter.projectionMatrix = cameraContext.camera.combined + } + + private fun getButtonTextureRegionKey(button: MenuButton): String { + val buttonAction = menuButtonActions[button.actionKey] + + if (buttonAction?.canPerform() != true) { + return KEY_BUTTON_DISABLED_TEXTURE + } + + return KEY_BUTTON_ENABLED_TEXTURE.takeIf { button.isEnabled } ?: KEY_BUTTON_DISABLED_TEXTURE + } + + private fun renderButton(button: MenuButton, position: Int) { + val textureRegion = getTextureRegionByName[getButtonTextureRegionKey(button)] ?: run { + Gdx.app.error(TAG, "Couldn't render button because region not found") + return + } + + val label = when (button) { + is MenuButton.Simple -> button.label + is MenuButton.BooleanOption -> String.format( + button.label, + button.optionKeys.map { key -> buttonBooleanOptions[key]?.getOption().toString() } + ) + } + + val buttonX = gameContextRepository.getWidth() / 2 - textureRegion.regionWidth / 2 + val buttonY = gameContextRepository.getHeight() / 4 + position.toFloat() * 30 + + val buttonRect = Rectangle( + /* x = */ buttonX, + /* y = */ buttonY, + /* width = */ textureRegion.regionWidth.toFloat(), + /* height = */ textureRegion.regionHeight.toFloat(), + ) + + val inputCoordinates = gameContextRepository.getCameraContext()?.getViewportCoordinates( + x = Gdx.input.x, + y = Gdx.input.y, + ) + + spriter.draw( + if (button.isEnabled && inputCoordinates != null && buttonRect.contains( + /* x = */ inputCoordinates.first, + /* y = */ inputCoordinates.second + ) + ) { + getTextureRegionByName[KEY_BUTTON_SELECTED_TEXTURE] ?: textureRegion + } else { + textureRegion + }, + /* x = */ buttonX, + /* y = */ buttonY, + ) + + spriter.drawString( + font = getFont(), + str = label, + x = buttonX + textureRegion.regionWidth / 2 - getStringWidth(label) / 2, + y = buttonY + textureRegion.regionHeight / 2 - getStringHeight(label), + ) + } + + private fun drawBackground() { + val backgroundRegion = getTextureRegionByName["background"] ?: return + val gameLogo = getTextureRegionByName["gamelogo"] ?: return + + val backgroundRegionWidth = backgroundRegion.regionWidth + val backgroundRegionHeight = backgroundRegion.regionWidth + + for (x in 0 .. gameContextRepository.getWidth().toInt() / backgroundRegionWidth) { + for (y in 0 .. gameContextRepository.getHeight().toInt() / backgroundRegionHeight) { + spriter.draw( + /* region = */ backgroundRegion, + /* x = */ x * backgroundRegionWidth.toFloat(), + /* y = */ y * backgroundRegionHeight.toFloat(), + ) + } + } + + spriter.draw( + /* region = */ gameLogo, + /* x = */ gameContextRepository.getWidth() / 2 - gameLogo.regionWidth.toFloat() / 2, + /* y = */ 8f, + ) + } + + fun render(delta: Float) { + spriter.begin() + drawBackground() + + menuButtonRepository.getCurrentMenuButtons()?.values + ?.forEachIndexed { position, button -> renderButton(button, position) } + + spriter.drawString( + font = getFont(), + str = "CaveDroid " + CaveDroidConstants.VERSION, + x = 0f, + y = gameContextRepository.getHeight() - getStringHeight("CaveDroid " + CaveDroidConstants.VERSION) * 1.5f, + ); + spriter.end() + + } + + fun dispose() { + spriter.dispose() + } + + companion object { + private const val TAG = "MenuRenderer" + + private const val KEY_BUTTON_SELECTED_TEXTURE = "button_2" + private const val KEY_BUTTON_ENABLED_TEXTURE = "button_1" + private const val KEY_BUTTON_DISABLED_TEXTURE = "button_0" + } + +} \ No newline at end of file diff --git a/desktop/src/main/kotlin/ru/deadsoftware/cavedroid/desktop/DesktopPreferencesStore.kt b/desktop/src/main/kotlin/ru/deadsoftware/cavedroid/desktop/DesktopPreferencesStore.kt index 03591bb..951330b 100644 --- a/desktop/src/main/kotlin/ru/deadsoftware/cavedroid/desktop/DesktopPreferencesStore.kt +++ b/desktop/src/main/kotlin/ru/deadsoftware/cavedroid/desktop/DesktopPreferencesStore.kt @@ -1,6 +1,6 @@ package ru.deadsoftware.cavedroid.desktop -import ru.deadsoftware.cavedroid.prefs.PreferencesStore +import ru.fredboy.cavedroid.common.api.PreferencesStore import java.util.prefs.Preferences class DesktopPreferencesStore : PreferencesStore { diff --git a/settings.gradle.kts b/settings.gradle.kts index e5070d7..f38be29 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,6 +13,7 @@ include("core:common") include("core:data:assets") include("core:data:configuration") include("core:data:items") +include("core:data:menu") include("core:data:save") /** @@ -21,6 +22,7 @@ include("core:data:save") include("core:domain:assets") include("core:domain:configuration") include("core:domain:items") +include("core:domain:menu") include("core:domain:world") include("core:domain:save") @@ -53,3 +55,8 @@ include("core:game:world") include("core:ux:controls") include("core:ux:physics") include("core:ux:rendering") + +/** + * Zygote module: initialization, menu, screens... + */ +include("core:zygote") -- 2.29.2