mirror of
https://github.com/haselkern/Minecraft-ArmorStand.git
synced 2025-05-17 15:05:33 +00:00
TroisJS demo
This commit is contained in:
parent
608fce96cc
commit
e46ba54aac
18 changed files with 2725 additions and 12871 deletions
36
README.md
36
README.md
|
@ -1,36 +0,0 @@
|
||||||
# Minecraft Armorstand
|
|
||||||
|
|
||||||
## [Try it out](http://haselkern.github.io/Minecraft-ArmorStand)
|
|
||||||
|
|
||||||
In Minecraft 1.8 armorstands were introduced. Unfortunately, the syntax to summon one is quite confusing and not very intuitive, especially when you're trying to create an awesome pose. This tool provides a graphical interface so that you can focus on the looks and not worry about the code.
|
|
||||||
|
|
||||||
If you would like to see a feature implemented, feel free to open an issue or submit a pull request.
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
To install all required dependencies run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Run this when developing. It will automatically rebuild the project on changes.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run serve
|
|
||||||
```
|
|
||||||
|
|
||||||
The project will automatically build on pushes on the master branch. If you want to build the production build locally, you can run this to generate the `dist` directory.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the linter to check for mistakes:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
Currently Vue does not support Postcss 8, so we use a compatibility build of it. Some time in the future, [this should be upgraded](https://tailwindcss.com/docs/installation#post-css-7-compatibility-build).
|
|
|
@ -1,5 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
'@vue/cli-plugin-babel/preset'
|
|
||||||
]
|
|
||||||
}
|
|
13
index.html
Normal file
13
index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>TroisJS App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
15125
package-lock.json
generated
15125
package-lock.json
generated
File diff suppressed because it is too large
Load diff
58
package.json
58
package.json
|
@ -1,50 +1,22 @@
|
||||||
{
|
{
|
||||||
"name": "minecraft-armorstand",
|
"name": "troisjs-app",
|
||||||
"version": "2.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"dev": "vite",
|
||||||
"build": "vue-cli-service build",
|
"build": "vite build",
|
||||||
"lint": "vue-cli-service lint"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.1",
|
"three": "^0.127.0",
|
||||||
"autoprefixer": "^9.8.6",
|
"troisjs": "^0.3.1",
|
||||||
"core-js": "^3.6.5",
|
"vue": "^3.0.11"
|
||||||
"dat.gui": "^0.7.7",
|
|
||||||
"oimo": "^1.0.9",
|
|
||||||
"postcss": "^7.0.35",
|
|
||||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.2",
|
|
||||||
"three": "^0.123.0",
|
|
||||||
"vue": "^2.6.11",
|
|
||||||
"vue-threejs": "^0.2.0-alpha.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vitejs/plugin-vue": "^1.2.2",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/compiler-sfc": "^3.0.11",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"autoprefixer": "^10.3.1",
|
||||||
"babel-eslint": "^10.1.0",
|
"postcss": "^8.3.6",
|
||||||
"eslint": "^6.7.2",
|
"tailwindcss": "^2.2.7",
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
"vite": "^2.2.3"
|
||||||
"vue-template-compiler": "^2.6.11"
|
}
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:vue/essential",
|
|
||||||
"eslint:recommended"
|
|
||||||
],
|
|
||||||
"parserOptions": {
|
|
||||||
"parser": "babel-eslint"
|
|
||||||
},
|
|
||||||
"rules": {}
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"> 1%",
|
|
||||||
"last 2 versions",
|
|
||||||
"not dead"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
const autoprefixer = require("autoprefixer");
|
|
||||||
const tailwindcss = require("tailwindcss");
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: {
|
||||||
require("tailwindcss"),
|
tailwindcss: {},
|
||||||
require("autoprefixer"),
|
autoprefixer: {},
|
||||||
]
|
},
|
||||||
}
|
}
|
||||||
|
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 360 B |
|
@ -1,17 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
||||||
<link rel="icon" type="image/png" href="<%= BASE_URL %>favicon.png">
|
|
||||||
<title>Minecraft Armorstand</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>
|
|
||||||
<strong>We're sorry but Minecraft Armorstand doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- built files will be auto injected -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
81
src/App.vue
81
src/App.vue
|
@ -1,83 +1,24 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="grid grid-cols-5 min-h-screen bg-gray-700">
|
<div class="flex">
|
||||||
<div ref="rendererwrapper" class="col-span-3">
|
<div class="flex-1 h-screen">
|
||||||
<renderer :obj="renderer" :size="{w: 400, h: 400}">
|
<Scene :rot="roty" />
|
||||||
<scene>
|
|
||||||
<orbit-controls :position="{z: 3}"
|
|
||||||
:rotation="{x: 2, y: 0, z: 3}">
|
|
||||||
<camera :obj="camera"></camera>
|
|
||||||
<light :hex="0xFFFFFF" :position="{x: 100, y: 200, z: 300}"></light>
|
|
||||||
</orbit-controls>
|
|
||||||
<armorstand :pose="pose"></armorstand>
|
|
||||||
</scene>
|
|
||||||
</renderer>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-2">
|
<div class="flex-none w-60">
|
||||||
<card class="text-center">
|
<h1>{{ roty }}</h1>
|
||||||
<h1 class="text-2xl font-bold">Minecraft Armorstand</h1>
|
<input type="range" min="0" max="100" v-model="roty" />
|
||||||
<a
|
|
||||||
title="Source Code"
|
|
||||||
href="https://github.com/haselkern/Minecraft-ArmorStand"
|
|
||||||
class="inline-flex items-center justify-center w-8 h-8 m-2 text-white bg-gray-700 rounded-lg">
|
|
||||||
<i class="fas fa-code"></i>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
title="Help"
|
|
||||||
href="https://haselkern.com/armorstand/"
|
|
||||||
class="inline-flex items-center justify-center w-8 h-8 m-2 text-white bg-gray-700 rounded-lg">
|
|
||||||
<i class="fas fa-question"></i>
|
|
||||||
</a>
|
|
||||||
</card>
|
|
||||||
<card>
|
|
||||||
<h1 class="text-xl">Pose</h1>
|
|
||||||
<!-- TODO modularize sliders -->
|
|
||||||
<table class="w-full">
|
|
||||||
<tr>
|
|
||||||
<td>Rotation</td>
|
|
||||||
<td colspan="3"><input class="w-full" type="range" min="0" max="360"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Head</td>
|
|
||||||
<td><input v-model="pose.head.x" class="w-full" type="range" min="0" max="360"></td>
|
|
||||||
<td><input v-model="pose.head.y" class="w-full" type="range" min="0" max="360"></td>
|
|
||||||
<td><input v-model="pose.head.z" class="w-full" type="range" min="0" max="360"></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Card from "./components/Card";
|
import Scene from "./Scene.vue"
|
||||||
import Armorstand from "./components/Armorstand";
|
|
||||||
import * as THREE from "three";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {Card, Armorstand},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
renderer: new THREE.WebGLRenderer({alpha: true, antialias: true}),
|
roty: 0,
|
||||||
camera: new THREE.PerspectiveCamera(70, 400 / 400, 0.1, 100),
|
}
|
||||||
ambientLight: new THREE.AmbientLight(0x333333),
|
|
||||||
pose: {
|
|
||||||
head: {x: 0, y: 0, z: 0},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.resize();
|
|
||||||
window.resize = this.resize;
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
resize() {
|
|
||||||
let el = this.$refs.rendererwrapper;
|
|
||||||
let w = el.clientWidth;
|
|
||||||
let h = el.clientHeight;
|
|
||||||
this.camera.aspect = w/h;
|
|
||||||
this.camera.updateProjectionMatrix();
|
|
||||||
this.renderer.setSize(w, h);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
components: {Scene},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
39
src/Scene.vue
Normal file
39
src/Scene.vue
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<Renderer ref="renderer" antialias :orbit-ctrl="{ enableDamping: false }" resize="true">
|
||||||
|
<Camera :position="{ z: 10 }" />
|
||||||
|
<Scene>
|
||||||
|
<AmbientLight :intensity="0.3" />
|
||||||
|
<DirectionalLight :intensity="1" :position="{ x: 10, y: 9 }" />
|
||||||
|
<Box ref="box" :rotation="{ y: rot / Math.PI / 4 }">
|
||||||
|
<LambertMaterial />
|
||||||
|
</Box>
|
||||||
|
</Scene>
|
||||||
|
</Renderer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { Box, Camera, LambertMaterial, AmbientLight, Renderer, Scene } from 'troisjs';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ["rot"],
|
||||||
|
mounted() {
|
||||||
|
// const renderer = this.$refs.renderer
|
||||||
|
// const box = this.$refs.box.mesh
|
||||||
|
// renderer.onBeforeRender(() => {
|
||||||
|
// box.rotation.x += 0.01
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
components: { Box, Camera, LambertMaterial, Renderer, Scene },
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
|
@ -1,101 +0,0 @@
|
||||||
<template>
|
|
||||||
<!-- Armorstand -->
|
|
||||||
<object3d :position="{y: -1}">
|
|
||||||
<!-- BasePlate -->
|
|
||||||
<mesh :position="{x: 0, y: -1/32, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorStone"></material>
|
|
||||||
<geometry type="Box" :args="[12/16, 1/16, 12/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
<!-- Little direction indicator for the baseplate -->
|
|
||||||
<mesh :position="{x: 0, y: -1/32, z: 10/16}">
|
|
||||||
<material type="MeshPhong" :color="colorStone"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 1/16, 4/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
<!-- Left leg -->
|
|
||||||
<object3d :position="{x: 2/16, y: 11/16, z: 0}">
|
|
||||||
<mesh :position="{x: 0, y: -5.5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 11/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
</object3d>
|
|
||||||
<!-- Right leg -->
|
|
||||||
<object3d :position="{x: -2/16, y: 11/16, z: 0}">
|
|
||||||
<mesh :position="{x: 0, y: -5.5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 11/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
</object3d>
|
|
||||||
<!-- Left arm -->
|
|
||||||
<object3d :position="{x: 6/16, y: 21/16, z: 0}">
|
|
||||||
<mesh :position="{x: 0, y: -4/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 12/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
</object3d>
|
|
||||||
<!-- Right arm -->
|
|
||||||
<object3d :position="{x: -6/16, y: 21/16, z: 0}">
|
|
||||||
<mesh :position="{x: 0, y: -4/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 12/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
</object3d>
|
|
||||||
<!-- Body -->
|
|
||||||
<object3d :position="{x: 0, y: 23/16, z: 0}">
|
|
||||||
<!-- Hip -->
|
|
||||||
<mesh :position="{x: 0, y: -11/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[8/16, 2/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
<!-- Left side -->
|
|
||||||
<mesh :position="{x: 2/16, y: -6.5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 7/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
<!-- Right side -->
|
|
||||||
<mesh :position="{x: -2/16, y: -6.5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 7/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
<!-- Shoulders -->
|
|
||||||
<mesh :position="{x: 0, y: -1.5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[12/16, 3/16, 3/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
</object3d>
|
|
||||||
<!-- Head -->
|
|
||||||
<object3d :position="{x: 0, y: 22/16, z: 0}" :rotation="head">
|
|
||||||
<!-- Neck -->
|
|
||||||
<mesh :position="{x: 0, y: 3.5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorWood"></material>
|
|
||||||
<geometry type="Box" :args="[2/16, 7/16, 2/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
<!-- Skull -->
|
|
||||||
<mesh :position="{x: 0, y: 5/16, z: 0}">
|
|
||||||
<material type="MeshPhong" :color="colorStone"></material>
|
|
||||||
<geometry type="Box" :args="[10/16, 10/16, 10/16]"></geometry>
|
|
||||||
</mesh>
|
|
||||||
</object3d>
|
|
||||||
</object3d>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: ["pose"],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
colorWood: 0xCC933D,
|
|
||||||
colorStone: 0x888888,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
head() {
|
|
||||||
// TODO Translate rotation Minecraft -> ThreeJS
|
|
||||||
return {
|
|
||||||
x: this.pose.head.x * Math.PI/180,
|
|
||||||
y: this.pose.head.y * Math.PI/180,
|
|
||||||
z: this.pose.head.z * Math.PI/180,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="bg-white rounded-lg m-2 p-2 shadow">
|
|
||||||
<slot/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
6
src/main.css
Normal file
6
src/main.css
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* Do not define your own styles, instead use https://tailwindcss.com/ classes on your elements.
|
||||||
|
*/
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
14
src/main.js
14
src/main.js
|
@ -1,11 +1,5 @@
|
||||||
import Vue from "vue";
|
import { createApp } from 'troisjs'
|
||||||
import App from "./App.vue";
|
import App from './App.vue'
|
||||||
import * as VueThreejs from "vue-threejs";
|
import "./main.css"
|
||||||
import "./assets/tailwind.css";
|
|
||||||
import "../node_modules/@fortawesome/fontawesome-free/css/all.css";
|
|
||||||
|
|
||||||
Vue.use(VueThreejs);
|
createApp(App).mount('#app')
|
||||||
|
|
||||||
new Vue({
|
|
||||||
render: h => h(App),
|
|
||||||
}).$mount('#app');
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
purge: [
|
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
||||||
"./src/**/*.vue",
|
darkMode: false, // or 'media' or 'class'
|
||||||
],
|
theme: {
|
||||||
theme: {},
|
extend: {},
|
||||||
variants: {},
|
},
|
||||||
|
variants: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
}
|
||||||
|
|
7
vite.config.js
Normal file
7
vite.config.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue()]
|
||||||
|
})
|
Loading…
Add table
Add a link
Reference in a new issue