From 40290b09d50129122ede4ebab695a94ad3f370df Mon Sep 17 00:00:00 2001 From: ThePedroo Date: Sun, 22 Oct 2023 17:47:22 -0300 Subject: [PATCH] add: multi-platform support This commit adds multi-platform support, re-organizing the repository to accept more platforms. --- index.js | 14 +- {src => platforms/android}/achievements.js | 44 +-- {src => platforms/android}/coder.js | 189 ++++------- {src => platforms/android}/items.js | 41 +-- {src => platforms/android}/menu.js | 86 +---- {src => platforms/android}/scene.js | 375 ++------------------- {src => platforms/android}/sub-scene.js | 4 +- platforms/main/achievements.js | 45 +++ platforms/main/coder.js | 80 +++++ {src => platforms/main}/custom.js | 24 +- {src => platforms/main}/helper.js | 18 +- platforms/main/items.js | 48 +++ platforms/main/menu.js | 80 +++++ platforms/main/scene.js | 165 +++++++++ platforms/main/sub-scene.js | 9 + 15 files changed, 571 insertions(+), 651 deletions(-) rename {src => platforms/android}/achievements.js (81%) rename {src => platforms/android}/coder.js (81%) rename {src => platforms/android}/items.js (55%) rename {src => platforms/android}/menu.js (98%) rename {src => platforms/android}/scene.js (86%) rename {src => platforms/android}/sub-scene.js (90%) create mode 100644 platforms/main/achievements.js create mode 100644 platforms/main/coder.js rename {src => platforms/main}/custom.js (92%) rename {src => platforms/main}/helper.js (93%) create mode 100644 platforms/main/items.js create mode 100644 platforms/main/menu.js create mode 100644 platforms/main/scene.js create mode 100644 platforms/main/sub-scene.js diff --git a/index.js b/index.js index 1b4a388..3c21cf0 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,10 @@ -import coder from './src/coder.js' -import scene from './src/scene.js' -import subScene from './src/sub-scene.js' -import menu from './src/menu.js' -import achievements from './src/achievements.js' -import custom from './src/custom.js' -import items from './src/items.js' +import coder from './platforms/main/coder.js' +import scene from './platforms/main/scene.js' +import subScene from './platforms/main/sub-scene.js' +import menu from './platforms/main/menu.js' +import achievements from './platforms/main/achievements.js' +import custom from './platforms/main/custom.js' +import items from './platforms/main/items.js' export default { coder, diff --git a/src/achievements.js b/platforms/android/achievements.js similarity index 81% rename from src/achievements.js rename to platforms/android/achievements.js index 3ad4604..023073b 100644 --- a/src/achievements.js +++ b/platforms/android/achievements.js @@ -1,42 +1,9 @@ /* TODO: Achievements searchs from O(n) to O(1) through objects */ /* TODO: Option for scenes to require an achievement and if not, fallback to another scene */ -import helper from './helper.js' - -function init(options) { - const checks = { - 'id': { - type: 'string', - extraVerification: (param) => { - if (visualNovel.achievements.find((achievement) => achievement.id == param)) - helper.logFatal('An achievement already exists with this id.') - } - }, - 'name': { - type: 'string', - extraVerification: (param) => { - if (visualNovel.achievements.find((achievement) => achievement.name == param)) - helper.logFatal('An achievement already exists with this name.') - } - }, - 'image': { - type: 'fileInitial', - basePath: `${visualNovel.info.paths.android}/app/src/main/res/raw/` - } - } - - helper.verifyParams(checks, options) - - visualNovel.achievements = options || [] -} +import helper from '../main/helper.js' function give(page, achievementId) { - if (!visualNovel.achievements.find((achievement) => achievement.id == achievementId)) - helper.logFatal(`The achievement '${achievementId}' doesn't exist.`) - - if (page.achievements.find((achievement) => achievement.id == achievementId)) - helper.logFatal(`The achievement '${achievementId}' was already given.`) - page.achievements.push({ id: achievementId }) @@ -44,7 +11,7 @@ function give(page, achievementId) { return page } -function _AchievementGiveFunction() { +function _AchievementGive() { return helper.codePrepare(` private fun giveAchievement(${visualNovel.optimizations.hashAchievementIds ? 'achievement: Int' : 'achievement: String, achievementParsed: String'}) { val inputStream = openFileInput("achievements.json") @@ -70,7 +37,7 @@ function _AchievementGiveFunction() { } function _SetAchievementsMenu() { - const menu = visualNovel.menu + const menu = AndroidVisualNovel.menu let achievementsSwitch = helper.codePrepare(` when (achievements.get${visualNovel.optimizations.hashAchievementIds ? 'Int' : 'String'}(i)) { @@ -168,12 +135,11 @@ ${achievementsSwitch} achievementsCode = helper.finalizeMultipleResources(menu, menu.pages.achievements, achievementsCode) - helper.replace('__PERFORVNM_ACHIEVEMENTS_MENU__', achievementsCode) + helper.replace('Android', '__PERFORVNM_ACHIEVEMENTS_MENU__', achievementsCode) } export default { - init, give, - _AchievementGiveFunction, + _AchievementGive, _SetAchievementsMenu } \ No newline at end of file diff --git a/src/coder.js b/platforms/android/coder.js similarity index 81% rename from src/coder.js rename to platforms/android/coder.js index f6a7dbb..eb9b03d 100644 --- a/src/coder.js +++ b/platforms/android/coder.js @@ -2,12 +2,12 @@ import fs from 'fs' -import helper from './helper.js' +import helper from '../main/helper.js' import achievements from './achievements.js' import { _ItemsParsingFunction, _ItemsRestore, _ItemsSaver } from './items.js' -global.visualNovel = { menu: null, info: null, internalInfo: {}, code: '', scenes: [], subScenes: [], achievements: [], items: [], customXML: [], optimizations: {} } +global.AndroidVisualNovel = { menu: null, internalInfo: {}, code: '', scenes: [], subScenes: [], achievements: [], items: [], customXML: [] } global.PerforVNM = { codeGeneratorVersion: '1.23.0', generatedCodeVersion: '1.21.0', @@ -17,71 +17,8 @@ global.PerforVNM = { function init(options) { helper.logOk('Starting VN, coding main code.', 'Android') - const checks = { - 'name': { - type: 'string' - }, - 'fullName': { - type: 'string' - }, - 'version': { - type: 'string' - }, - 'applicationId': { - type: 'string' - }, - 'paths': { - type: 'object', - params: { - 'android': { - type: 'string' - } - } - }, - 'optimizations': { - type: 'object', - params: { - 'reuseResources': { - type: 'boolean', - required: false - }, - 'hashScenesNames': { - type: 'boolean', - required: false - }, - 'hashAchievementIds': { - type: 'boolean', - required: false - }, - 'hashItemsId': { - type: 'boolean', - required: false - }, - 'preCalculateRounding': { - type: 'boolean', - required: false - }, - 'preCalculateScenesInfo': { - type: 'boolean', - required: false - }, - 'minify': { - type: 'boolean', - required: false - } - }, - required: true - } - } - - helper.verifyParams(checks, options) - - if (options.optimizations) visualNovel.optimizations = options.optimizations - - visualNovel.info = options - /* TODO: Only add necessary `import`s */ - visualNovel.code = helper.codePrepare(` + AndroidVisualNovel.code = helper.codePrepare(` package ${options.applicationId} import java.io.File @@ -158,7 +95,7 @@ function init(options) { __PERFORVNM_CLASSES__`, 4 ) - visualNovel.customXML.push({ + AndroidVisualNovel.customXML.push({ path: 'values/strings.xml', content: helper.codePrepare(` @@ -173,7 +110,7 @@ function init(options) { /* TODO: Create functions for stopping the music and sound effects */ function finalize() { - helper.replace('__PERFORVNM_CODE__', '') + helper.replace('Android', '__PERFORVNM_CODE__', '') if (visualNovel.menu.showAchievements) achievements._SetAchievementsMenu() @@ -184,18 +121,18 @@ function finalize() { let savesSwitchCode = '' - if (visualNovel.scenes.length) { + if (AndroidVisualNovel.scenes.length) { let scenesCode = '' - visualNovel.scenes.forEach((scene, i) => { + AndroidVisualNovel.scenes.forEach((scene, i) => { savesSwitchCode += helper.sceneEach(scene) if (scene.next) { - const nextScene = visualNovel.scenes.find((nScene) => nScene.name == scene.next.scene) + const nextScene = AndroidVisualNovel.scenes.find((nScene) => nScene.name == scene.next.scene) const finishScene = [] if (scene.next.item?.require?.fallback) { - const fallbackScene = visualNovel.scenes.find((fScene) => fScene.name == scene.next.item.require.fallback) + const fallbackScene = AndroidVisualNovel.scenes.find((fScene) => fScene.name == scene.next.item.require.fallback) const functionParams = [] if (fallbackScene.speech && !scene.speech) { @@ -236,7 +173,7 @@ function finalize() { if (scene.speech || (scene.effect && scene.effect.delay != 0) || (scene.music && scene.music.delay != 0)) finishScene.push(helper.codePrepare('handler.removeCallbacksAndMessages(null)', 0, 14, false)) - if (i == visualNovel.scenes.length - 2) + if (i == AndroidVisualNovel.scenes.length - 2) finishScene.push(helper.codePrepare('findViewById(android.R.id.content).setOnClickListener(null)', 0, 14, false)) finishScene.push(helper.codePrepare('it.setOnClickListener(null)', 0, 14, false)) @@ -246,8 +183,8 @@ function finalize() { ${finishScene.join('\n')}\n\n`, 8, 0) const functionParams = [] - if (nextScene.speech && i != visualNovel.scenes.length - 2) functionParams.push('true') - if (nextScene.speech?.author?.name && scene.speech && !scene.speech?.author?.name && i + 1 != visualNovel.scenes.length - 1) functionParams.push('true') + if (nextScene.speech && i != AndroidVisualNovel.scenes.length - 2) functionParams.push('true') + if (nextScene.speech?.author?.name && scene.speech && !scene.speech?.author?.name && i + 1 != AndroidVisualNovel.scenes.length - 1) functionParams.push('true') if (scene.speech && !nextScene.speech) { code += helper.codePrepare(` @@ -304,8 +241,8 @@ ${finishScene.join('\n')}\n\n`, 8, 0) scene.code = scene.code.replace(`__PERFORVNM_SCENE_${scene.name.toUpperCase()}__`, code) } else { - const subScene1 = visualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[0].scene) - const subScene2 = visualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[1].scene) + const subScene1 = AndroidVisualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[0].scene) + const subScene2 = AndroidVisualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[1].scene) if (!subScene1 || !subScene2) helper.logFatal('A subscene does not exist.') @@ -380,7 +317,7 @@ ${finishScene.join('\n')}\n\n`, 8, 0) scene.code = scene.code.replace('__PERFORVNM_SPEECH_HANDLER__', speechHandler) } } else { - const oldScene = visualNovel.scenes[i - 1] + const oldScene = AndroidVisualNovel.scenes[i - 1] const functionParams = { function: [], switch: [] } if (scene.speech && !oldScene.speech) { @@ -393,8 +330,8 @@ ${finishScene.join('\n')}\n\n`, 8, 0) } if (scene.subScenes.length != 0) { - const subScene1 = visualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[0].scene) - const subScene2 = visualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[1].scene) + const subScene1 = AndroidVisualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[0].scene) + const subScene2 = AndroidVisualNovel.subScenes.find(subScene => subScene.name == scene.subScenes[1].scene) if (!subScene1 || !subScene2) helper.logFatal('A subscene does not exist.') @@ -449,11 +386,11 @@ ${finishScene.join('\n')}\n\n`, 8, 0) scenesCode += '\n\n' + scene.code }) - visualNovel.subScenes.forEach((scene, i) => { + AndroidVisualNovel.subScenes.forEach((scene, i) => { savesSwitchCode += helper.sceneEach(scene) if (scene.next.scene) { - const nextScene = visualNovel.scenes.find((nScene) => nScene.name == scene.next.scene) + const nextScene = AndroidVisualNovel.scenes.find((nScene) => nScene.name == scene.next.scene) if (!nextScene) helper.logFatal('Next scene does not exist.') @@ -487,7 +424,7 @@ ${finishScene.join('\n')}\n\n`, 8, 0) if (scene.speech || (scene.effect && scene.effect.delay != 0) || (scene.music && scene.music.delay != 0)) finishScene.push(helper.codePrepare('handler.removeCallbacksAndMessages(null)', 0, 12, false)) - if (i == visualNovel.subScenes.length - 2) + if (i == AndroidVisualNovel.subScenes.length - 2) finishScene.push(helper.codePrepare('findViewById(android.R.id.content).setOnClickListener(null)', 0, 12, false)) finishScene.push(helper.codePrepare('it.setOnClickListener(null)', 0, 12, false)) @@ -497,8 +434,8 @@ ${finishScene.join('\n')}\n\n`, 8, 0) ${finishScene.join('\n')}\n\n`, 6, 0) const functionParams = [] - if (nextScene.speech && i != visualNovel.subScenes.length - 2) functionParams.push('true') - if (nextScene.speech?.author?.name && scene.speech && !scene.speech?.author?.name && i + 1 != visualNovel.scenes.length - 1) functionParams.push('true') + if (nextScene.speech && i != AndroidVisualNovel.subScenes.length - 2) functionParams.push('true') + if (nextScene.speech?.author?.name && scene.speech && !scene.speech?.author?.name && i + 1 != AndroidVisualNovel.scenes.length - 1) functionParams.push('true') if (scene.speech && !nextScene.speech) { code += helper.codePrepare(` @@ -584,7 +521,7 @@ ${finishScene.join('\n')}\n\n`, 6, 0) scene.code = scene.code.replace('__PERFORVNM_SPEECH_HANDLER__', speechHandler) } } else { - const oldScene = visualNovel.scenes.find((pScene) => pScene.name == scene.parent) + const oldScene = AndroidVisualNovel.scenes.find((pScene) => pScene.name == scene.parent) if (!oldScene) helper.logFatal('Parent scene does not exist.') @@ -626,7 +563,7 @@ ${finishScene.join('\n')}\n\n`, 6, 0) scenesCode += '\n\n' + scene.code }) - helper.replace('__PERFORVNM_SCENES__', `${scenesCode}__PERFORVNM_SCENES__`) + helper.replace('Android', '__PERFORVNM_SCENES__', `${scenesCode}__PERFORVNM_SCENES__`) } switchesCode += helper.codePrepare(` @@ -634,25 +571,25 @@ ${finishScene.join('\n')}\n\n`, 6, 0) }`, 2, 0, false ) - helper.writeFunction(switchesCode) + helper.writeFunction('Android', switchesCode) if (visualNovel.achievements.length != 0) - helper.writeFunction(achievements._AchievementGiveFunction()) + helper.writeFunction('Android', achievements._AchievementGive()) if (visualNovel.items.length != 0) { - helper.writeFunction(_ItemsParsingFunction()) + helper.writeFunction('Android', _ItemsParsingFunction()) - helper.replace('__PERFORVNM_ITEMS_RESTORE__', _ItemsRestore()) - helper.replace(/__PERFORVNM_ITEMS_SAVER__/g, _ItemsSaver()) + helper.replace('Android', '__PERFORVNM_ITEMS_RESTORE__', _ItemsRestore()) + helper.replace('Android', /__PERFORVNM_ITEMS_SAVER__/g, _ItemsSaver()) } else { - helper.replace('__PERFORVNM_ITEMS_RESTORE__', '') - helper.replace(/__PERFORVNM_ITEMS_SAVER__/g, '') + helper.replace('Android', '__PERFORVNM_ITEMS_RESTORE__', '') + helper.replace('Android', /__PERFORVNM_ITEMS_SAVER__/g, '') } - helper.replace('__PERFORVNM_SCENES__', '') - helper.replace('__PERFORVNM_MENU__', '// No menu created.') - helper.replace('__PERFORVNM_CLASSES__', '') - helper.replace('__PERFORVNM_MULTI_PATH__', visualNovel.scenes.length != 0 ? `scenes.set(0, ${helper.getSceneId(visualNovel.scenes[0].name)})` : '// No scenes created.') + helper.replace('Android', '__PERFORVNM_SCENES__', '') + helper.replace('Android', '__PERFORVNM_MENU__', '// No menu created.') + helper.replace('Android', '__PERFORVNM_CLASSES__', '') + helper.replace('Android', '__PERFORVNM_MULTI_PATH__', AndroidVisualNovel.scenes.length != 0 ? `scenes.set(0, ${helper.getSceneId(AndroidVisualNovel.scenes[0].name)})` : '// No scenes created.') if (!visualNovel.optimizations.preCalculateRounding) { const defaultSaveSwitchCode = helper.codePrepare(` when (characterData.getJSONObject("position").getString("sideType")) { @@ -688,13 +625,13 @@ ${finishScene.join('\n')}\n\n`, 6, 0) } }`, 0, 2) - helper.replace('__PERFORVNM_SAVES_SWITCH__', defaultSaveSwitchCode) - helper.replace('__PERFORVNM_HEADERS__', '\nimport kotlin.math.roundToInt') + helper.replace('Android', '__PERFORVNM_SAVES_SWITCH__', defaultSaveSwitchCode) + helper.replace('Android', '__PERFORVNM_HEADERS__', '\nimport kotlin.math.roundToInt') } else { - helper.replace('__PERFORVNM_SAVES_SWITCH__', helper.sceneEachFinalize(savesSwitchCode)) + helper.replace('Android', '__PERFORVNM_SAVES_SWITCH__', helper.sceneEachFinalize(savesSwitchCode)) } - helper.replace('__PERFORVNM_HEADERS__', '') + helper.replace('Android', '__PERFORVNM_HEADERS__', '') if (visualNovel.menu) { let menuCode = 'buttonStart.setOnClickListener {\n' @@ -721,18 +658,18 @@ ${finishScene.join('\n')}\n\n`, 6, 0) } menuCode += helper.codePrepare(` - ${visualNovel.scenes.length != 0 ? `${visualNovel.scenes[0].name}(${(visualNovel.scenes[0].speech ? 'true' : '')})` : '// No scenes created.'} + ${AndroidVisualNovel.scenes.length != 0 ? `${AndroidVisualNovel.scenes[0].name}(${(AndroidVisualNovel.scenes[0].speech ? 'true' : '')})` : '// No scenes created.'} }`, 2 ) - helper.replace(/__PERFORVNM_MENU_START__/g, menuCode) - helper.replace(/__PERFORVNM_RELEASE_MEDIA_PLAYER__/g, releaseCode) + helper.replace('Android', /__PERFORVNM_MENU_START__/g, menuCode) + helper.replace('Android', /__PERFORVNM_RELEASE_MEDIA_PLAYER__/g, releaseCode) } - helper.replace(/__PERFORVNM_SCENES_LENGTH__/g, visualNovel.scenes.length + visualNovel.subScenes.length) + helper.replace('Android', /__PERFORVNM_SCENES_LENGTH__/g, AndroidVisualNovel.scenes.length + AndroidVisualNovel.subScenes.length) let addHeaders = helper.codePrepare(` - private var scenes = MutableList<${visualNovel.optimizations.hashScenesNames ? 'Int' : 'String'}>(${visualNovel.scenes.length + visualNovel.subScenes.length}) { ${visualNovel.optimizations.hashScenesNames ? '0' : '""'} } + private var scenes = MutableList<${visualNovel.optimizations.hashScenesNames ? 'Int' : 'String'}>(${AndroidVisualNovel.scenes.length + AndroidVisualNovel.subScenes.length}) { ${visualNovel.optimizations.hashScenesNames ? '0' : '""'} } private var scenesLength = 1\n`, 2 ) @@ -741,23 +678,23 @@ ${finishScene.join('\n')}\n\n`, 6, 0) private var items = MutableList<${visualNovel.optimizations.hashItemsId ? 'Int' : 'String'}>(${visualNovel.items.length}) { ${visualNovel.optimizations.hashItemsId ? '0' : '""'} } private var itemsLength = 0\n`, 4) - if (visualNovel.internalInfo.hasSpeech || visualNovel.internalInfo.hasDelayedSoundEffect || visualNovel.internalInfo.hasEffect || visualNovel.internalInfo.hasDelayedMusic || visualNovel.internalInfo.hasDelayedAnimation) + if (AndroidVisualNovel.internalInfo.hasSpeech || AndroidVisualNovel.internalInfo.hasDelayedSoundEffect || AndroidVisualNovel.internalInfo.hasEffect || AndroidVisualNovel.internalInfo.hasDelayedMusic || AndroidVisualNovel.internalInfo.hasDelayedAnimation) addHeaders += helper.codePrepare('private val handler = Handler(Looper.getMainLooper())\n', 0, 2, false) - if (visualNovel.menu || visualNovel.internalInfo.hasSpeech) + if (visualNovel.menu || AndroidVisualNovel.internalInfo.hasSpeech) addHeaders += helper.codePrepare(`private var textSpeed = ${visualNovel.menu?.textSpeed || 1000}L\n`, 0, 2, false) - if (visualNovel.menu || visualNovel.internalInfo.hasEffect) + if (visualNovel.menu || AndroidVisualNovel.internalInfo.hasEffect) addHeaders += helper.codePrepare('private var sEffectVolume = 1f\n', 0, 2, false) - if (visualNovel.menu || visualNovel.internalInfo.hasSceneMusic) + if (visualNovel.menu || AndroidVisualNovel.internalInfo.hasSceneMusic) addHeaders += helper.codePrepare('private var sceneMusicVolume = 1f\n', 0, 2, false) - if (visualNovel.internalInfo.needs2Players) + if (AndroidVisualNovel.internalInfo.needs2Players) addHeaders += helper.codePrepare('private var mediaPlayer2: MediaPlayer? = null\n', 0, 2, false) - if (visualNovel.internalInfo.menuMusic || visualNovel.internalInfo.hasEffect || visualNovel.internalInfo.hasSpeech || visualNovel.internalInfo.hasSceneMusic) { - if (visualNovel.menu?.backgroundMusic || visualNovel.internalInfo.hasEffect) { + if (AndroidVisualNovel.internalInfo.menuMusic || AndroidVisualNovel.internalInfo.hasEffect || AndroidVisualNovel.internalInfo.hasSpeech || AndroidVisualNovel.internalInfo.hasSceneMusic) { + if (visualNovel.menu?.backgroundMusic || AndroidVisualNovel.internalInfo.hasEffect) { addHeaders += helper.codePrepare(` private var mediaPlayer: MediaPlayer? = null @@ -767,7 +704,7 @@ ${finishScene.join('\n')}\n\n`, 6, 0) mediaPlayer?.pause()\n`, 6 ) - if (visualNovel.internalInfo.needs2Players) { + if (AndroidVisualNovel.internalInfo.needs2Players) { addHeaders += helper.codePrepare('mediaPlayer2?.pause()\n', 0, 4, false) } @@ -783,7 +720,7 @@ ${finishScene.join('\n')}\n\n`, 6, 0) }\n`, 6 ) - if (visualNovel.internalInfo.needs2Players) { + if (AndroidVisualNovel.internalInfo.needs2Players) { addHeaders += helper.codePrepare(` if (mediaPlayer2 != null) { mediaPlayer2!!.seekTo(mediaPlayer2!!.getCurrentPosition()) @@ -802,11 +739,11 @@ ${finishScene.join('\n')}\n\n`, 6, 0) super.onDestroy()`, 4 ) - if (visualNovel.internalInfo.hasSpeech || visualNovel.internalInfo.hasEffect) { + if (AndroidVisualNovel.internalInfo.hasSpeech || AndroidVisualNovel.internalInfo.hasEffect) { addHeaders += '\n\n' + helper.codePrepare('handler.removeCallbacksAndMessages(null)', 0, 4, false) } - if (visualNovel.menu?.backgroundMusic || visualNovel.internalInfo.hasEffect) { + if (visualNovel.menu?.backgroundMusic || AndroidVisualNovel.internalInfo.hasEffect) { addHeaders += helper.codePrepare(` if (mediaPlayer != null) { @@ -817,7 +754,7 @@ ${finishScene.join('\n')}\n\n`, 6, 0) ) } - if (visualNovel.internalInfo.needs2Players) { + if (AndroidVisualNovel.internalInfo.needs2Players) { addHeaders += helper.codePrepare(` if (mediaPlayer2 != null) { @@ -831,7 +768,7 @@ ${finishScene.join('\n')}\n\n`, 6, 0) addHeaders += '\n' + helper.codePrepare('}\n', 0, 2, false) } - helper.replace('__PERFORVNM_HEADER__', addHeaders ? '\n' + addHeaders : '') + helper.replace('Android', '__PERFORVNM_HEADER__', addHeaders ? '\n' + addHeaders : '') const startMusicCode = helper.codePrepare(`\n mediaPlayer = MediaPlayer.create(this, R.raw.${visualNovel.menu?.background.music}) @@ -848,15 +785,15 @@ ${finishScene.join('\n')}\n\n`, 6, 0) }`, 0, 2, false ) - helper.replace(/__PERFORVNM_START_MUSIC__/g, startMusicCode) + helper.replace('Android', /__PERFORVNM_START_MUSIC__/g, startMusicCode) - if (visualNovel.optimizations.minify) visualNovel.code = helper.removeAllDoubleLines(visualNovel.code) + if (visualNovel.optimizations.minify) AndroidVisualNovel.code = helper.removeAllDoubleLines(AndroidVisualNovel.code) helper.logOk('Code finished up.', 'Android') let finished = [ false, false ] - fs.writeFile(`${visualNovel.info.paths.android}/app/src/main/java/com/${visualNovel.info.name.toLowerCase()}/MainActivity.kt`, visualNovel.code, (err) => { + fs.writeFile(`${visualNovel.info.paths.android}/app/src/main/java/com/${visualNovel.info.name.toLowerCase()}/MainActivity.kt`, AndroidVisualNovel.code, (err) => { if (err) return helper.logFatal(err) helper.logOk('Visual Novel output code written.', 'Android') @@ -866,9 +803,9 @@ ${finishScene.join('\n')}\n\n`, 6, 0) helper.lastMessage(finished) }) - let i = 0, j = visualNovel.customXML.length - 1 - while (visualNovel.customXML.length > 0) { - const customXML = visualNovel.customXML.shift() + let i = 0, j = AndroidVisualNovel.customXML.length - 1 + while (AndroidVisualNovel.customXML.length > 0) { + const customXML = AndroidVisualNovel.customXML.shift() fs.writeFile(`${visualNovel.info.paths.android}/app/src/main/res/${customXML.path}`, customXML.content, (err) => { if (err) return helper.logFatal(err) diff --git a/src/items.js b/platforms/android/items.js similarity index 55% rename from src/items.js rename to platforms/android/items.js index 3121db4..2f27d57 100644 --- a/src/items.js +++ b/platforms/android/items.js @@ -2,45 +2,9 @@ /* TODO: Cross-saves items */ /* TODO: Option for scenes to require an item and if not, fallback to another scene */ -import helper from './helper.js' - -export function init(options) { - const checks = { - 'id': { - type: 'string', - extraVerification: (param) => { - if (visualNovel.items.find((achievement) => achievement.id == param)) - helper.logFatal('An item already exists with this id.') - } - }, - 'name': { - type: 'string', - extraVerification: (param) => { - if (visualNovel.items.find((item) => item.name == param)) - helper.logFatal('An item already exists with this name.') - } - } - } - - helper.verifyParams(checks, options) - - visualNovel.items = options || [] -} - -export function give(page, itemId) { - const checks = { - 'id': { - type: 'string', - extraVerification: (param) => { - if (!visualNovel.items.find((item) => item.id == param)) - helper.logFatal(`The item '${param}' doesn't exist.`) - - if (page.items.give.find((item) => item.id == param)) - helper.logFatal(`The item '${param}' was already given.`) - } - } - } +import helper from '../main/helper.js' +function give(page, itemId) { page.items.give.push(itemId) return page @@ -85,6 +49,5 @@ export function _ItemsSaver() { } export default { - init, give } \ No newline at end of file diff --git a/src/menu.js b/platforms/android/menu.js similarity index 98% rename from src/menu.js rename to platforms/android/menu.js index 1005250..60494c6 100644 --- a/src/menu.js +++ b/platforms/android/menu.js @@ -1,71 +1,9 @@ /* TODO: Allow to remove footer and add buttons manually */ /* TODO (Critical): Fix saves, if saves topDp > 620 then it will crash the app */ -import helper from './helper.js' +import helper from '../main/helper.js' function init(options) { - const checks = { - 'textColor': { - type: 'string' - }, - 'backTextColor': { - type: 'string' - }, - 'textSpeed': { - type: 'number' - }, - 'aboutText': { - type: 'string' - }, - 'seekBar': { - type: 'object', - params: { - 'backgroundColor': { - type: 'string' - }, - 'progressColor': { - type: 'string' - }, - 'thumbColor': { - type: 'string' - } - } - }, - 'background': { - type: 'object', - params: { - 'image': { - type: 'string' - }, - 'music': { - type: 'string', - required: false - } - } - }, - 'footer': { - type: 'object', - params: { - 'color': { - type: 'string' - }, - 'textColor': { - type: 'string' - }, - 'opacity': { - type: 'number', - min: 0, - max: 1 - } - } - }, - 'showAchievements': { - type: 'boolean' - } - } - - helper.verifyParams(checks, options) - return { ...options, custom: [], @@ -519,7 +457,7 @@ function finalize(menu) { menu()` ) - helper.replace(/__PERFORVNM_MENU__/g, mainCode) + helper.replace('Android', /__PERFORVNM_MENU__/g, mainCode) const sdp30Main = helper.getMultipleResources(menu, menu.pages.main, { type: 'sdp', dp: '30' }) menu.pages.main = helper.addResource(menu.pages.main, { type: 'sdp', dp: '30', spaces: 4 }) @@ -691,7 +629,7 @@ function finalize(menu) { }`, 2 ) - helper.writeFunction(menuCode) + helper.writeFunction('Android', menuCode) const rectangleViewCode = helper.codePrepare(` class RectangleView(context: Context) : View(context) { @@ -712,7 +650,7 @@ function finalize(menu) { }\n`, 4, 0, false ) - helper.replace('__PERFORVNM_CLASSES__', rectangleViewCode) + helper.replace('Android', '__PERFORVNM_CLASSES__', rectangleViewCode) const sdp30About = helper.getMultipleResources(menu, menu.pages.about, { type: 'sdp', dp: '30' }) menu.pages.about = helper.addResource(menu.pages.about, { type: 'sdp', dp: '30', spaces: 4 }) @@ -981,7 +919,7 @@ function finalize(menu) { }`, 2 ) - helper.writeFunction(aboutCode) + helper.writeFunction('Android', aboutCode) const sdp30Settings = helper.getMultipleResources(menu, menu.pages.settings, { type: 'sdp', dp: '30' }) menu.pages.settings = helper.addResource(menu.pages.settings, { type: 'sdp', dp: '30', spaces: 4 }) @@ -1502,9 +1440,9 @@ function finalize(menu) { }`, 2 ) - helper.writeFunction(settingsCode) + helper.writeFunction('Android', settingsCode) - visualNovel.customXML.push({ + AndroidVisualNovel.customXML.push({ path: 'drawable/custom_seekbar_progress.xml', content: helper.codePrepare(` @@ -1526,7 +1464,7 @@ function finalize(menu) { ) }) - visualNovel.customXML.push({ + AndroidVisualNovel.customXML.push({ path: 'drawable/custom_seekbar_thumb.xml', content: helper.codePrepare(` @@ -1887,7 +1825,7 @@ __PERFORVNM_SAVES_SWITCH__ }`, 2 ) - helper.writeFunction(saverCode) + helper.writeFunction('Android', saverCode) if (menu.showAchievements) { const sdp30Achievements = helper.getMultipleResources(menu, menu.pages.achievements, { type: 'sdp', dp: '30' }) @@ -2109,10 +2047,10 @@ __PERFORVNM_SAVES_SWITCH__ }`, 4 ) - helper.writeFunction(achievementsCode) + helper.writeFunction('Android', achievementsCode) } - visualNovel.menu = menu + AndroidVisualNovel.menu = menu helper.logOk('Main, about, settings and saves menu coded.', 'Android') } @@ -2120,4 +2058,4 @@ __PERFORVNM_SAVES_SWITCH__ export default { init, finalize -} +} \ No newline at end of file diff --git a/src/scene.js b/platforms/android/scene.js similarity index 86% rename from src/scene.js rename to platforms/android/scene.js index 64cc557..68d97d4 100644 --- a/src/scene.js +++ b/platforms/android/scene.js @@ -1,7 +1,7 @@ /* TODO: Scenes searchs from O(n) to O(1) through objects */ /* TODO (unconfirmed): Set the scenes in order through a queue [ 'scene1', 'scene2', ... ] */ -import helper from './helper.js' +import helper from '../main/helper.js' import { _ItemGive, _ItemRemove } from './items.js' @@ -11,7 +11,7 @@ function init(options) { type: 'string', notValues: ['onCreate', 'onDestroy', 'onResume', 'onPause', 'menu', 'about', 'settings', 'saves'], extraVerification: (param) => { - if (visualNovel.scenes.find((scene) => scene.name == param)) + if (AndroidVisualNovel.scenes.find((scene) => scene.name == param)) helper.logFatal('A scene already exists with this name.') } }, @@ -148,7 +148,7 @@ function addCharacter(scene, options) { }, extraVerification: (param) => { if (param.delay != 0) - visualNovel.internalInfo.hasDelayedAnimation = true + AndroidVisualNovel.internalInfo.hasDelayedAnimation = true }, required: false } @@ -162,85 +162,21 @@ function addCharacter(scene, options) { } function addScenario(scene, options) { - const checks = { - 'image': { - type: 'fileInitial', - basePath: `${visualNovel.info.paths.android}/app/src/main/res/raw/` - } - } - - helper.verifyParams(checks, options) - scene.background = options.image return scene } function addSpeech(scene, options) { - const checks = { - 'author': { - type: 'object', - params: { - 'name': { - type: 'string' - }, - 'textColor': { - type: 'string' - }, - 'rectangle': { - type: 'object', - params: { - 'color': { - type: 'string' - }, - 'opacity': { - type: 'number' - } - } - } - } - }, - 'text': { - type: 'object', - params: { - 'content': { - type: 'string' - }, - 'color': { - type: 'string' - }, - 'fontSize': { - type: 'number' - }, - 'rectangle': { - type: 'object', - params: { - 'color': { - type: 'string' - }, - 'opacity': { - type: 'number' - } - } - } - } - } - } - - helper.verifyParams(checks, options) - scene.speech = options scene.speech.text.content = JSON.stringify(options.text.content).slice(1, -1) - visualNovel.internalInfo.hasSpeech = true + AndroidVisualNovel.internalInfo.hasSpeech = true return scene } function addSoundEffects(scene, options) { - if (!Array.isArray(options)) - helper.logFatal('Sound effects must be an array.') - const checks = { 'sound': { type: 'fileInitial', @@ -250,7 +186,7 @@ function addSoundEffects(scene, options) { type: 'number', extraVerification: (param) => { if (param != 0) - visualNovel.internalInfo.hasDelayedSoundEffect = true + AndroidVisualNovel.internalInfo.hasDelayedSoundEffect = true }, required: false } @@ -260,7 +196,7 @@ function addSoundEffects(scene, options) { scene.effect = options - visualNovel.internalInfo.hasEffect = true + AndroidVisualNovel.internalInfo.hasEffect = true return scene } @@ -275,7 +211,7 @@ function addMusic(scene, options) { type: 'number', extraVerification: (param) => { if (param != 0) - visualNovel.internalInfo.hasDelayedMusic = true + AndroidVisualNovel.internalInfo.hasDelayedMusic = true }, required: false } @@ -285,63 +221,18 @@ function addMusic(scene, options) { scene.music = options - visualNovel.internalInfo.hasSceneMusic = true + AndroidVisualNovel.internalInfo.hasSceneMusic = true return scene } function addTransition(scene, options) { - const checks = { - 'duration': { - type: 'number' - } - } - - helper.verifyParams(checks, options) - scene.transition = options return scene } function setNextScene(scene, options) { - const checks = { - 'scene': { - type: 'string' - }, - 'item': { - type: 'object', - required: false, - params: { - 'require': { - type: 'object', - params: { - 'id': { - type: 'string', - extraVerification: (param) => { - if (!visualNovel.items.find((item) => item.id == param)) - helper.logFatal(`The item '${param}' doesn't exist.`) - } - }, - 'fallback': { - type: 'string', - } - } - }, - 'remove': { - type: 'boolean', - required: false, - extraVerification: (param, additionalinfo) => { - if (param && !additionalinfo.parent?.require?.id) - helper.logFatal('You must specify an item to be removed once used.') - } - } - } - } - } - - helper.verifyParams(checks, options) - scene.next = options return scene @@ -376,7 +267,7 @@ function addSubScenes(scene, options) { 'scene': { type: 'string', extraVerification: (param) => { - if (visualNovel.subScenes.find((subScene) => subScene.name == param)) + if (AndroidVisualNovel.subScenes.find((subScene) => subScene.name == param)) helper.logFatal('A sub-scene already exists with this name.') } } @@ -389,214 +280,6 @@ function addSubScenes(scene, options) { return scene } -function addCustomText(scene, options) { - const checks = { - 'text': { - type: 'string' - }, - 'color': { - type: 'string' - }, - 'fontSize': { - type: 'number' - }, - 'position': { - type: 'object', - params: { - 'side': { - type: 'string', - values: [ 'center', 'left', 'right' ] - }, - 'margins': { - type: 'object', - params: { - 'side': { - type: 'number' - }, - 'top': { - type: 'number' - } - } - } - } - } - } - - helper.verifyParams(checks, options) - - scene.custom.push({ - type: 'text', - ...options - }) - - return scene -} - -function addCustomButton(scene, options) { - const checks = { - 'text': { - type: 'string' - }, - 'color': { - type: 'string' - }, - 'fontSize': { - type: 'number' - }, - 'height': { - type: [ 'number', 'string' ], - shouldCheckValues: (value) => { - return typeof value != 'number' - }, - values: [ 'match', 'wrap' ] - }, - 'width': { - type: [ 'number', 'string' ], - shouldCheckValues: (value) => { - return typeof value != 'number' - }, - values: [ 'match', 'wrap' ] - }, - 'position': { - type: 'object', - params: { - 'side': { - type: 'string', - values: [ 'center', 'left', 'right' ] - }, - 'margins': { - type: 'object', - params: { - 'side': { - type: 'number' - }, - 'top': { - type: 'number' - } - } - } - } - } - } - - helper.verifyParams(checks, options) - - scene.custom.push({ - type: 'button', - ...options - }) - - return scene -} - -function addCustomRectangle(scene, options) { - const checks = { - 'color': { - type: 'string' - }, - 'opacity': { - type: 'number', - min: 0, - max: 1 - }, - 'height': { - type: [ 'number', 'string' ], - shouldCheckValues: (value) => { - return typeof value != 'number' - }, - values: [ 'match', 'wrap' ] - }, - 'width': { - type: [ 'number', 'string' ], - shouldCheckValues: (value) => { - return typeof value != 'number' - }, - values: [ 'match', 'wrap' ] - }, - 'position': { - type: 'object', - params: { - 'side': { - type: 'string', - values: [ 'center', 'left', 'right' ] - }, - 'margins': { - type: 'object', - params: { - 'side': { - type: 'number' - }, - 'top': { - type: 'number' - } - } - } - } - } - } - - helper.verifyParams(checks, options) - - scene.custom.push({ - type: 'rectangle', - ...options - }) - - return scene -} - -function addCustomImage(scene, options) { - const checks = { - 'image': { - type: 'fileInitial', - basePath: `${visualNovel.info.paths.android}/app/src/main/res/raw/` - }, - 'height': { - type: [ 'number', 'string' ], - shouldCheckValues: (value) => { - return typeof value != 'number' - }, - values: [ 'match', 'wrap' ] - }, - 'width': { - type: [ 'number', 'string' ], - shouldCheckValues: (value) => { - return typeof value != 'number' - }, - values: [ 'match', 'wrap' ] - }, - 'position': { - type: 'object', - params: { - 'side': { - type: 'string', - values: [ 'center', 'left', 'right' ] - }, - 'margins': { - type: 'object', - params: { - 'side': { - type: 'number' - }, - 'top': { - type: 'number' - } - } - } - } - } - } - - helper.verifyParams(checks, options) - - scene.custom.push({ - type: 'image', - ...options - }) - - return scene -} - function finalize(scene) { let sceneCode = helper.codePrepare(` private fun ${scene.name}(__PERFORVNM_SCENE_PARAMS__) { @@ -881,15 +564,15 @@ function finalize(scene) { rectangleViewSpeech.layoutParams = layoutParamsRectangleSpeech\n`, 2, 0, false ) - const oldScene = visualNovel.subScenes.find((subScene) => subScene.next.scene == scene.name) || visualNovel.scenes[visualNovel.scenes.length - 1] + const oldScene = AndroidVisualNovel.subScenes.find((subScene) => subScene.next.scene == scene.name) || AndroidVisualNovel.scenes[AndroidVisualNovel.scenes.length - 1] - if (visualNovel.scenes.length != 0 && oldScene.speech) { + if (AndroidVisualNovel.scenes.length != 0 && oldScene.speech) { sceneCode += helper.codePrepare(`rectangleViewSpeech.setAlpha(${scene.speech.text.rectangle.opacity}f)\n`, 0, 4, false) } sceneCode += helper.codePrepare(`rectangleViewSpeech.setColor(0xFF${scene.speech.text.rectangle.color}.toInt())\n`, 0, 4, false) - if (visualNovel.scenes.length == 0 || !oldScene.speech) { + if (AndroidVisualNovel.scenes.length == 0 || !oldScene.speech) { sceneCode += helper.codePrepare(` if (animate) { val animationRectangleSpeech = AlphaAnimation(0f, ${scene.speech.text.rectangle.opacity}f) @@ -941,13 +624,13 @@ function finalize(scene) { rectangleViewAuthor.layoutParams = layoutParamsRectangleAuthor\n`, 2 ) - if (visualNovel.scenes.length != 0 && oldScene.speech) { + if (AndroidVisualNovel.scenes.length != 0 && oldScene.speech) { sceneCode += helper.codePrepare(`rectangleViewAuthor.setAlpha(${scene.speech.author.rectangle.opacity}f)\n`, 0, 4, false) } sceneCode += helper.codePrepare(`rectangleViewAuthor.setColor(0xFF${scene.speech.author.rectangle.color}.toInt())\n\n`, 0, 4, false) - if (visualNovel.scenes.length == 0 || !oldScene.speech) { + if (AndroidVisualNovel.scenes.length == 0 || !oldScene.speech) { sceneCode += helper.codePrepare(` if (animate) { val animationRectangleAuthor = AlphaAnimation(0f, ${scene.speech.author.rectangle.opacity}f) @@ -989,17 +672,17 @@ function finalize(scene) { textViewAuthor.layoutParams = layoutParamsAuthor\n\n`, 4, 0, false ) - const oldScene = visualNovel.subScenes.find((subScene) => subScene.next.scene == scene.name) || visualNovel.scenes[visualNovel.scenes.length - 1] + const oldScene = AndroidVisualNovel.subScenes.find((subScene) => subScene.next.scene == scene.name) || AndroidVisualNovel.scenes[AndroidVisualNovel.scenes.length - 1] if ( - visualNovel.scenes.length == 0 || + AndroidVisualNovel.scenes.length == 0 || !oldScene.speech || - (visualNovel.scenes.length != 0 && + (AndroidVisualNovel.scenes.length != 0 && scene.speech?.author?.name && oldScene.speech && !oldScene.speech?.author?.name) ) { - if (visualNovel.scenes.length != 0 && scene.speech?.author?.name && oldScene.speech && !oldScene.speech?.author?.name) { + if (AndroidVisualNovel.scenes.length != 0 && scene.speech?.author?.name && oldScene.speech && !oldScene.speech?.author?.name) { sceneCode += helper.codePrepare('if (animateAuthor) {', 0, 4, false) } else { sceneCode += helper.codePrepare('if (animate) {', 0, 4, false) @@ -1301,7 +984,7 @@ ${finishScene.join('\n\n')}__PERFORVNM_START_MUSIC__\n\n`, 4 frameLayout.addView(buttonMenu)\n\n` ) - if (visualNovel.scenes.length != 0) { + if (AndroidVisualNovel.scenes.length != 0) { const sdp46 = helper.getResource(scene, { type: 'sdp', dp: '46' }) scene = helper.addResource(scene, { type: 'sdp', dp: '46', spaces: 4 }) @@ -1328,9 +1011,9 @@ ${finishScene.join('\n\n')}__PERFORVNM_START_MUSIC__\n\n`, 4 ${finishScene.join('\n\n')}${itemRemover.join('\n\n')}\n\n`, 4 ) - let oldScene = visualNovel.subScenes.find((subScene) => subScene.next.scene == scene.name) + let oldScene = AndroidVisualNovel.subScenes.find((subScene) => subScene.next.scene == scene.name) - if (oldScene || visualNovel.scenes.find((cScene) => scene.name == cScene.next?.item?.require?.fallback) || visualNovel.subScenes.find((cScene) => scene.name == cScene.next?.item?.require?.fallback)) { + if (oldScene || AndroidVisualNovel.scenes.find((cScene) => scene.name == cScene.next?.item?.require?.fallback) || AndroidVisualNovel.subScenes.find((cScene) => scene.name == cScene.next?.item?.require?.fallback)) { sceneCode += helper.codePrepare(` val scene = scenes.get(scenesLength - 1) @@ -1340,17 +1023,17 @@ ${finishScene.join('\n\n')}${itemRemover.join('\n\n')}\n\n`, 4 switchScene(scene)\n`, 2 ) } else { - oldScene = visualNovel.scenes[visualNovel.scenes.length - 1] + oldScene = AndroidVisualNovel.scenes[AndroidVisualNovel.scenes.length - 1] const functionParams = [] - const olderOldScene = visualNovel.subScenes.find((subScene) => subScene.next.scene == oldScene.name) + const olderOldScene = AndroidVisualNovel.subScenes.find((subScene) => subScene.next.scene == oldScene.name) if (olderOldScene) { if (olderOldScene.speech && oldScene.speech) functionParams.push('false') if (olderOldScene.speech?.author?.name && olderOldScene.speech && !olderOldScene.speech?.author?.name) functionParams.push('false') } - if (visualNovel.scenes.length == 1) { + if (AndroidVisualNovel.scenes.length == 1) { sceneCode += helper.codePrepare(`${oldScene.name}(${functionParams.join(', ')})\n`, 0, 6, false) } else { sceneCode += helper.codePrepare(` @@ -1396,7 +1079,7 @@ ${finishScene.join('\n\n')}${itemRemover.join('\n\n')}\n\n`, 4 const functionParams = [] if (scene.subScenes[0].speech && !scene.speech) functionParams.push('true') - if (scene.subScenes[0].speech?.author?.name && scene.speech && !scene.speech?.author?.name && i + 1 != visualNovel.scenes.length - 1) functionParams.push('true') + if (scene.subScenes[0].speech?.author?.name && scene.speech && !scene.speech?.author?.name && i + 1 != AndroidVisualNovel.scenes.length - 1) functionParams.push('true') const sdp150 = helper.getResource(scene, { type: 'sdp', dp: '150' }) scene = helper.addResource(scene, { type: 'sdp', dp: '150', spaces: 4 }) @@ -1886,8 +1569,8 @@ ${nextCode} sceneCode = helper.finalizeResources(scene, sceneCode) - if (scene.type == 'normal') visualNovel.scenes.push({ ...scene, code: sceneCode }) - else visualNovel.subScenes.push({ ...scene, code: sceneCode }) + if (scene.type == 'normal') AndroidVisualNovel.scenes.push({ ...scene, code: sceneCode }) + else AndroidVisualNovel.subScenes.push({ ...scene, code: sceneCode }) helper.logOk(`Scene "${scene.name}" coded.`, 'Android') } @@ -1902,9 +1585,5 @@ export default { addTransition, setNextScene, addSubScenes, - addCustomText, - addCustomButton, - addCustomRectangle, - addCustomImage, finalize } diff --git a/src/sub-scene.js b/platforms/android/sub-scene.js similarity index 90% rename from src/sub-scene.js rename to platforms/android/sub-scene.js index ce0fa5a..33da45e 100644 --- a/src/sub-scene.js +++ b/platforms/android/sub-scene.js @@ -1,6 +1,6 @@ /* TODO: Sub-scene searchs from O(n) to O(1) through objects */ -import helper from './helper.js' +import helper from '../main/helper.js' function init(options) { const checks = { @@ -8,7 +8,7 @@ function init(options) { type: 'string', notValues: ['onCreate', 'onDestroy', 'onResume', 'onPause', 'menu', 'about', 'settings', 'saves'], extraVerification: (param) => { - if (visualNovel.subScenes.find((subScene) => subScene.name == param)) + if (AndroidVisualNovel.subScenes.find((subScene) => subScene.name == param)) helper.logFatal('A scene already exists with this name.') } }, diff --git a/platforms/main/achievements.js b/platforms/main/achievements.js new file mode 100644 index 0000000..5e6f936 --- /dev/null +++ b/platforms/main/achievements.js @@ -0,0 +1,45 @@ +import androidAchievements from '../android/achievements.js' + +import helper from './helper.js' + +function init(options) { + const checks = { + 'id': { + type: 'string', + extraVerification: (param) => { + if (visualNovel.achievements.find((achievement) => achievement.id == param)) + helper.logFatal('An achievement already exists with this id.') + } + }, + 'name': { + type: 'string', + extraVerification: (param) => { + if (visualNovel.achievements.find((achievement) => achievement.name == param)) + helper.logFatal('An achievement already exists with this name.') + } + }, + 'image': { + type: 'fileInitial', + basePath: `${visualNovel.info.paths.android}/app/src/main/res/raw/` + } + } + + helper.verifyParams(checks, options) + + visualNovel.achievements = options || [] +} + +function give(page, achievementId) { + if (!visualNovel.achievements.find((achievement) => achievement.id == achievementId)) + helper.logFatal(`The achievement '${achievementId}' doesn't exist.`) + + if (page.achievements.find((achievement) => achievement.id == achievementId)) + helper.logFatal(`The achievement '${achievementId}' was already given.`) + + return androidAchievements.give(page, achievementId) +} + +export default { + init, + give +} \ No newline at end of file diff --git a/platforms/main/coder.js b/platforms/main/coder.js new file mode 100644 index 0000000..34e37b0 --- /dev/null +++ b/platforms/main/coder.js @@ -0,0 +1,80 @@ +import androidCoder from '../android/coder.js' + +global.visualNovel = { info: null, achievements: [], items: [], optimizations: {} } + +import helper from './helper.js' + +function init(options) { + const checks = { + 'name': { + type: 'string' + }, + 'fullName': { + type: 'string' + }, + 'version': { + type: 'string' + }, + 'applicationId': { + type: 'string' + }, + 'paths': { + type: 'object', + params: { + 'android': { + type: 'string' + } + } + }, + 'optimizations': { + type: 'object', + params: { + 'reuseResources': { + type: 'boolean', + required: false + }, + 'hashScenesNames': { + type: 'boolean', + required: false + }, + 'hashAchievementIds': { + type: 'boolean', + required: false + }, + 'hashItemsId': { + type: 'boolean', + required: false + }, + 'preCalculateRounding': { + type: 'boolean', + required: false + }, + 'preCalculateScenesInfo': { + type: 'boolean', + required: false + }, + 'minify': { + type: 'boolean', + required: false + } + }, + required: true + } + } + + helper.verifyParams(checks, options) + + visualNovel.info = options + if (options.optimizations) visualNovel.optimizations = options.optimizations + + androidCoder.init(options) +} + +function finalize() { + androidCoder.finalize() +} + +export default { + init, + finalize +} \ No newline at end of file diff --git a/src/custom.js b/platforms/main/custom.js similarity index 92% rename from src/custom.js rename to platforms/main/custom.js index 4e84929..dcb6dfc 100644 --- a/src/custom.js +++ b/platforms/main/custom.js @@ -1,6 +1,6 @@ import helper from './helper.js' -function addCustomText(menu, options) { +function addCustomText(page, options) { const checks = { 'text': { type: 'string' @@ -35,15 +35,15 @@ function addCustomText(menu, options) { helper.verifyParams(checks, options) - menu.custom.push({ + page.custom.push({ type: 'text', ...options }) - return menu + return page } -function addCustomButton(menu, options) { +function addCustomButton(page, options) { const checks = { 'text': { type: 'string' @@ -92,15 +92,15 @@ function addCustomButton(menu, options) { helper.verifyParams(checks, options) - menu.custom.push({ + page.custom.push({ type: 'button', ...options }) - return menu + return page } -function addCustomRectangle(menu, options) { +function addCustomRectangle(page, options) { const checks = { 'color': { type: 'string' @@ -148,15 +148,15 @@ function addCustomRectangle(menu, options) { helper.verifyParams(checks, options) - menu.custom.push({ + page.custom.push({ type: 'rectangle', ...options }) - return menu + return page } -function addCustomImage(menu, options) { +function addCustomImage(page, options) { const checks = { 'image': { type: 'fileInitial', @@ -200,12 +200,12 @@ function addCustomImage(menu, options) { helper.verifyParams(checks, options) - menu.custom.push({ + page.custom.push({ type: 'image', ...options }) - return menu + return page } export default { diff --git a/src/helper.js b/platforms/main/helper.js similarity index 93% rename from src/helper.js rename to platforms/main/helper.js index bcb012d..527b651 100644 --- a/src/helper.js +++ b/platforms/main/helper.js @@ -3,14 +3,24 @@ import fs from 'fs' -function writeFunction(sceneCode) { +function writeFunction(platform, sceneCode) { const writenCode = `\n\n${sceneCode}__PERFORVNM_SCENES__` - visualNovel.code = visualNovel.code.replace('__PERFORVNM_SCENES__', writenCode) + switch (platform) { + case 'Android': AndroidVisualNovel.code = AndroidVisualNovel.code.replace('__PERFORVNM_SCENES__', writenCode); break; + // case 'iOS': iOSVisualNovel.code = iOSVisualNovel.code.replace('__PERFORVNM_SCENES__', writenCode); break; + // case 'Web': WebVisualNovel.code = WebVisualNovel.code.replace('__PERFORVNM_SCENES__', writenCode); break; + // case 'Desktop': DesktopVisualNovel.code = DesktopVisualNovel.code.replace('__PERFORVNM_SCENES__', writenCode); break; + } } -function replace(header, content) { - visualNovel.code = visualNovel.code.replace(header, content) +function replace(platform, header, content) { + switch (platform) { + case 'Android': AndroidVisualNovel.code = AndroidVisualNovel.code.replace(header, content); break; + // case 'iOS': iOSVisualNovel.code = iOSVisualNovel.code.replace(header, content); break; + // case 'Web': WebVisualNovel.code = WebVisualNovel.code.replace(header, content); break; + // case 'Desktop': DesktopVisualNovel.code = DesktopVisualNovel.code.replace(header, content); break; + } } function makeLog(message) { diff --git a/platforms/main/items.js b/platforms/main/items.js new file mode 100644 index 0000000..eeb81fe --- /dev/null +++ b/platforms/main/items.js @@ -0,0 +1,48 @@ +import androidItems from '../android/items.js' + +import helper from './helper.js' + +function init(options) { + const checks = { + 'id': { + type: 'string', + extraVerification: (param) => { + if (visualNovel.items.find((achievement) => achievement.id == param)) + helper.logFatal('An item already exists with this id.') + } + }, + 'name': { + type: 'string', + extraVerification: (param) => { + if (visualNovel.items.find((item) => item.name == param)) + helper.logFatal('An item already exists with this name.') + } + } + } + + helper.verifyParams(checks, options) + + visualNovel.items = options || [] +} + +function give(page, itemId) { + const checks = { + 'id': { + type: 'string', + extraVerification: (param) => { + if (!visualNovel.items.find((item) => item.id == param)) + helper.logFatal(`The item '${param}' doesn't exist.`) + + if (page.items.give.find((item) => item.id == param)) + helper.logFatal(`The item '${param}' was already given.`) + } + } + } + + return androidItems.give(page, itemId) +} + +export default { + init, + give +} \ No newline at end of file diff --git a/platforms/main/menu.js b/platforms/main/menu.js new file mode 100644 index 0000000..7ce1dfa --- /dev/null +++ b/platforms/main/menu.js @@ -0,0 +1,80 @@ +import androdMenu from '../android/menu.js' + +import helper from './helper.js' + +function init(options) { + const checks = { + 'textColor': { + type: 'string' + }, + 'backTextColor': { + type: 'string' + }, + 'textSpeed': { + type: 'number' + }, + 'aboutText': { + type: 'string' + }, + 'seekBar': { + type: 'object', + params: { + 'backgroundColor': { + type: 'string' + }, + 'progressColor': { + type: 'string' + }, + 'thumbColor': { + type: 'string' + } + } + }, + 'background': { + type: 'object', + params: { + 'image': { + type: 'string' + }, + 'music': { + type: 'string', + required: false + } + } + }, + 'footer': { + type: 'object', + params: { + 'color': { + type: 'string' + }, + 'textColor': { + type: 'string' + }, + 'opacity': { + type: 'number', + min: 0, + max: 1 + } + } + }, + 'showAchievements': { + type: 'boolean' + } + } + + helper.verifyParams(checks, options) + + return androdMenu.init(options) +} + +function finalize(menu) { + visualNovel.menu = menu + + return androdMenu.finalize(menu) +} + +export default { + init, + finalize +} \ No newline at end of file diff --git a/platforms/main/scene.js b/platforms/main/scene.js new file mode 100644 index 0000000..4db6577 --- /dev/null +++ b/platforms/main/scene.js @@ -0,0 +1,165 @@ +import androidScene from '../android/scene.js' + +import helper from './helper.js' + +function init(options) { + return androidScene.init(options) +} + +function addCharacter(scene, options) { + return androidScene.addCharacter(scene, options) +} + +function addScenario(scene, options) { + const checks = { + 'image': { + type: 'fileInitial', + basePath: `${visualNovel.info.paths.android}/app/src/main/res/raw/` + } + } + + helper.verifyParams(checks, options) + + return androidScene.addScenario(scene, options) +} + +function addSpeech(scene, options) { + const checks = { + 'author': { + type: 'object', + params: { + 'name': { + type: 'string' + }, + 'textColor': { + type: 'string' + }, + 'rectangle': { + type: 'object', + params: { + 'color': { + type: 'string' + }, + 'opacity': { + type: 'number' + } + } + } + } + }, + 'text': { + type: 'object', + params: { + 'content': { + type: 'string' + }, + 'color': { + type: 'string' + }, + 'fontSize': { + type: 'number' + }, + 'rectangle': { + type: 'object', + params: { + 'color': { + type: 'string' + }, + 'opacity': { + type: 'number' + } + } + } + } + } + } + + helper.verifyParams(checks, options) + + return androidScene.addSpeech(scene, options) +} + +function addSoundEffects(scene, options) { + if (!Array.isArray(options)) + helper.logFatal('Sound effects must be an array.') + + return androidScene.addSoundEffects(scene, options) +} + +function addMusic(scene, options) { + return androidScene.addMusic(scene, options) +} + +function addTransition(scene, options) { + const checks = { + 'duration': { + type: 'number' + } + } + + helper.verifyParams(checks, options) + + return androidScene.addTransition(scene, options) +} + +function setNextScene(scene, options) { + const checks = { + 'scene': { + type: 'string' + }, + 'item': { + type: 'object', + required: false, + params: { + 'require': { + type: 'object', + params: { + 'id': { + type: 'string', + extraVerification: (param) => { + if (!visualNovel.items.find((item) => item.id == param)) + helper.logFatal(`The item '${param}' doesn't exist.`) + } + }, + 'fallback': { + type: 'string', + } + } + }, + 'remove': { + type: 'boolean', + required: false, + extraVerification: (param, additionalinfo) => { + if (param && !additionalinfo.parent?.require?.id) + helper.logFatal('You must specify an item to be removed once used.') + } + } + } + } + } + + helper.verifyParams(checks, options) + + return androidScene.setNextScene(scene, options) +} + +function addSubScenes(scene, options) { + return androidScene.addSubScenes(scene, options) +} + +function finalize(scene) { + return androidScene.finalize(scene) +} + +export default { + init, + addCharacter, + addScenario, + addSpeech, + addSoundEffects, + addMusic, + addTransition, + setNextScene, + addSubScenes, + finalize +} \ No newline at end of file diff --git a/platforms/main/sub-scene.js b/platforms/main/sub-scene.js new file mode 100644 index 0000000..982eb8d --- /dev/null +++ b/platforms/main/sub-scene.js @@ -0,0 +1,9 @@ +import androidSubScene from '../android/sub-scene.js' + +function init(options) { + return androidSubScene.init(options) +} + +export default { + init +} \ No newline at end of file