diff --git a/backend/app/bl/GameObjectsManager.js b/backend/app/bl/GameObjectsManager.js
index 2111bab..e1b3406 100644
--- a/backend/app/bl/GameObjectsManager.js
+++ b/backend/app/bl/GameObjectsManager.js
@@ -2,6 +2,10 @@ import decompress from "decompress";
import sharp from 'sharp';
sharp.cache({ files : 0 });
+import util from 'node:util';
+import { execFile as npExecFile } from 'child_process';
+const execFile = util.promisify(npExecFile);
+
import fs from 'fs';
import path from 'path';
@@ -99,7 +103,7 @@ class GameObjectsManager{
}else{
object.asset.type = 'single';
await fs.promises.copyFile(src, def + ext);
- if (['.jpg', '.png', '.webp'].includes(ext)){
+ if (['.jpg', '.png', '.webp', '.mp4', '.avi', '.webv'].includes(ext)){
await this.addThumb(object, src);
}
}
@@ -111,8 +115,16 @@ class GameObjectsManager{
* @param {File} thumbSrc A thumbnail, представително изображение
*/
this.addThumb = async function(object, thumbSrc){
+ let ext = path.extname(object.asset.ofn).toLowerCase();
let dest = `${config.fs.repo}/thumb/${object.id}.webp`;
- await sharp(thumbSrc).resize({height: 250}).toFile(dest);
+ if (['.jpg', '.png', '.webp'].includes(ext)){
+ await sharp(thumbSrc).resize({height: 250}).toFile(dest);
+ }else if (['.mp4', '.avi', '.webv'].includes(ext)){
+ let frame = 1;
+ await execFile('ffmpeg', [
+ '-i', thumbSrc, '-vf', `select=eq(n\\,${frame}),scale=-2:300`,
+ '-vframes', 1, '-f', 'image2', '-y', dest]);
+ }
object.asset.thumb = `${object.id}.webp`;
}
diff --git a/src/components/AssetPreview.vue b/src/components/AssetPreview.vue
new file mode 100644
index 0000000..14e6b67
--- /dev/null
+++ b/src/components/AssetPreview.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+ {{ a.name }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/SceneDesigner/GameObject.vue b/src/components/SceneDesigner/GameObject.vue
index de78298..c0fd22c 100644
--- a/src/components/SceneDesigner/GameObject.vue
+++ b/src/components/SceneDesigner/GameObject.vue
@@ -3,9 +3,10 @@
+ {{ modelValue.title }}
-
+
Choose game object
@@ -13,6 +14,7 @@
+
@@ -46,7 +48,7 @@ export default {
modifiers: ['x1', 'y1'],
methods:{
intersect(v){
- return Utils.intersectLineRect(this.vd, v);
+ return Utils.intersectPointRect([this.vd.x1, this.vd.y1], v);
},
assignGameObject(e){
this.modelValue.go = e.id;
diff --git a/src/components/SceneDesigner/Scene.vue b/src/components/SceneDesigner/Scene.vue
index 88d3643..af5f1de 100644
--- a/src/components/SceneDesigner/Scene.vue
+++ b/src/components/SceneDesigner/Scene.vue
@@ -2,10 +2,11 @@
+ {{ modelValue.title }}
-
-
+
+
Choose environment
@@ -13,8 +14,8 @@
+
-
@@ -48,9 +49,9 @@ export default {
modifiers: ['x1', 'y1'],
methods:{
intersect(v){
- return Utils.intersectLineRect(this.vd, v);
+ return Utils.intersectPointRect([this.vd.x1, this.vd.y1], v);
},
- assignGameObject(e){
+ assignEnvironment(e){
this.modelValue.environment = e.id;
if (this.modelValue.id == this.modelValue.title){
this.modelValue.title = e.name
diff --git a/src/components/SceneDesigner/SceneDesigner.vue b/src/components/SceneDesigner/SceneDesigner.vue
index 8803923..4dd06e6 100644
--- a/src/components/SceneDesigner/SceneDesigner.vue
+++ b/src/components/SceneDesigner/SceneDesigner.vue
@@ -26,11 +26,22 @@
-
+
+
+
+
+
+
+
+
+ :key="i" :title="item.data.title" :value="item" :style="`padding-left:${item.__level}rem`"
+ v-show="!item.__parent || item.__parent.vd.expanded" :color="[0,'secondary', 'primary', 'success'][item.__level]">
-
-
-
-
-
@@ -98,7 +102,9 @@ export default {
assetSelector: {
active: false,
type: 'Scene'
- }
+ },
+ dialog: false,
+ expandDrawer: false
}
},
mounted(){
@@ -277,12 +283,11 @@ export default {
id = `${this.components[this.mode].name}-${nid++}`
}while (this.flatItems.find(i=>i.data.id == id));
- let targetContainer = this.selectedItem[0]?.data; //this.items;
- if (targetContainer){
+ let targetContainer = this.items;
+ if (this.mode != 'Scene'){
+ targetContainer = this.selectedItem[0]?.data; //this.items;
targetContainer.items = targetContainer.items || [];
targetContainer = targetContainer.items;
- }else{
- targetContainer = this.items
}
targetContainer.push({
//__type: this.mode,
@@ -337,7 +342,7 @@ export default {
},
select(){
let r = Utils.adjustMinMax(this.selector);
- this.selectedItem = this.flatItems.filter(i=>this.$refs['svg-'+i.id][0].intersect(r));
+ this.selectedItem = this.flatItems.filter(i=>this.$refs['sc-'+i.__path][0].intersect(r));
},
resize(){
let r = this.$refs.svgContainer;
@@ -384,11 +389,17 @@ export default {
stroke-dasharray: 0 calc(8 * var(--svg-scale)) 0;
}
}
+ text {
+ text-anchor: middle;
+ fill:rgb(var(--v-theme-on-surface));
+ stroke-width: 0;//calc( .1px * var(--svg-scale) );;
+ }
+ background-color: rgba(128,128,128,.05);
}
overflow: hidden;
width: 100%;
max-width: 100vw;
- height: 95vh;
+ height: calc(100vh - 244px);
&.pan {
cursor: grab;
}
diff --git a/src/components/SceneDesigner/Task.vue b/src/components/SceneDesigner/Task.vue
index 4b3b757..f622d30 100644
--- a/src/components/SceneDesigner/Task.vue
+++ b/src/components/SceneDesigner/Task.vue
@@ -3,18 +3,20 @@
-
+
+ {{ modelValue.title }}
-
+
+
-
+
@@ -47,7 +49,13 @@ export default {
modifiers: ['x1', 'y1'],
methods:{
intersect(v){
- return Utils.intersectLineRect(this.vd, v);
+ return Utils.intersectPointRect([this.vd.x1, this.vd.y1], v);
+ },
+ assignTaskIntro(e){
+ this.modelValue.intro = e.id;
+ if (this.modelValue.id == this.modelValue.title){
+ this.modelValue.title = e.name
+ }
}
}
}
diff --git a/src/pages/game-objects/[[id]].vue b/src/pages/game-objects/[[id]].vue
index a5e8658..649a825 100644
--- a/src/pages/game-objects/[[id]].vue
+++ b/src/pages/game-objects/[[id]].vue
@@ -2,6 +2,7 @@
+
@@ -18,17 +19,7 @@
-
-
-
-
-
- {{ a.name }}
-
-
-
-
-
+
{{ $l.captureThumbnail }}
@@ -38,8 +29,6 @@