diff --git a/src/App.vue b/src/App.vue index 0db1af1..11d05ad 100644 --- a/src/App.vue +++ b/src/App.vue @@ -4,23 +4,10 @@ @select:font="setFont($event)" @select:theme="setTheme($event)" /> - +
- +
  • Edit planets by clicking directly inside the graphic or in the table below.
  • Drag planets around to change their distance.
  • @@ -28,8 +15,8 @@
  • The last removed planet can be restored from the table.
  • ONLY THE LAST removed planet can be restored.
  • - - + +
    @@ -43,89 +30,12 @@ import Tips from './components/Tips.vue' import SystemSettings from './components/SystemSettings.vue' import ObjectList from './components/ObjectList.vue' import ObjectSettings from './components/ObjectSettings.vue' -import { MAX_DISTANCE_PLANET } from './constants' +import useObjects from './useObjects' -const star = reactive({ - designation: 'Sol', - radius: 400, -}) - -const objects = reactive(exampleData) +const { selectedObject } = useObjects() const labelFonts = ['xolonium', 'douar', 'lack'] const themes = ['default', 'retro', 'inverse', 'paper'] -const selectedObject = ref(null) -const deletedObject = ref(null) // { index: Number, object: Object } - -function addObject() { - const amount = objects.length - let distance = 100 - - if (amount) { - const lastObject = objects[amount - 1] - distance = Math.min(MAX_DISTANCE_PLANET, lastObject.distance + 2*lastObject.radius + 10) - } - - objects.push({ - type: 'planet', - name: `${star.designation}-${amount + 1}`, - radius: 1, - distance, - satellites: [], - rings: 0, - }) -} - -function editObject (object) { - if (object) { - document.documentElement.scrollTop = 0 - document.body.scrollTop = 0 - } - selectedObject.value = object -} -function selectObject (object) { - selectedObject.value = object -} - -function updateSelectedObject (payload) { - for (const key in payload) { - selectedObject.value[key] = payload[key] - } -} - -function deleteObject (object) { - if (deletedObject.value) { - const lost = deletedObject.value.object.name - const confirmed = confirm(` - Attention! Only the LAST deleted object can be restored. - ${lost} will be lost forever! Proceed anyway?` - ) - if (!confirmed) return - } - - if (!object) object = selectedObject.value - const index = objects.indexOf(object) - - console.debug('deleting object at index', index) - - if (index >= 0) objects.splice(index, 1) - if (object === selectedObject.value) selectedObject.value = null - - deletedObject.value = { index, object } -} - -function restoreDeleted () { - const { index, object } = deletedObject.value - console.debug('restoring deleted object', index) - objects.splice(index, 0, object) - deletedObject.value = null -} - -function autoName (obj) { - const index = objects.indexOf(obj) - return `${star.designation}-${index}` -} - function setTheme (theme) { const classes = document.body.className.split(' ') const currentTheme = classes.find(c => c.startsWith('theme-')) diff --git a/src/app.css b/src/app.css index 4a2fa43..a8aff38 100644 --- a/src/app.css +++ b/src/app.css @@ -210,6 +210,9 @@ h1 { padding: .25em 1em; border-bottom: 2px solid var(--fg-app); } +#object-list tr.selected { + font-weight: bold; +} #object-list .cell { display: flex; justify-content: space-around; diff --git a/src/components/ObjectList.vue b/src/components/ObjectList.vue index 8889927..5db327f 100644 --- a/src/components/ObjectList.vue +++ b/src/components/ObjectList.vue @@ -4,14 +4,15 @@ {{ col }} actions - +
    {{ o[value] }}
    {{ o.satellites.length }}
    - - + + +
    + diff --git a/src/components/ObjectSettings.vue b/src/components/ObjectSettings.vue index 9ed7226..123f301 100644 --- a/src/components/ObjectSettings.vue +++ b/src/components/ObjectSettings.vue @@ -8,51 +8,50 @@
    Distance Δ:
    Radius r:
    Rings:
    - +
    - +
    Other options: - +
    diff --git a/src/components/SystemDiagram.vue b/src/components/SystemDiagram.vue index 716a041..2fe7565 100644 --- a/src/components/SystemDiagram.vue +++ b/src/components/SystemDiagram.vue @@ -34,26 +34,15 @@ diff --git a/src/components/SystemSettings.vue b/src/components/SystemSettings.vue index 4666330..32eba49 100644 --- a/src/components/SystemSettings.vue +++ b/src/components/SystemSettings.vue @@ -4,20 +4,17 @@ @@ -25,22 +22,15 @@ diff --git a/src/example-data.js b/src/example-data.js index 73d4408..1375bb5 100644 --- a/src/example-data.js +++ b/src/example-data.js @@ -1,38 +1,44 @@ -export default [ - { type: 'planet', name: 'Mercury', radius: 1, distance: 100, satellites: [], rings: 0 }, - { type: 'planet', name: 'Venus', radius: 4, distance: 120, satellites: [], rings: 0 }, - { type: 'planet', name: 'Terra', radius: 4, distance: 140, satellites: [ - { name: 'ISS', radius: 1, type: 'station' }, - { name: 'Luna', radius: 2, type: 'moon' }, - ], rings: 0 }, - { type: 'planet', name: 'Mars', radius: 2, distance: 160, satellites: [ - { name: 'MTO', radius: 1, type: 'station' }, - { name: 'Phobos', radius: 1, type: 'moon' }, - { name: 'Daimos', radius: 1, type: 'moon' }, - ], rings: 0 }, - { type: 'planet', name: 'Jupiter', radius: 40, distance: 260, satellites: [ - { name: 'Io', radius: 2, type: 'moon' }, - { name: 'Europa', radius: 2, type: 'moon' }, - { name: 'Ganymede', radius: 4, type: 'moon' }, - { name: 'Callisto', radius: 3, type: 'moon' }, - ], rings: 1 }, - { type: 'planet', name: 'Saturn', radius: 36, distance: 410, satellites: [ - { name: 'Mimas', radius: 1, type: 'moon' }, - { name: 'Enceladus', radius: 1, type: 'moon' }, - { name: 'Tethys', radius: 1, type: 'moon' }, - { name: 'Dione', radius: 1, type: 'moon' }, - { name: 'Rhea', radius: 1, type: 'moon' }, - { name: 'Titan', radius: 3, type: 'moon' }, - { name: 'Iapetus', radius: 1, type: 'moon' }, - ], rings: 5 }, - { type: 'planet', name: 'Uranus', radius: 16, distance: 680, satellites: [ - { name: 'Miranda', radius: 1, type: 'moon' }, - { name: 'Ariel', radius: 1, type: 'moon' }, - { name: 'Umbriel', radius: 1, type: 'moon' }, - { name: 'Titania', radius: 1, type: 'moon' }, - { name: 'Oberon', radius: 1, type: 'moon' }, - ], rings: 2 }, - { type: 'planet', name: 'Neptune', radius: 15, distance: 950, satellites: [ - { name: 'Triton', radius: 1, type: 'moon' }, - ], rings: 0 }, -] +export default { + star: { + designation: 'Sol', + radius: 400, + }, + objects: [ + { type: 'planet', name: 'Mercury', designation: 'Sol-1', radius: 1, distance: 100, satellites: [], rings: 0 }, + { type: 'planet', name: 'Venus', designation: 'Sol-2', radius: 4, distance: 120, satellites: [], rings: 0 }, + { type: 'planet', name: 'Terra', designation: 'Sol-3', radius: 4, distance: 140, satellites: [ + { name: 'ISS', radius: 1, type: 'station' }, + { name: 'Luna', radius: 2, type: 'moon' }, + ], rings: 0 }, + { type: 'planet', name: 'Mars', designation: 'Sol-4', radius: 2, distance: 160, satellites: [ + { name: 'MTO', radius: 1, type: 'station' }, + { name: 'Phobos', radius: 1, type: 'moon' }, + { name: 'Daimos', radius: 1, type: 'moon' }, + ], rings: 0 }, + { type: 'planet', name: 'Jupiter', designation: 'Sol-5', radius: 40, distance: 260, satellites: [ + { name: 'Io', radius: 2, type: 'moon' }, + { name: 'Europa', radius: 2, type: 'moon' }, + { name: 'Ganymede', radius: 4, type: 'moon' }, + { name: 'Callisto', radius: 3, type: 'moon' }, + ], rings: 1 }, + { type: 'planet', name: 'Saturn', designation: 'Sol-6', radius: 36, distance: 410, satellites: [ + { name: 'Mimas', radius: 1, type: 'moon' }, + { name: 'Enceladus', radius: 1, type: 'moon' }, + { name: 'Tethys', radius: 1, type: 'moon' }, + { name: 'Dione', radius: 1, type: 'moon' }, + { name: 'Rhea', radius: 1, type: 'moon' }, + { name: 'Titan', radius: 3, type: 'moon' }, + { name: 'Iapetus', radius: 1, type: 'moon' }, + ], rings: 5 }, + { type: 'planet', name: 'Uranus', designation: 'Sol-7', radius: 16, distance: 680, satellites: [ + { name: 'Miranda', radius: 1, type: 'moon' }, + { name: 'Ariel', radius: 1, type: 'moon' }, + { name: 'Umbriel', radius: 1, type: 'moon' }, + { name: 'Titania', radius: 1, type: 'moon' }, + { name: 'Oberon', radius: 1, type: 'moon' }, + ], rings: 2 }, + { type: 'planet', name: 'Neptune', designation: 'Sol-8', radius: 15, distance: 950, satellites: [ + { name: 'Triton', radius: 1, type: 'moon' }, + ], rings: 0 }, + ], +} diff --git a/src/useObjects.js b/src/useObjects.js new file mode 100644 index 0000000..6c11b68 --- /dev/null +++ b/src/useObjects.js @@ -0,0 +1,117 @@ +import { reactive, ref, computed } from 'vue' +import { + MIN_SIZE_STAR, + MAX_SIZE_STAR, + MIN_SIZE_PLANET, + MAX_SIZE_PLANET, + MIN_DISTANCE_PLANET, + MAX_DISTANCE_PLANET, + MIN_AMOUNT_RINGS, + MAX_AMOUNT_RINGS, +} from './constants' +import { steepCurve } from './utils' +import exampleData from './example-data.js' + + +const star = reactive(exampleData.star) +const objects = reactive(exampleData.objects) +const selectedObject = ref(null) +const deletedObject = ref(null) // { index: Number, object: Object } + +const starCX = computed(() => { + const r = star.radius + return -1 * r * steepCurve(r, 50, 0.955) +}) + +export default function useObjects () { + + function addObject() { + const amount = objects.length + let distance = 100 + + if (amount) { + const lastObject = objects[amount - 1] + distance = Math.min(MAX_DISTANCE_PLANET, lastObject.distance + 2*lastObject.radius + 10) + } + + objects.push({ + type: 'planet', + name: `${star.designation}-${amount + 1}`, + radius: 1, + distance, + satellites: [], + rings: 0, + }) + } + + function updateSelectedObject (payload) { + if (payload.name && !payload.name.trim().length) { + payload.name = selectedObject.value.designation + } + if (payload.distance) { + payload.distance = Math.max(MIN_DISTANCE_PLANET, payload.distance) + payload.distance = Math.min(MAX_DISTANCE_PLANET, payload.distance) + } + if (payload.radius) { + payload.radius = Math.max(MIN_SIZE_PLANET, payload.radius) + payload.radius = Math.min(MAX_SIZE_PLANET, payload.radius) + } + if (payload.rings) { + payload.rings = Math.max(MIN_AMOUNT_RINGS, payload.rings) + payload.rings = Math.min(MAX_AMOUNT_RINGS, payload.rings) + } + for (const key in payload) { + selectedObject.value[key] = payload[key] + } + } + + function deleteObject (object) { + if (deletedObject.value) { + const lost = deletedObject.value.object.name + const confirmed = confirm(` + Attention! Only the LAST deleted object can be restored. + ${lost} will be lost forever! Proceed anyway?` + ) + if (!confirmed) return + } + + if (!object) object = selectedObject.value + const index = objects.indexOf(object) + + console.debug('deleting object at index', index) + + if (index >= 0) objects.splice(index, 1) + if (object === selectedObject.value) selectedObject.value = null + + deletedObject.value = { index, object } + } + + function restoreDeleted () { + const { index, object } = deletedObject.value + console.debug('restoring deleted object', index) + objects.splice(index, 0, object) + deletedObject.value = null + } + + function autoName (object) { + const index = objects.indexOf(object) + return `${star.designation}-${index}` + } + + function randomizeObject (object) { + } + + return { + star, + starCX, + objects, + selectedObject, + deletedObject, + addObject, + deleteObject, + updateSelectedObject, + restoreDeleted, + randomizeObject, + autoName, + } +}