From 2a4457843046967e904508e19603babe9b2a1ef3 Mon Sep 17 00:00:00 2001 From: goynov Date: Sat, 15 Mar 2025 11:23:55 +0200 Subject: [PATCH] link scenarios to backend --- backend/app/Db.js | 20 ++++++- backend/app/bl/GameObjectsManager.js | 24 +------- backend/app/bl/ScenariosManager.js | 25 ++++++-- .../controllers/api/ScenariosController.js | 15 ++++- backend/main.js | 2 + .../SceneDesigner/AssetSelector.vue | 51 ++++++++++++++++ src/components/SceneDesigner/GameObject.vue | 15 +++-- src/components/SceneDesigner/Scene.vue | 14 ++++- .../SceneDesigner/SceneDesigner.vue | 58 ++++++++++++++----- src/pages/scenarios/[[id]].vue | 17 +----- src/pages/scenarios/list.vue | 42 +++++++++++++- src/plugins/api.js | 13 ++++- src/plugins/params.js | 12 ++-- 13 files changed, 233 insertions(+), 75 deletions(-) create mode 100644 src/components/SceneDesigner/AssetSelector.vue diff --git a/backend/app/Db.js b/backend/app/Db.js index acfa3b9..27587dd 100644 --- a/backend/app/Db.js +++ b/backend/app/Db.js @@ -26,7 +26,7 @@ class Db { try { dbo = db.db(app.config.db.name); this.instance = dbo; - for (let c of ['users', 'user_sessions', 'history', 'log', 'assets']){ + for (let c of ['users', 'user_sessions', 'history', 'log', 'assets', 'scenarios']){ try { await dbo.createCollection(c); }catch(err){} @@ -245,6 +245,24 @@ class Db { ObjectId(id){ return new ObjectId(id); } + + /** + * Gets last asset Id from database, намира последния пореден идентификатор на обект в базата от данни + * @returns {Number} Last Asset Id, последен (най-голям) идентификатор + */ + async getLastId(collection){ + let ag = await this.aggregate(collection, [ + { + $group:{ + _id: null, + max: { + $max: "$id", + }, + }, + }, + ]); + return ag.max || 0; + } } export { Db }; \ No newline at end of file diff --git a/backend/app/bl/GameObjectsManager.js b/backend/app/bl/GameObjectsManager.js index 965276a..2111bab 100644 --- a/backend/app/bl/GameObjectsManager.js +++ b/backend/app/bl/GameObjectsManager.js @@ -20,31 +20,13 @@ class GameObjectsManager{ init(app){ const {db, config} = app; - /** - * Gets last asset Id from database, намира последния пореден идентификатор на обект в базата от данни - * @returns {Number} Last Asset Id, последен (най-голям) идентификатор - */ - this.getLastId = async function(){ - let ag = await db.aggregate(collection, [ - { - $group:{ - _id: null, - max: { - $max: "$id", - }, - }, - }, - ]); - return ag.max || 0; - } - /** * Creates a game object, създаване на игрови обект * @param {Context} ctx Request context, контекст на заявката * @param {GameObject} data Asset data, данни за игровия обект */ this.create = async function(ctx, data){ - data.id = (await this.getLastId()) + 1; + data.id = (await db.getLastId(collection)) + 1; await db.create(collection, data); if (ctx.files?.file){ await this.addFile(data, ctx.files.file) @@ -139,9 +121,9 @@ class GameObjectsManager{ * @param {Object} query Query to DB, критерии - заявка към базата от данни * @returns {GameObject[]} Array of game objects, масив от игрови обекти */ - this.list = async function(query){ + this.list = async function(query = {}){ return await db.list(collection, { - query: {}, + query, project: { name:1, id:1, type:1, asset:1} }); } diff --git a/backend/app/bl/ScenariosManager.js b/backend/app/bl/ScenariosManager.js index 20d2421..270ba68 100644 --- a/backend/app/bl/ScenariosManager.js +++ b/backend/app/bl/ScenariosManager.js @@ -1,4 +1,6 @@ +const collection = 'scenarios'; + /** * Scenarios manager class, контролен клас за управление на игрови сценарии */ @@ -18,7 +20,9 @@ class ScenariosManager{ * @param {Scenario} data the scenario, данни за сценария */ this.create = async function(ctx, data){ - + data.id = (await db.getLastId(collection)) + 1; + await db.create(collection, data); + return data; } /** @@ -27,7 +31,8 @@ class ScenariosManager{ * @returns {Scenario} */ this.read = async function(id){ - + id = parseInt(id); + return await db.get(collection, {id}); } /** @@ -36,7 +41,11 @@ class ScenariosManager{ * @param {Scenario} data the scenario */ this.update = async function(ctx, data){ - + data.id = parseInt(data.id); + let object = await this.read(data.id); + data = Object.assign(object, data); + await db.update(collection, {id: data.id}, data); + return data; } /** @@ -44,7 +53,8 @@ class ScenariosManager{ * @param {Number} id scenario ID, идентификатор на сценарий */ this.remove = async function(id){ - + id = parseInt(id); + await db.remove(collection, {id}); } /** @@ -52,8 +62,11 @@ class ScenariosManager{ * @param {Query} query criteria, критерии - заявка към базата от данни * @returns {Scenario[]} */ - this.list = async function(query){ - + this.list = async function(query = {}){ + return await db.list(collection, { + query, + project: { name:1, id:1, sceneThumb: '$scenes.data.environment'} + }); } } diff --git a/backend/controllers/api/ScenariosController.js b/backend/controllers/api/ScenariosController.js index 97f4211..b667d1c 100644 --- a/backend/controllers/api/ScenariosController.js +++ b/backend/controllers/api/ScenariosController.js @@ -22,7 +22,14 @@ class ScenariosController{ * @memberof ScenariosController */ router.put('/', async (req, res)=>{ - + try{ + let data = req.body; + let object = await scenarios[data.id? 'update' : 'create'](req, data) + res.json({status: 'OK', object}); + }catch(err){ + console.error(err); + res.status(500).json({status: 'ERR', err}); + } }); /** @@ -32,6 +39,8 @@ class ScenariosController{ * @memberof ScenariosController */ router.post('/', async (req, res)=>{ + let result = await scenarios.list(req.body); + res.json(result); }) /** @@ -42,6 +51,8 @@ class ScenariosController{ * @memberof ScenariosController */ router.get('/:id', async (req, res)=>{ + let object = await scenarios.read(parseInt(req.params.id)); + res.json(object); }) /** @@ -51,6 +62,8 @@ class ScenariosController{ * @memberof ScenariosController */ router.delete('/:id', async (req, res)=>{ + await gameObject.remove(req.params.id); + res.json({status: 'OK'}); }) app.webServer.xapp.use(this.route, router); diff --git a/backend/main.js b/backend/main.js index 89033f1..35fbd67 100644 --- a/backend/main.js +++ b/backend/main.js @@ -12,9 +12,11 @@ const modules = [ {name:'Config', path:'app/Config.js'}, {name:'Db', path:'app/Db.js'}, {name:'GameObjectsManager', path:'app/bl/GameObjectsManager.js'}, + {name:'ScenariosManager', path:'app/bl/ScenariosManager.js'}, {name:'WebServer', path:'app/WebServer.js'}, {name: 'AssetController', path: 'controllers/AssetController.js'}, {name:'GameObjectsController', path:'controllers/api/GameObjectsController.js'}, + {name:'ScenariosController', path:'controllers/api/ScenariosController.js'}, ] process.on('uncaughtException', err => { diff --git a/src/components/SceneDesigner/AssetSelector.vue b/src/components/SceneDesigner/AssetSelector.vue new file mode 100644 index 0000000..00f6934 --- /dev/null +++ b/src/components/SceneDesigner/AssetSelector.vue @@ -0,0 +1,51 @@ + + + \ No newline at end of file diff --git a/src/components/SceneDesigner/GameObject.vue b/src/components/SceneDesigner/GameObject.vue index facb0ea..ed47b38 100644 --- a/src/components/SceneDesigner/GameObject.vue +++ b/src/components/SceneDesigner/GameObject.vue @@ -2,12 +2,16 @@ - + - - - + + + + + \ No newline at end of file diff --git a/src/plugins/api.js b/src/plugins/api.js index fafc10b..d6cc480 100644 --- a/src/plugins/api.js +++ b/src/plugins/api.js @@ -2,7 +2,18 @@ import axios from 'axios'; const $ax = axios.create({ baseURL: '/api/', - //transformRequest: data=> + transformRequest: [ + (data, headers)=>{ + if (data && !(data instanceof FormData)){ + data = JSON.stringify(data, (k, v)=>{ + return k.startsWith('__') ? undefined : v; + }); + headers['Content-Type'] = 'application/json;charset=utf-8'; + } + return data; + } + , ...axios.defaults.transformRequest + ] }) export default { diff --git a/src/plugins/params.js b/src/plugins/params.js index db8abfc..d19a7ab 100644 --- a/src/plugins/params.js +++ b/src/plugins/params.js @@ -7,21 +7,25 @@ export default { value: 'panorama2d', icon: 'panorama-variant-outline', title: l.panorama2d, - render: true + render: true, + type: 'Scene' }, { value: 'environment3d', icon: 'panorama-sphere-outline', title: l.environment3d, - render: true + render: true, + type: 'Scene' }, { value: 'object3d', icon: 'video-3d', title: l.object3d, - render: true + render: true, + type: 'GameObject' }, { value: 'object2d', icon: 'file-image-outline', - title: l.object2d + title: l.object2d, + type: 'GameObject' }, { value: 'player3d', icon: 'human-greeting',