THREE?
This commit is contained in:
49
app/imports/api/tabletop/TabletopMaps.js
Normal file
49
app/imports/api/tabletop/TabletopMaps.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import ChildSchema from '/imports/api/parenting/ChildSchema.js';
|
||||
|
||||
let TabletopMaps = new Mongo.Collection('tabletopmaps');
|
||||
|
||||
let TabletopMapschema = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
texture: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
position: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
},
|
||||
'position.x': {
|
||||
type: Number,
|
||||
},
|
||||
'position.y': {
|
||||
type: Number,
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
},
|
||||
rotation: {
|
||||
type: Number,
|
||||
max: 360,
|
||||
min: 0,
|
||||
},
|
||||
// If this map was copied from a library map, this ID will be set
|
||||
libraryMapId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
const schema = new SimpleSchema({});
|
||||
schema.extend(ChildSchema);
|
||||
schema.extend(TabletopMapschema);
|
||||
TabletopMaps.attachSchema(schema);
|
||||
|
||||
export default TabletopMaps;
|
||||
@@ -97,6 +97,7 @@
|
||||
//{title: 'Tabletops', icon: 'api', to: '/tabletops', requireLogin: true},
|
||||
//{title: 'Friends', icon: 'people', to: '/friends', requireLogin: true},
|
||||
{title: 'Files', icon: 'mdi-file-multiple', to: '/my-files'},
|
||||
{title: 'Tabletops', icon: 'mdi-table', to: '/tabletops'},
|
||||
{title: 'Feedback', icon: 'mdi-bug', to: '/feedback'},
|
||||
{title: 'About', icon: 'mdi-sign-text', to: '/about'},
|
||||
{title: 'Patreon', icon: 'mdi-patreon', href: 'https://www.patreon.com/dicecloud'},
|
||||
|
||||
@@ -1,54 +1,68 @@
|
||||
<template lang="html">
|
||||
<v-container
|
||||
class="tabletop"
|
||||
fluid
|
||||
<div
|
||||
class="tabletop layout column"
|
||||
style="height: 100%;"
|
||||
>
|
||||
<v-row
|
||||
dense
|
||||
class="initiative-row"
|
||||
style="flex-wrap: nowrap; overflow-x: auto;"
|
||||
@wheel="transformScroll($event)"
|
||||
<tabletop-map
|
||||
class="play-area"
|
||||
style="
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
"
|
||||
/>
|
||||
<v-container
|
||||
fluid
|
||||
>
|
||||
<tabletop-creature-card
|
||||
v-for="creature in creatures"
|
||||
:key="creature._id"
|
||||
:model="creature"
|
||||
:active="activeCreature === creature._id"
|
||||
:targeted="targets.includes(creature._id)"
|
||||
@click="activeCreature = creature._id; targets = []"
|
||||
@target="targets.push(creature._id)"
|
||||
@untarget="untarget(creature._id)"
|
||||
/>
|
||||
<div
|
||||
class="layout column ma-1"
|
||||
style="flex-grow: 0;"
|
||||
<v-row
|
||||
dense
|
||||
class="initiative-row flex-grow-0"
|
||||
style="flex-wrap: nowrap; overflow-x: auto;"
|
||||
@wheel="transformScroll($event)"
|
||||
>
|
||||
<v-btn
|
||||
data-id="select-creatures"
|
||||
class="mb-2"
|
||||
@click="addCreature"
|
||||
<tabletop-creature-card
|
||||
v-for="creature in creatures"
|
||||
:key="creature._id"
|
||||
:model="creature"
|
||||
:active="activeCreature === creature._id"
|
||||
:targeted="targets.includes(creature._id)"
|
||||
@click="activeCreature = creature._id; targets = []"
|
||||
@target="targets.push(creature._id)"
|
||||
@untarget="untarget(creature._id)"
|
||||
/>
|
||||
<div
|
||||
class="layout column ma-1 flex-grow-0"
|
||||
>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
Add Character
|
||||
</v-btn>
|
||||
<v-btn disabled>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
Add Creature
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<tabletop-map class="play-area" />
|
||||
</v-row>
|
||||
<v-btn
|
||||
data-id="select-creatures"
|
||||
class="mb-2"
|
||||
@click="addCreature"
|
||||
>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
Add Character
|
||||
</v-btn>
|
||||
<v-btn disabled>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
Add Creature
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<v-footer
|
||||
app
|
||||
inset
|
||||
class="pa-0"
|
||||
style="background: none; box-shadow: none;"
|
||||
style="background: none;
|
||||
box-shadow: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom:0;
|
||||
right: 0;"
|
||||
>
|
||||
<v-container fluid>
|
||||
<v-row
|
||||
@@ -73,13 +87,13 @@
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-footer>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import addCreaturesToTabletop from '/imports/api/tabletop/methods/addCreaturesToTabletop.js';
|
||||
import TabletopCreatureCard from '/imports/ui/tabletop/TabletopCreatureCard.vue';
|
||||
import TabletopMap from '/imports/ui/tabletop/TabletopMap.vue';
|
||||
import TabletopMap from '/imports/ui/tabletop/map/TabletopMap.vue';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import MiniCharacterSheet from '/imports/ui/creature/character/MiniCharacterSheet.vue';
|
||||
import snackbar from '/imports/ui/components/snackbars/SnackbarQueue.js';
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<template lang="html">
|
||||
<v-card
|
||||
style="height: 150px; min-width: 120px;"
|
||||
style="height: 100px; width: 70px;"
|
||||
:color="active ? 'accent' : ''"
|
||||
hover
|
||||
@mouseover="hover = true"
|
||||
@mouseleave="hover = false"
|
||||
@click="$emit('click')"
|
||||
>
|
||||
<v-progress-linear
|
||||
v-if="model.variables.hitPoints"
|
||||
:value="model.variables.hitPoints.value * 100 / model.variables.hitPoints.total"
|
||||
/>
|
||||
<v-img
|
||||
:src="model.picture"
|
||||
aspect-ratio="1"
|
||||
@@ -52,7 +56,7 @@ export default {
|
||||
|
||||
<style lang="css" scoped>
|
||||
.small-title {
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<template lang="html">
|
||||
<div class="tabletop-map" />
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
// TODO use Pixi.js to render a map
|
||||
export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
</style>
|
||||
89
app/imports/ui/tabletop/map/TabletopMap.vue
Normal file
89
app/imports/ui/tabletop/map/TabletopMap.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div>
|
||||
<canvas
|
||||
ref="map"
|
||||
class="tabletop-map"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as THREE from 'three';
|
||||
import { Tracker } from 'meteor/tracker'
|
||||
import { MapControls } from '/imports/ui/tabletop/three/OrbitControls.js';
|
||||
|
||||
const maps = [
|
||||
{
|
||||
name: 'first map',
|
||||
position: { x: 0, y: 0 },
|
||||
width: 5,
|
||||
height: 5,
|
||||
texture: '/images/battlemap.webp',
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
mounted(){
|
||||
const scene = new THREE.Scene();
|
||||
const perspectiveCam = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
|
||||
perspectiveCam.position.z = 5;
|
||||
const orthoCam = new THREE.OrthographicCamera( -2, 2, 2, -2, 1, 1000 );
|
||||
orthoCam.position.z = 5
|
||||
const activeCamera = orthoCam;
|
||||
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({canvas: this.$refs.map});
|
||||
|
||||
activeCamera.up.set( 0, 0, 1 ); // Use z as upwards
|
||||
const controls = new MapControls( activeCamera, renderer.domElement );
|
||||
|
||||
maps.forEach(map => {
|
||||
const texture = new THREE.TextureLoader().load( map.texture );
|
||||
const material = new THREE.MeshBasicMaterial({ map: texture });
|
||||
material.map.needsUpdate = true;
|
||||
const plane = new THREE.Mesh(new THREE.PlaneGeometry(map.width, map.height), material);
|
||||
plane.overdraw = true;
|
||||
scene.add(plane);
|
||||
});
|
||||
|
||||
/*
|
||||
const axesHelper = new THREE.AxesHelper( 5 );
|
||||
scene.add( axesHelper );
|
||||
*/
|
||||
|
||||
function resizeCanvasToDisplaySize() {
|
||||
const canvas = renderer.domElement;
|
||||
// look up the size the canvas is being displayed
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight - 50;
|
||||
|
||||
// adjust displayBuffer size to match
|
||||
if (canvas.width !== width || canvas.height !== height) {
|
||||
// you must pass false here or three.js sadly fights the browser
|
||||
perspectiveCam.aspect = width / height;
|
||||
orthoCam.left= width / -200;
|
||||
orthoCam.right = width / 200;
|
||||
orthoCam.top = height / 200;
|
||||
orthoCam.bottom = height / -200;
|
||||
perspectiveCam.updateProjectionMatrix();
|
||||
orthoCam.updateProjectionMatrix();
|
||||
controls.update();
|
||||
renderer.setSize(width, height, false);
|
||||
}
|
||||
}
|
||||
function animate() {
|
||||
resizeCanvasToDisplaySize();
|
||||
renderer.render( scene, activeCamera );
|
||||
requestAnimationFrame( animate );
|
||||
}
|
||||
animate();
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tabletop-map {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
1253
app/imports/ui/tabletop/three/OrbitControls.js
Normal file
1253
app/imports/ui/tabletop/three/OrbitControls.js
Normal file
File diff suppressed because it is too large
Load Diff
7
app/package-lock.json
generated
7
app/package-lock.json
generated
@@ -2793,7 +2793,7 @@
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"resolved": false,
|
||||
"resolved": "",
|
||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
||||
},
|
||||
"simpl-schema": {
|
||||
@@ -3041,6 +3041,11 @@
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"three": {
|
||||
"version": "0.139.2",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.139.2.tgz",
|
||||
"integrity": "sha512-gV7q7QY8rogu7HLFZR9cWnOQAUedUhu2WXAnpr2kdXZP9YDKsG/0ychwQvWkZN5PlNw9mv5MoCTin6zNTXoONg=="
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"source-map-support": "^0.5.21",
|
||||
"speakingurl": "^14.0.1",
|
||||
"styles": "^0.2.1",
|
||||
"three": "^0.139.2",
|
||||
"underscore": "^1.13.2",
|
||||
"vue": "2.6.10",
|
||||
"vue-meteor-tracker": "^2.0.0-beta.5",
|
||||
|
||||
BIN
app/public/images/battlemap.webp
Normal file
BIN
app/public/images/battlemap.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 217 KiB |
Reference in New Issue
Block a user