link scenarios to backend
This commit is contained in:
+19
-1
@@ -26,7 +26,7 @@ class Db {
|
|||||||
try {
|
try {
|
||||||
dbo = db.db(app.config.db.name);
|
dbo = db.db(app.config.db.name);
|
||||||
this.instance = dbo;
|
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 {
|
try {
|
||||||
await dbo.createCollection(c);
|
await dbo.createCollection(c);
|
||||||
}catch(err){}
|
}catch(err){}
|
||||||
@@ -245,6 +245,24 @@ class Db {
|
|||||||
ObjectId(id){
|
ObjectId(id){
|
||||||
return new 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 };
|
export { Db };
|
||||||
@@ -20,31 +20,13 @@ class GameObjectsManager{
|
|||||||
init(app){
|
init(app){
|
||||||
const {db, config} = 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, създаване на игрови обект
|
* Creates a game object, създаване на игрови обект
|
||||||
* @param {Context} ctx Request context, контекст на заявката
|
* @param {Context} ctx Request context, контекст на заявката
|
||||||
* @param {GameObject} data Asset data, данни за игровия обект
|
* @param {GameObject} data Asset data, данни за игровия обект
|
||||||
*/
|
*/
|
||||||
this.create = async function(ctx, 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);
|
await db.create(collection, data);
|
||||||
if (ctx.files?.file){
|
if (ctx.files?.file){
|
||||||
await this.addFile(data, ctx.files.file)
|
await this.addFile(data, ctx.files.file)
|
||||||
@@ -139,9 +121,9 @@ class GameObjectsManager{
|
|||||||
* @param {Object} query Query to DB, критерии - заявка към базата от данни
|
* @param {Object} query Query to DB, критерии - заявка към базата от данни
|
||||||
* @returns {GameObject[]} Array of game objects, масив от игрови обекти
|
* @returns {GameObject[]} Array of game objects, масив от игрови обекти
|
||||||
*/
|
*/
|
||||||
this.list = async function(query){
|
this.list = async function(query = {}){
|
||||||
return await db.list(collection, {
|
return await db.list(collection, {
|
||||||
query: {},
|
query,
|
||||||
project: { name:1, id:1, type:1, asset:1}
|
project: { name:1, id:1, type:1, asset:1}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
const collection = 'scenarios';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scenarios manager class, контролен клас за управление на игрови сценарии
|
* Scenarios manager class, контролен клас за управление на игрови сценарии
|
||||||
*/
|
*/
|
||||||
@@ -18,7 +20,9 @@ class ScenariosManager{
|
|||||||
* @param {Scenario} data the scenario, данни за сценария
|
* @param {Scenario} data the scenario, данни за сценария
|
||||||
*/
|
*/
|
||||||
this.create = async function(ctx, data){
|
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}
|
* @returns {Scenario}
|
||||||
*/
|
*/
|
||||||
this.read = async function(id){
|
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
|
* @param {Scenario} data the scenario
|
||||||
*/
|
*/
|
||||||
this.update = async function(ctx, data){
|
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, идентификатор на сценарий
|
* @param {Number} id scenario ID, идентификатор на сценарий
|
||||||
*/
|
*/
|
||||||
this.remove = async function(id){
|
this.remove = async function(id){
|
||||||
|
id = parseInt(id);
|
||||||
|
await db.remove(collection, {id});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,8 +62,11 @@ class ScenariosManager{
|
|||||||
* @param {Query} query criteria, критерии - заявка към базата от данни
|
* @param {Query} query criteria, критерии - заявка към базата от данни
|
||||||
* @returns {Scenario[]}
|
* @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'}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,14 @@ class ScenariosController{
|
|||||||
* @memberof ScenariosController
|
* @memberof ScenariosController
|
||||||
*/
|
*/
|
||||||
router.put('/', async (req, res)=>{
|
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
|
* @memberof ScenariosController
|
||||||
*/
|
*/
|
||||||
router.post('/', async (req, res)=>{
|
router.post('/', async (req, res)=>{
|
||||||
|
let result = await scenarios.list(req.body);
|
||||||
|
res.json(result);
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +51,8 @@ class ScenariosController{
|
|||||||
* @memberof ScenariosController
|
* @memberof ScenariosController
|
||||||
*/
|
*/
|
||||||
router.get('/:id', async (req, res)=>{
|
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
|
* @memberof ScenariosController
|
||||||
*/
|
*/
|
||||||
router.delete('/:id', async (req, res)=>{
|
router.delete('/:id', async (req, res)=>{
|
||||||
|
await gameObject.remove(req.params.id);
|
||||||
|
res.json({status: 'OK'});
|
||||||
})
|
})
|
||||||
|
|
||||||
app.webServer.xapp.use(this.route, router);
|
app.webServer.xapp.use(this.route, router);
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ const modules = [
|
|||||||
{name:'Config', path:'app/Config.js'},
|
{name:'Config', path:'app/Config.js'},
|
||||||
{name:'Db', path:'app/Db.js'},
|
{name:'Db', path:'app/Db.js'},
|
||||||
{name:'GameObjectsManager', path:'app/bl/GameObjectsManager.js'},
|
{name:'GameObjectsManager', path:'app/bl/GameObjectsManager.js'},
|
||||||
|
{name:'ScenariosManager', path:'app/bl/ScenariosManager.js'},
|
||||||
{name:'WebServer', path:'app/WebServer.js'},
|
{name:'WebServer', path:'app/WebServer.js'},
|
||||||
{name: 'AssetController', path: 'controllers/AssetController.js'},
|
{name: 'AssetController', path: 'controllers/AssetController.js'},
|
||||||
{name:'GameObjectsController', path:'controllers/api/GameObjectsController.js'},
|
{name:'GameObjectsController', path:'controllers/api/GameObjectsController.js'},
|
||||||
|
{name:'ScenariosController', path:'controllers/api/ScenariosController.js'},
|
||||||
]
|
]
|
||||||
|
|
||||||
process.on('uncaughtException', err => {
|
process.on('uncaughtException', err => {
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<slot name="activator" v-bind="activatorProps" @click="dialog = !dialog"></slot>
|
||||||
|
<v-dialog transition="dialog-bottom-transition" fullscreen v-model="dialog">
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col v-for="(v, i) in items" :key="i" cols="12" xs="6" sm="4" md="3" xl="2" class="position-relative">
|
||||||
|
<v-img :src="`/asset/thumb/${v.asset?.thumb}`" @click="select(v.id)"></v-img>
|
||||||
|
<div class="d-flex">
|
||||||
|
<span class="flex-grow-1">{{ v.name }}</span>
|
||||||
|
<v-icon color="primary" size="x-large" class="position-absolute top-0 left-0 ma-6">mdi-{{ $p.objectTypes.find(t=>t.value == v.type).icon }}</v-icon>
|
||||||
|
<!-- <v-btn density="compact" variant="text" icon="mdi-pencil-outline" :to="`/game-objects/${v.id}`" color="primary"></v-btn> -->
|
||||||
|
</div>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props:[
|
||||||
|
'modelValue', 'type'
|
||||||
|
],
|
||||||
|
emits:['select'],
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
items: [],
|
||||||
|
activatorProps:{},
|
||||||
|
dialog: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted(){
|
||||||
|
console.log(this.activatorProps, this.cls)
|
||||||
|
},
|
||||||
|
|
||||||
|
async created(){
|
||||||
|
this.items = (await this.$api.gameObject.search({
|
||||||
|
type: { $in: this.$p.objectTypes.filter(t=>t.type == this.type || !this.type).map(t=>t.value) }
|
||||||
|
})).data.data
|
||||||
|
},
|
||||||
|
|
||||||
|
methods:{
|
||||||
|
select(id){
|
||||||
|
this.$emit('select', id);
|
||||||
|
this.dialog = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -2,12 +2,16 @@
|
|||||||
<teleport to=".scene-designer" v-if="active">
|
<teleport to=".scene-designer" v-if="active">
|
||||||
<g @mousedown="$emit('target', {target:vd, attrs:['x1', 'y1'], delta: true})" :class="{gameObject: true, selected}">
|
<g @mousedown="$emit('target', {target:vd, attrs:['x1', 'y1'], delta: true})" :class="{gameObject: true, selected}">
|
||||||
<line :x1="vd.x1" :y1="vd.y1" :x2="parent.vd.x1" :y2="parent.vd.y1"></line>
|
<line :x1="vd.x1" :y1="vd.y1" :x2="parent.vd.x1" :y2="parent.vd.y1"></line>
|
||||||
<svg-icon :src="`/asset/thumb/${modelValue.id}.webp`" :x="vd.x1" :y="vd.y1" :size="37"></svg-icon>
|
<svg-icon :src="`/asset/thumb/${modelValue.id||0}.webp`" :x="vd.x1" :y="vd.y1" :size="37"></svg-icon>
|
||||||
</g>
|
</g>
|
||||||
</teleport>
|
</teleport>
|
||||||
<v-list density="compact" nav v-if="selected">
|
<v-card v-if="selected">
|
||||||
<v-list-item prepend-icon="mdi-panorama-outline" :title="$l.addScene" value="scene"></v-list-item>
|
<asset-selector @select="modelValue.id = $event" type="GameObject">
|
||||||
</v-list>
|
<template v-slot:activator="props">
|
||||||
|
<v-btn v-bind="props" icon="mdi-panorama-outline"></v-btn>
|
||||||
|
</template>
|
||||||
|
</asset-selector>
|
||||||
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -26,6 +30,7 @@ export default {
|
|||||||
this.active = true;
|
this.active = true;
|
||||||
},
|
},
|
||||||
props:{
|
props:{
|
||||||
|
//context: Object,
|
||||||
modelValue: Object,
|
modelValue: Object,
|
||||||
vd: Object,
|
vd: Object,
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
|
|||||||
@@ -1,24 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<teleport to=".scene-designer" v-if="active">
|
<teleport to=".scene-designer" v-if="active">
|
||||||
<g @mousedown="$emit('target', {target:vd, attrs:['x1', 'y1'], delta: true})" :class="{scene: true, selected}">
|
<g @mousedown="$emit('target', {target:vd, attrs:['x1', 'y1'], delta: true})" :class="{scene: true, selected}">
|
||||||
<svg-icon :src="`/asset/thumb/${modelValue.environment}.webp`" :x="vd.x1" :y="vd.y1" :size="65"></svg-icon>
|
<svg-icon :src="`/asset/thumb/${modelValue.environment||0}.webp`" :x="vd.x1" :y="vd.y1" :size="65"></svg-icon>
|
||||||
</g>
|
</g>
|
||||||
</teleport>
|
</teleport>
|
||||||
<v-card title="Scene" v-if="selected">
|
<v-card title="Scene" v-if="selected">
|
||||||
<v-form class="pa-4">
|
<v-form class="pa-4">
|
||||||
<v-text-field density="compact" :label="$l.name" v-model="modelValue.name"></v-text-field>
|
<v-text-field density="compact" :label="$l.name" v-model="modelValue.name"></v-text-field>
|
||||||
</v-form>
|
</v-form>
|
||||||
<v-btn prepend-icon="mdi-panorama-outline" ></v-btn>
|
|
||||||
|
<asset-selector @select="modelValue.environment = $event" type="Scene">
|
||||||
|
<template v-slot:activator="props">
|
||||||
|
<v-btn v-bind="props" icon="mdi-panorama-outline"></v-btn>
|
||||||
|
</template>
|
||||||
|
</asset-selector>
|
||||||
|
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SvgIcon from './SvgIcon.vue';
|
import SvgIcon from './SvgIcon.vue';
|
||||||
import Utils from '@/lib/utils';
|
import Utils from '@/lib/utils';
|
||||||
|
import AssetSelector from './AssetSelector.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits:['target'],
|
emits:['target'],
|
||||||
components: { SvgIcon },
|
components: { SvgIcon, AssetSelector },
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
active: false
|
active: false
|
||||||
@@ -28,6 +35,7 @@ export default {
|
|||||||
this.active = true;
|
this.active = true;
|
||||||
},
|
},
|
||||||
props:{
|
props:{
|
||||||
|
//context: Object,
|
||||||
modelValue: Object,
|
modelValue: Object,
|
||||||
vd: Object,
|
vd: Object,
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
|
|||||||
@@ -1,28 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container my-3">
|
<div class="container my-3">
|
||||||
<v-btn-toggle variant="tonal" density="compact" class="mx-auto" v-model="mode" color="blue">
|
<v-btn-toggle variant="tonal" density="compact" class="mx-auto" v-model="mode" color="blue">
|
||||||
<v-btn size="small" class="text-none" value="default" prepend-icon="mdi-cursor-default-click">Pointer</v-btn>
|
<v-btn size="small" class="text-none" value="default"
|
||||||
|
prepend-icon="mdi-cursor-default-click">Pointer</v-btn>
|
||||||
<v-btn size="small" class="text-none" value="select" prepend-icon="mdi-select-multiple">Select</v-btn>
|
<v-btn size="small" class="text-none" value="select" prepend-icon="mdi-select-multiple">Select</v-btn>
|
||||||
<v-btn size="small" class="text-none" value="move" prepend-icon="mdi-cursor-move">Move</v-btn>
|
<v-btn size="small" class="text-none" value="move" prepend-icon="mdi-cursor-move">Move</v-btn>
|
||||||
<v-btn size="small" class="text-none" value="pan" prepend-icon="mdi-hand-back-right-outline">Pan</v-btn>
|
<v-btn size="small" class="text-none" value="pan" prepend-icon="mdi-hand-back-right-outline">Pan</v-btn>
|
||||||
|
|
||||||
<v-btn size="small" class="text-none" value="scene" prepend-icon="mdi-panorama-outline">{{ $l.addScene }}</v-btn>
|
<v-btn size="small" class="text-none" value="Scene" prepend-icon="mdi-panorama-outline">Add scene</v-btn>
|
||||||
<v-btn size="small" class="text-none" value="object" prepend-icon="mdi-bird">{{ $l.addScene }}</v-btn>
|
<v-btn size="small" class="text-none" value="GameObject"
|
||||||
<v-btn size="small" class="text-none" value="task" prepend-icon="mdi-checkbox-marked-circle-plus-outline">{{ $l.addScene }}</v-btn>
|
v-if="selectedItem.length == 1 && selectedItem[0].__type == 'Scene'" prepend-icon="mdi-bird">Add game
|
||||||
|
object</v-btn>
|
||||||
|
<v-btn size="small" class="text-none" value="Task"
|
||||||
|
v-if="selectedItem.length == 1 && selectedItem[0].__type == 'GameObject'"
|
||||||
|
prepend-icon="mdi-checkbox-marked-circle-plus-outline">Add task</v-btn>
|
||||||
</v-btn-toggle>
|
</v-btn-toggle>
|
||||||
<div @wheel="onWheel" @mousedown="onMouseDown" @mouseup="onMouseUp" @mousemove="onDrag"
|
<div @wheel="onWheel" @mousedown="onMouseDown" @mouseup="onMouseUp" @mousemove="onDrag"
|
||||||
:class="`svg-container ${mode}`" ref="svgContainer">
|
:class="`svg-container ${mode}`" ref="svgContainer">
|
||||||
<svg class="scene-designer" @resize="resize" :width="viewBox.w" :height="viewBox.h" :viewBox="`${vb.x} ${vb.y} ${vb.w} ${vb.h}`" x="0" y="0"
|
<svg class="scene-designer" @resize="resize" :width="viewBox.w" :height="viewBox.h"
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
:viewBox="`${vb.x} ${vb.y} ${vb.w} ${vb.h}`" x="0" y="0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<SvgRectangle v-model="selector" class="selector"></SvgRectangle>
|
<SvgRectangle v-model="selector" class="selector"></SvgRectangle>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<v-navigation-drawer location="right">
|
<v-navigation-drawer location="right">
|
||||||
<template v-for="(item, i) in flatItems" :key="i">
|
<template v-for="(item, i) in flatItems" :key="i">
|
||||||
<component :is="components[item.__type]" :ref="'svg-'+item.id"
|
<component :is="components[item.__type]" :ref="'svg-'+item.id" :vd="item.vd" v-model="item.data"
|
||||||
:vd="item.vd" v-model="item.data" @target="setTarget($event, item)"
|
@target="setTarget($event, item)" :visible="item.visible" :cid="item.id" :parent="item.__parent"
|
||||||
:visible="item.visible" :cid="item.id"
|
:selected="selectedItem.includes(item)">
|
||||||
:parent="item.__parent" :selected="selectedItem.includes(item)">
|
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
@@ -34,17 +39,20 @@ import GameObject from './GameObject.vue';
|
|||||||
import Scene from './Scene.vue';
|
import Scene from './Scene.vue';
|
||||||
import SvgRectangle from './SvgRectangle.vue';
|
import SvgRectangle from './SvgRectangle.vue';
|
||||||
import Utils from '@/lib/utils';
|
import Utils from '@/lib/utils';
|
||||||
|
import AssetSelector from './AssetSelector.vue';
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
Scene, GameObject
|
Scene, GameObject
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { AssetSelector },
|
||||||
props:{
|
props:{
|
||||||
modelValue: Object
|
modelValue: Object
|
||||||
},
|
},
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
|
context: this,
|
||||||
mode: 'default',
|
mode: 'default',
|
||||||
selectedItem: [],
|
selectedItem: [],
|
||||||
viewBox: {
|
viewBox: {
|
||||||
@@ -64,6 +72,10 @@ export default {
|
|||||||
modeStep: 0,
|
modeStep: 0,
|
||||||
mousedown: false,
|
mousedown: false,
|
||||||
target: null,
|
target: null,
|
||||||
|
assetSelector: {
|
||||||
|
active: false,
|
||||||
|
type: 'Scene'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted(){
|
mounted(){
|
||||||
@@ -101,7 +113,7 @@ export default {
|
|||||||
},
|
},
|
||||||
flatItems(){
|
flatItems(){
|
||||||
let fi = [];
|
let fi = [];
|
||||||
this.items.forEach(i=>{
|
this.items?.forEach(i=>{
|
||||||
i.__type = 'Scene';
|
i.__type = 'Scene';
|
||||||
fi.push(i);
|
fi.push(i);
|
||||||
i.data?.gameObjects?.forEach(go=>{
|
i.data?.gameObjects?.forEach(go=>{
|
||||||
@@ -228,10 +240,18 @@ export default {
|
|||||||
let id, nid = 1;
|
let id, nid = 1;
|
||||||
do {
|
do {
|
||||||
id = `${this.components[this.mode].name}-${nid++}`
|
id = `${this.components[this.mode].name}-${nid++}`
|
||||||
}while (this.flatItems.find(i=>i.id == id))
|
}while (this.flatItems.find(i=>i.id == id));
|
||||||
this.items.push({
|
let targetArray = this.items;
|
||||||
name: this.mode,
|
if (this.mode == 'GameObject'){
|
||||||
data: this.target.target,
|
if (this.selectedItem[0].data && !this.selectedItem[0].data.gameObjects){
|
||||||
|
this.selectedItem[0].data.gameObjects = [];
|
||||||
|
}
|
||||||
|
targetArray = this.selectedItem[0].data.gameObjects;
|
||||||
|
}
|
||||||
|
targetArray.push({
|
||||||
|
//__type: this.mode,
|
||||||
|
vd: this.target.target,
|
||||||
|
data: {},
|
||||||
visible: true,
|
visible: true,
|
||||||
id, title: id
|
id, title: id
|
||||||
})
|
})
|
||||||
@@ -284,6 +304,9 @@ export default {
|
|||||||
this.viewBox.w = r.clientWidth;
|
this.viewBox.w = r.clientWidth;
|
||||||
this.viewBox.h = r.clientHeight;
|
this.viewBox.h = r.clientHeight;
|
||||||
//this.zoom = Math.min(r.clientWidth / this.viewBox.w, r.clientHeight / this.viewBox.h);
|
//this.zoom = Math.min(r.clientWidth / this.viewBox.w, r.clientHeight / this.viewBox.h);
|
||||||
|
},
|
||||||
|
assetSelected(e, v){
|
||||||
|
console.log(e, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,7 +334,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
line, path{
|
line, path{
|
||||||
stroke: #19c;
|
stroke: rgb(213, 226, 231);
|
||||||
stroke-width: calc( 2px * var(--svg-scale) );
|
stroke-width: calc( 2px * var(--svg-scale) );
|
||||||
}
|
}
|
||||||
g.selector {
|
g.selector {
|
||||||
@@ -326,5 +349,8 @@ export default {
|
|||||||
&.pan {
|
&.pan {
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
&.Scene, &.GameObject {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -22,22 +22,7 @@ import SceneDesigner from '@/components/SceneDesigner/SceneDesigner.vue';
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
object: {
|
object: {},
|
||||||
scenes: [
|
|
||||||
{
|
|
||||||
id: 'test',
|
|
||||||
vd: { x1: 220, y1: 220 },
|
|
||||||
data: {
|
|
||||||
environment: 3, intro: 2,
|
|
||||||
gameObjects: [
|
|
||||||
{ vd: { x1: 350, y1:350 }, data:{ id: 7, }},
|
|
||||||
{ vd: { x1: 200, y1:400 }, data:{ id: 8, }},
|
|
||||||
{ vd: { x1: 70, y1:350 }, data:{ id: 9, }}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
valid: false,
|
valid: false,
|
||||||
rules: {
|
rules: {
|
||||||
required: v => v ? true : this.$l.fieldRequired,
|
required: v => v ? true : this.$l.fieldRequired,
|
||||||
|
|||||||
@@ -1,9 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col v-for="(v, i) in items" :key="i" cols="12" xs="6" sm="4" md="3" xl="2" class="position-relative">
|
||||||
|
<router-link :to="`/scenarios/${v.id}`">
|
||||||
|
<v-img :src="`/asset/thumb/${v.sceneThumb[0]}.webp`"></v-img>
|
||||||
|
</router-link>
|
||||||
|
<div class="d-flex">
|
||||||
|
<span class="flex-grow-1">{{ v.name }}</span>
|
||||||
|
<v-btn density="compact" variant="text" icon="mdi-pencil-outline" :to="`/scenarios/${v.id}`" color="primary"></v-btn>
|
||||||
|
<v-btn density="compact" variant="text" icon="mdi-close" @click="confirmTarget = v; confirmDialog = true" color="red"></v-btn>
|
||||||
|
</div>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
<v-dialog v-model="confirmDialog" width="auto">
|
||||||
|
<v-card :title="`${$l.confirmDeletionOf} ${ confirmTarget.name }?`">
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn @click="confirmDialog = false">{{ $l.no }}</v-btn>
|
||||||
|
<v-btn color="red-darken-4" @click="remove(confirmTarget)">{{ $l.yes }}</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
items: [],
|
||||||
|
confirmDialog: false,
|
||||||
|
confirmTarget: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async created(){
|
||||||
|
this.items = (await this.$api.scenario.search()).data.data
|
||||||
|
},
|
||||||
|
|
||||||
|
methods:{
|
||||||
|
async remove(item){
|
||||||
|
await this.$api.scenario.remove(item.id);
|
||||||
|
this.confirmDialog = false;
|
||||||
|
this.items.splice(this.items.indexOf(item), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
+12
-1
@@ -2,7 +2,18 @@ import axios from 'axios';
|
|||||||
|
|
||||||
const $ax = axios.create({
|
const $ax = axios.create({
|
||||||
baseURL: '/api/',
|
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 {
|
export default {
|
||||||
|
|||||||
@@ -7,21 +7,25 @@ export default {
|
|||||||
value: 'panorama2d',
|
value: 'panorama2d',
|
||||||
icon: 'panorama-variant-outline',
|
icon: 'panorama-variant-outline',
|
||||||
title: l.panorama2d,
|
title: l.panorama2d,
|
||||||
render: true
|
render: true,
|
||||||
|
type: 'Scene'
|
||||||
}, {
|
}, {
|
||||||
value: 'environment3d',
|
value: 'environment3d',
|
||||||
icon: 'panorama-sphere-outline',
|
icon: 'panorama-sphere-outline',
|
||||||
title: l.environment3d,
|
title: l.environment3d,
|
||||||
render: true
|
render: true,
|
||||||
|
type: 'Scene'
|
||||||
}, {
|
}, {
|
||||||
value: 'object3d',
|
value: 'object3d',
|
||||||
icon: 'video-3d',
|
icon: 'video-3d',
|
||||||
title: l.object3d,
|
title: l.object3d,
|
||||||
render: true
|
render: true,
|
||||||
|
type: 'GameObject'
|
||||||
}, {
|
}, {
|
||||||
value: 'object2d',
|
value: 'object2d',
|
||||||
icon: 'file-image-outline',
|
icon: 'file-image-outline',
|
||||||
title: l.object2d
|
title: l.object2d,
|
||||||
|
type: 'GameObject'
|
||||||
}, {
|
}, {
|
||||||
value: 'player3d',
|
value: 'player3d',
|
||||||
icon: 'human-greeting',
|
icon: 'human-greeting',
|
||||||
|
|||||||
Reference in New Issue
Block a user