diff --git a/applications/DANCE/Animations/BBoy Look at me be Booooi 202.fbx b/applications/DANCE/Animations/BBoy Look at me be Booooi 202.fbx new file mode 100644 index 0000000..c33fe38 Binary files /dev/null and b/applications/DANCE/Animations/BBoy Look at me be Booooi 202.fbx differ diff --git a/applications/DANCE/Animations/Ballet 372.fbx b/applications/DANCE/Animations/Ballet 372.fbx new file mode 100644 index 0000000..d6c2f60 Binary files /dev/null and b/applications/DANCE/Animations/Ballet 372.fbx differ diff --git a/applications/DANCE/Animations/Belly Dance 590.fbx b/applications/DANCE/Animations/Belly Dance 590.fbx new file mode 100644 index 0000000..1fee69c Binary files /dev/null and b/applications/DANCE/Animations/Belly Dance 590.fbx differ diff --git a/applications/DANCE/Animations/Belly Dancing 643.fbx b/applications/DANCE/Animations/Belly Dancing 643.fbx new file mode 100644 index 0000000..d6c2f60 Binary files /dev/null and b/applications/DANCE/Animations/Belly Dancing 643.fbx differ diff --git a/applications/DANCE/Animations/Beyonce Boogie 235.fbx b/applications/DANCE/Animations/Beyonce Boogie 235.fbx new file mode 100644 index 0000000..99ceaf3 Binary files /dev/null and b/applications/DANCE/Animations/Beyonce Boogie 235.fbx differ diff --git a/applications/DANCE/Animations/Body Rocka 64.fbx b/applications/DANCE/Animations/Body Rocka 64.fbx new file mode 100644 index 0000000..c8cd19c Binary files /dev/null and b/applications/DANCE/Animations/Body Rocka 64.fbx differ diff --git a/applications/DANCE/Animations/Booty Booty Booty 148.fbx b/applications/DANCE/Animations/Booty Booty Booty 148.fbx new file mode 100644 index 0000000..a280acc Binary files /dev/null and b/applications/DANCE/Animations/Booty Booty Booty 148.fbx differ diff --git a/applications/DANCE/Animations/Breakdance 1990 16.fbx b/applications/DANCE/Animations/Breakdance 1990 16.fbx new file mode 100644 index 0000000..d2f7f78 Binary files /dev/null and b/applications/DANCE/Animations/Breakdance 1990 16.fbx differ diff --git a/applications/DANCE/Animations/Chicken Dance 144.fbx b/applications/DANCE/Animations/Chicken Dance 144.fbx new file mode 100644 index 0000000..1db8edc Binary files /dev/null and b/applications/DANCE/Animations/Chicken Dance 144.fbx differ diff --git a/applications/DANCE/Animations/Every day Im shuffelin 226.fbx b/applications/DANCE/Animations/Every day Im shuffelin 226.fbx new file mode 100644 index 0000000..c54b043 Binary files /dev/null and b/applications/DANCE/Animations/Every day Im shuffelin 226.fbx differ diff --git a/applications/DANCE/Animations/Flair it Up 75.fbx b/applications/DANCE/Animations/Flair it Up 75.fbx new file mode 100644 index 0000000..c726fc9 Binary files /dev/null and b/applications/DANCE/Animations/Flair it Up 75.fbx differ diff --git a/applications/DANCE/Animations/Gangnam Style 372.fbx b/applications/DANCE/Animations/Gangnam Style 372.fbx new file mode 100644 index 0000000..9f7208b Binary files /dev/null and b/applications/DANCE/Animations/Gangnam Style 372.fbx differ diff --git a/applications/DANCE/Animations/Hokey Pokey 351.fbx b/applications/DANCE/Animations/Hokey Pokey 351.fbx new file mode 100644 index 0000000..7d26cfe Binary files /dev/null and b/applications/DANCE/Animations/Hokey Pokey 351.fbx differ diff --git a/applications/DANCE/Animations/In Yo Own World 392.fbx b/applications/DANCE/Animations/In Yo Own World 392.fbx new file mode 100644 index 0000000..093a95a Binary files /dev/null and b/applications/DANCE/Animations/In Yo Own World 392.fbx differ diff --git a/applications/DANCE/Animations/Jiggle Jangle 474.fbx b/applications/DANCE/Animations/Jiggle Jangle 474.fbx new file mode 100644 index 0000000..54b6824 Binary files /dev/null and b/applications/DANCE/Animations/Jiggle Jangle 474.fbx differ diff --git a/applications/DANCE/Animations/King Tut 509.fbx b/applications/DANCE/Animations/King Tut 509.fbx new file mode 100644 index 0000000..77d1c88 Binary files /dev/null and b/applications/DANCE/Animations/King Tut 509.fbx differ diff --git a/applications/DANCE/Animations/Mad attitude 184.fbx b/applications/DANCE/Animations/Mad attitude 184.fbx new file mode 100644 index 0000000..7354613 Binary files /dev/null and b/applications/DANCE/Animations/Mad attitude 184.fbx differ diff --git a/applications/DANCE/Animations/Raise the roof 124.fbx b/applications/DANCE/Animations/Raise the roof 124.fbx new file mode 100644 index 0000000..8c500d3 Binary files /dev/null and b/applications/DANCE/Animations/Raise the roof 124.fbx differ diff --git a/applications/DANCE/Animations/Runnin Man 326.fbx b/applications/DANCE/Animations/Runnin Man 326.fbx new file mode 100644 index 0000000..51a9daa Binary files /dev/null and b/applications/DANCE/Animations/Runnin Man 326.fbx differ diff --git a/applications/DANCE/Animations/Salsa Papi 136.fbx b/applications/DANCE/Animations/Salsa Papi 136.fbx new file mode 100644 index 0000000..ec5d887 Binary files /dev/null and b/applications/DANCE/Animations/Salsa Papi 136.fbx differ diff --git a/applications/DANCE/Animations/Salsa and Chips 566.fbx b/applications/DANCE/Animations/Salsa and Chips 566.fbx new file mode 100644 index 0000000..c4a3c0a Binary files /dev/null and b/applications/DANCE/Animations/Salsa and Chips 566.fbx differ diff --git a/applications/DANCE/Animations/Salsa spinna 79.fbx b/applications/DANCE/Animations/Salsa spinna 79.fbx new file mode 100644 index 0000000..07e7d0d Binary files /dev/null and b/applications/DANCE/Animations/Salsa spinna 79.fbx differ diff --git a/applications/DANCE/Animations/Shake it like you mean it 360.fbx b/applications/DANCE/Animations/Shake it like you mean it 360.fbx new file mode 100644 index 0000000..39eafed Binary files /dev/null and b/applications/DANCE/Animations/Shake it like you mean it 360.fbx differ diff --git a/applications/DANCE/Animations/Shoppin like its Costco 479.fbx b/applications/DANCE/Animations/Shoppin like its Costco 479.fbx new file mode 100644 index 0000000..221b725 Binary files /dev/null and b/applications/DANCE/Animations/Shoppin like its Costco 479.fbx differ diff --git a/applications/DANCE/Animations/Slider with cheese 520.fbx b/applications/DANCE/Animations/Slider with cheese 520.fbx new file mode 100644 index 0000000..b7bc6fb Binary files /dev/null and b/applications/DANCE/Animations/Slider with cheese 520.fbx differ diff --git a/applications/DANCE/Animations/Smoov Playa 489.fbx b/applications/DANCE/Animations/Smoov Playa 489.fbx new file mode 100644 index 0000000..059f9b4 Binary files /dev/null and b/applications/DANCE/Animations/Smoov Playa 489.fbx differ diff --git a/applications/DANCE/Animations/Snaker 2step 64.fbx b/applications/DANCE/Animations/Snaker 2step 64.fbx new file mode 100644 index 0000000..a0e2054 Binary files /dev/null and b/applications/DANCE/Animations/Snaker 2step 64.fbx differ diff --git a/applications/DANCE/Animations/So into it 244.fbx b/applications/DANCE/Animations/So into it 244.fbx new file mode 100644 index 0000000..72f25ae Binary files /dev/null and b/applications/DANCE/Animations/So into it 244.fbx differ diff --git a/applications/DANCE/Animations/Swing Batta Batta 742.fbx b/applications/DANCE/Animations/Swing Batta Batta 742.fbx new file mode 100644 index 0000000..4444f3b Binary files /dev/null and b/applications/DANCE/Animations/Swing Batta Batta 742.fbx differ diff --git a/applications/DANCE/Animations/Swing so happy 628.fbx b/applications/DANCE/Animations/Swing so happy 628.fbx new file mode 100644 index 0000000..aa5b2b6 Binary files /dev/null and b/applications/DANCE/Animations/Swing so happy 628.fbx differ diff --git a/applications/DANCE/Animations/Swinga 700.fbx b/applications/DANCE/Animations/Swinga 700.fbx new file mode 100644 index 0000000..ec89a05 Binary files /dev/null and b/applications/DANCE/Animations/Swinga 700.fbx differ diff --git a/applications/DANCE/Animations/Thriller Idle 131.fbx b/applications/DANCE/Animations/Thriller Idle 131.fbx new file mode 100644 index 0000000..2f969d8 Binary files /dev/null and b/applications/DANCE/Animations/Thriller Idle 131.fbx differ diff --git a/applications/DANCE/Animations/Thriller Part 1 896.fbx b/applications/DANCE/Animations/Thriller Part 1 896.fbx new file mode 100644 index 0000000..eb6000e Binary files /dev/null and b/applications/DANCE/Animations/Thriller Part 1 896.fbx differ diff --git a/applications/DANCE/Animations/Thriller Part 2 566.fbx b/applications/DANCE/Animations/Thriller Part 2 566.fbx new file mode 100644 index 0000000..7ec436f Binary files /dev/null and b/applications/DANCE/Animations/Thriller Part 2 566.fbx differ diff --git a/applications/DANCE/Animations/Thriller Part 3 768.fbx b/applications/DANCE/Animations/Thriller Part 3 768.fbx new file mode 100644 index 0000000..b87c720 Binary files /dev/null and b/applications/DANCE/Animations/Thriller Part 3 768.fbx differ diff --git a/applications/DANCE/Animations/Thriller Part 4 1113.fbx b/applications/DANCE/Animations/Thriller Part 4 1113.fbx new file mode 100644 index 0000000..4d85b1b Binary files /dev/null and b/applications/DANCE/Animations/Thriller Part 4 1113.fbx differ diff --git a/applications/DANCE/Animations/Twerk it Twerk it 457.fbx b/applications/DANCE/Animations/Twerk it Twerk it 457.fbx new file mode 100644 index 0000000..35d7118 Binary files /dev/null and b/applications/DANCE/Animations/Twerk it Twerk it 457.fbx differ diff --git a/applications/DANCE/Animations/Twista 284.fbx b/applications/DANCE/Animations/Twista 284.fbx new file mode 100644 index 0000000..28f6383 Binary files /dev/null and b/applications/DANCE/Animations/Twista 284.fbx differ diff --git a/applications/DANCE/Animations/Wavy baby 213.fbx b/applications/DANCE/Animations/Wavy baby 213.fbx new file mode 100644 index 0000000..4544c11 Binary files /dev/null and b/applications/DANCE/Animations/Wavy baby 213.fbx differ diff --git a/applications/DANCE/Animations/Ymca Dance 136.fbx b/applications/DANCE/Animations/Ymca Dance 136.fbx new file mode 100644 index 0000000..8513e35 Binary files /dev/null and b/applications/DANCE/Animations/Ymca Dance 136.fbx differ diff --git a/applications/DANCE/Animations/dance.js b/applications/DANCE/Animations/dance.js new file mode 100644 index 0000000..c9ce2ad --- /dev/null +++ b/applications/DANCE/Animations/dance.js @@ -0,0 +1,6 @@ +var fs = require("fs"); +var dir = fs.readdirSync(__dirname); +var baseUrl = "https://hifi-content.s3.amazonaws.com/milad/ROLC/Organize/O_Projects/Hifi/Scripts/hifi-content/DomainContent/Rust/DanceApp/Animations/"; +var finalArray = dir.map(function(file){ + return baseUrl + file; +}); diff --git a/applications/DANCE/DANCE.js b/applications/DANCE/DANCE.js new file mode 100644 index 0000000..d313e57 --- /dev/null +++ b/applications/DANCE/DANCE.js @@ -0,0 +1,454 @@ +"use strict"; +/* eslint-disable indent */ +// +// Dance-App +// +// Created by Milad Nazeri on 2018-10-11 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +/* globals Tablet, Script, HMD, Controller, Menu */ + +(function () { // BEGIN LOCAL_SCOPE + // Dependencies + // ///////////////////////////////////////////////////////////////////////// + var + appUi = Script.require('appUi') + ; + + // Consts + // ///////////////////////////////////////////////////////////////////////// + var + URL = Script.resolvePath("./Tablet/DANCE_Tablet.html"), + BUTTON_NAME = "DANCE", + PREVIEW_DANCE = "preview_dance", + PREVIEW_DANCE_STOP = "preview_dance_stop", + STOP_DANCE = "stop_dance", + START_DANCING = "start_dancing", + TRY_DANCE = "try_dance", + ADD_DANCE = "add_dance", + REMOVE_DANCE = "remove_dance", + REMOVE_DANCE_FROM_MENU = "remove_dance_from_menu", + UPDATE_DANCE_ARRAY = "update_dance_array", + CURRENT_DANCE = "current_dance", + TOGGLE_HMD = "toggle_hmd", + PREVIEW_TIMEOUT = 10000, + SECOND = 1000, + TABLET_OPEN_TIME = 300, + DEFAULT_START_FRAME = 0, + EVENT_BRIDGE_OPEN_MESSAGE = "eventBridgeOpen", + PREVIEW_DISTANCE = -2, + UPDATE_UI = BUTTON_NAME + "_update_ui" + ; + + // Init + // ///////////////////////////////////////////////////////////////////////// + var + overlay = null, + ui, + lastPreviewTimeStamp, + in3rdPerson = false, + zoomMapping, + numberOfZooms = 3 + ; + + // Constructor + // ///////////////////////////////////////////////////////////////////////// + + // General Dance Objects used + + function DanceAnimation(name, url, frames, fps, icon) { + this.name = name; + this.url = url; + this.startFrame = DEFAULT_START_FRAME; + this.endFrame = frames; + this.fps = fps; + this.duration = (this.endFrame / this.fps) * SECOND; + this.icon = icon; + } + + // Specific Dance Objects used for the dance playlist + + function DanceListEntry(name, url, startFrame, endFrame, duration, fps, icon) { + this.name = name; + this.url = url; + this.startFrame = startFrame; + this.endFrame = endFrame; + this.duration = duration; + this.fps = fps; + this.defaultEnd = endFrame; + this.selected = false; + this.icon = icon; + } + + // Collections + // ///////////////////////////////////////////////////////////////////////// + var + danceUrls = Script.require("./Dance-URLS.js?"+ Date.now()), + dataStore = { + shouldBeRunning: false, + danceArray: [], + currentIndex: 0, + toggleHMD: false, + ui: { + currentDance: false, + danceArray: false + }, + danceObjects: [] + } + ; + + // Helper Functions + // ///////////////////////////////////////////////////////////////////////// + + // Gets the dances from Dance-URLS and makes dance objects + + function splitDanceUrls() { + // Capture the different parts of the Dance URL to be used for the dance object + var regex = /((?:https:|http:|file:\/)\/\/.*\/)([a-zA-Z0-9 ]+) (\d+)(.fbx)/; + danceUrls.sort(function(a,b) { + // Sort the urls by charachter + if (a.toLowerCase() < b.toLowerCase()) { + return -1; + } else if (a > b) { + return 1; + } + return 0; + }).forEach(function(dance, index) { + // Use the regex match to make DanceAnimation objects + var regMatch = regex.exec(dance); + dataStore.danceObjects.push( + new DanceAnimation( + regMatch[2], + dance, + regMatch[3], + 30, + (index + 1) + ".jpg" + ) + ); + }); + } + + // Finds the index that matches an object in an Array. Used to splice/edit dances in our playlist + function findObjectIndexByKey(array, key, value) { + for (var i = 0; i < array.length; i++) { + if (array[i][key] === value) { + return i; + } + } + return null; + } + + // Procedural Functions + // ///////////////////////////////////////////////////////////////////////// + + // Creates an overlay animation in front of you to see what your dance looks like + + function previewDanceAnimation(danceObj) { + if (overlay) { + stopPreviewDanceAnimation(); + } + var localOffset = [0, 0, PREVIEW_DISTANCE], + worldOffset = Vec3.multiplyQbyV(MyAvatar.orientation, localOffset), + modelPosition = Vec3.sum(MyAvatar.position, worldOffset); + + overlay = Overlays.addOverlay("model", { + url: MyAvatar.skeletonModelURL, + position: modelPosition, + animationSettings: { + url: danceObj.url, + fps: danceObj.fps, + loop: true, + running: true, + lastFrame: danceObj.frames + } + }); + dataStore.ui.addThisDance = true; + dataStore.addThisDanceName = danceObj.name; + lastPreviewTimeStamp = Date.now(); + Script.setTimeout(function(){ + var currentTime = Date.now(); + if (currentTime - lastPreviewTimeStamp > PREVIEW_TIMEOUT) { + stopPreviewDanceAnimation(); + } + }, PREVIEW_TIMEOUT + 500); + ui.updateUI(dataStore); + } + + // Stops the overlay preview after a timer is called + + function stopPreviewDanceAnimation() { + + dataStore.ui.addThisDance = false; + dataStore.addThisDanceName = null; + Overlays.deleteOverlay(overlay); + overlay = null; + ui.updateUI(dataStore); + } + + // Called when a dance in UI is picked + + function addDanceAnimation(danceToAdd) { + dataStore.danceArray.push( + new DanceListEntry( + danceToAdd.dance.name, + danceToAdd.dance.url, + danceToAdd.dance.startFrame, + danceToAdd.dance.endFrame, + danceToAdd.dance.duration, + danceToAdd.dance.fps, + danceToAdd.dance.icon + ) + ); + dataStore.danceObjects[danceToAdd.index].selected = true; + dataStore.ui.danceArray = true; + ui.updateUI(dataStore); + } + + // When a dance is removed from your routine, we splice it out from the array + + function removeDanceAnimation(index) { + var danceIndex = findObjectIndexByKey(dataStore.danceObjects, "name", dataStore.danceArray[index].name); + dataStore.danceObjects[danceIndex].selected = false; + dataStore.danceArray.splice(index,1); + if (dataStore.danceArray.length === 0) { + stopDanceAnimation(); + dataStore.ui.danceArray = false; + } + ui.updateUI(dataStore); + } + + // Check to see if wee are in HMD and have it toggled before we play the dances + + function hmdCheck(){ + if (HMD.active && dataStore.toggleHMD) { + playDanceArray(); + } + + if (!HMD.active) { + playDanceArray(); + } + } + + // Init the dance array and plays the first on the list + + function playDanceArray(){ + dataStore.shouldBeRunning = true; + dataStore.currentIndex = 0; + playNextDance(dataStore.currentIndex); + ui.updateUI(dataStore); + } + + // Play the index supplied and then get the next dance ready + + function playNextDance(index) { + if ( index >= dataStore.danceArray.length) { + index = 0; + } + var danceArrayObject = dataStore.danceArray[index]; + dataStore.currentIndex++; + dataStore.currentIndex = + dataStore.currentIndex >= dataStore.danceArray.length + ? 0 + : dataStore.currentIndex; + + tryDanceAnimation(danceArrayObject); + Script.setTimeout(function(){ + if (dataStore.shouldBeRunning) { + playNextDance(dataStore.currentIndex); + } + }, danceArrayObject.duration); + } + + // Executes the actual dance animation + + function tryDanceAnimation(danceObj) { + if (!HMD.active) { + MyAvatar.overrideAnimation(danceObj.url, danceObj.fps, true, danceObj.startFrame, danceObj.endFrame); + + } else { + MyAvatar.overrideAnimation(danceObj.url, danceObj.fps, true, danceObj.startFrame, danceObj.endFrame); + if (!in3rdPerson) { + in3rdPerson = true; + enableZoom(); + } + } + + dataStore.ui.currentDance = true; + dataStore.currentDance = danceObj; + ui.updateUI(dataStore, {slice: CURRENT_DANCE}); + } + + // Emulates the scroll wheel zoom out + + function enableZoom() { + HMD.closeTablet(); + zoomMapping = Controller.newMapping('zoom'); + numberOfZooms = 2; + zoomMapping.from(function () { + numberOfZooms = numberOfZooms - 1; + return numberOfZooms >= 0 ? 1 : ( + zoomMapping.disable(), 0); + }).to(Controller.Actions.BOOM_OUT); + Script.setTimeout(function(){ + HMD.openTablet(); + }, TABLET_OPEN_TIME); + zoomMapping.enable(); + } + + // Emulates the scroll wheel zoom in + + function disableZoom() { + HMD.closeTablet(); + zoomMapping = Controller.newMapping('zoom'); + zoomMapping.enable(); + numberOfZooms = 0; + zoomMapping.from(function () { + numberOfZooms = numberOfZooms + 1; + return numberOfZooms <= 2 ? 1 : ( + zoomMapping.disable(), 0); + }).to(Controller.Actions.BOOM_IN); + Script.setTimeout(function(){ + HMD.openTablet(); + }, TABLET_OPEN_TIME); + zoomMapping.enable(); + } + + // Stop the dance animations + + function stopDanceAnimation() { + MyAvatar.restoreAnimation(); + if (in3rdPerson) { + Camera.mode = "first person"; + disableZoom(); + in3rdPerson = false; + } + dataStore.ui.currentDance = false; + dataStore.currentDance = null; + dataStore.shouldBeRunning = false; + ui.updateUI(dataStore); + } + + // If an update is made to how a dance should be played, replace the original in the array + + function updateDanceArray(danceUpdate) { + dataStore.danceArray[danceUpdate.index] = danceUpdate.dance; + ui.updateUI(dataStore); + } + + // Send an update to the Vue UI + + function updateUI(dataStore, slice) { + if (!slice) { + slice = {}; + } + var messageObject = { + type: UPDATE_UI, + value: dataStore + }; + Object.keys(slice).forEach(function(key){ + if (slice.hasOwnProperty(key)) { + messageObject[key] = slice[key]; + } + }); + ui.sendToHtml(messageObject); + } + + // Stop dancing if the script ends + + function onEnding(){ + MyAvatar.restoreAnimation(); + } + + // Stop dancing if the domain location is changed + + function onDomainChange(){ + MyAvatar.restoreAnimation(); + } + + // Handles if toggleHMD is picked from the UI + + function toggleHMD(){ + dataStore.toggleHMD = !dataStore.toggleHMD; + ui.updateUI(dataStore); + } + + // Handles removing the dance directly from the icon menu + + function removeDanceFromMenu(danceToRemove){ + var index = findObjectIndexByKey(dataStore.danceArray, "name", danceToRemove.dance.name); + if (index > -1) { + dataStore.danceArray.splice(index, 1); + dataStore.danceObjects[danceToRemove.index].selected = false; + } + if (dataStore.danceArray.length === 0) { + stopDanceAnimation(); + dataStore.ui.danceArray = false; + } + ui.updateUI(dataStore); + } + + // Tablet + // ///////////////////////////////////////////////////////////////////////// + function startup() { + ui = new appUi({ + buttonName: BUTTON_NAME, + home: URL, + graphicsDirectory: Script.resolvePath("./icons/tablet-icons/"), + onMessage: onMessage, + updateUI: updateUI + }); + MyAvatar.restoreAnimation(); + + Script.scriptEnding.connect(onEnding); + Window.domainChanged.connect(onDomainChange); + + splitDanceUrls(); + } + + function onMessage(data) { + // EventBridge message from HTML script. + switch (data.type) { + case EVENT_BRIDGE_OPEN_MESSAGE: + ui.updateUI(dataStore); + break; + case TOGGLE_HMD: + toggleHMD(); + break; + case ADD_DANCE: + addDanceAnimation(data.value); + break; + case REMOVE_DANCE: + removeDanceAnimation(data.value); + break; + case REMOVE_DANCE_FROM_MENU: + removeDanceFromMenu(data.value); + break; + case START_DANCING: + hmdCheck(); + break; + case TRY_DANCE: + tryDanceAnimation(data.value); + break; + case UPDATE_DANCE_ARRAY: + updateDanceArray(data.value); + break; + case STOP_DANCE: + stopDanceAnimation(data.value); + break; + case PREVIEW_DANCE: + previewDanceAnimation(data.value); + break; + case PREVIEW_DANCE_STOP: + stopPreviewDanceAnimation(); + break; + } + } + + // Main + // ///////////////////////////////////////////////////////////////////////// + startup(); + +}()); // END LOCAL_SCOPE diff --git a/applications/DANCE/Dance-URLS.js b/applications/DANCE/Dance-URLS.js new file mode 100644 index 0000000..eea7157 --- /dev/null +++ b/applications/DANCE/Dance-URLS.js @@ -0,0 +1,43 @@ +var danceurls = [ + Script.resolvePath('./Animations/Ballet 372.fbx'), + Script.resolvePath('./Animations/BBoy Look at me be Booooi 202.fbx'), + Script.resolvePath('./Animations/Belly Dance 590.fbx'), + Script.resolvePath('./Animations/Snaker 2step 64.fbx'), + Script.resolvePath('./Animations/Beyonce Boogie 235.fbx'), + Script.resolvePath('./Animations/Body Rocka 64.fbx'), + Script.resolvePath('./Animations/Booty Booty Booty 148.fbx'), + Script.resolvePath('./Animations/Breakdance 1990 16.fbx'), + Script.resolvePath('./Animations/Chicken Dance 144.fbx'), + Script.resolvePath('./Animations/Every day Im shuffelin 226.fbx'), + Script.resolvePath('./Animations/Flair it Up 75.fbx'), + Script.resolvePath('./Animations/Gangnam Style 372.fbx'), + Script.resolvePath('./Animations/Hokey Pokey 351.fbx'), + Script.resolvePath('./Animations/In Yo Own World 392.fbx'), + Script.resolvePath('./Animations/Jiggle Jangle 474.fbx'), + Script.resolvePath('./Animations/King Tut 509.fbx'), + Script.resolvePath('./Animations/Mad attitude 184.fbx'), + Script.resolvePath('./Animations/Raise the roof 124.fbx'), + Script.resolvePath('./Animations/Runnin Man 326.fbx'), + Script.resolvePath('./Animations/Salsa and Chips 566.fbx'), + Script.resolvePath('./Animations/Salsa Papi 136.fbx'), + Script.resolvePath('./Animations/Salsa spinna 79.fbx'), + Script.resolvePath('./Animations/Shake it like you mean it 360.fbx'), + Script.resolvePath('./Animations/Shoppin like its Costco 479.fbx'), + Script.resolvePath('./Animations/Slider with cheese 520.fbx'), + Script.resolvePath('./Animations/Smoov Playa 489.fbx'), + Script.resolvePath('./Animations/So into it 244.fbx'), + Script.resolvePath('./Animations/Swing Batta Batta 742.fbx'), + Script.resolvePath('./Animations/Swing so happy 628.fbx'), + Script.resolvePath('./Animations/Swinga 700.fbx'), + Script.resolvePath('./Animations/Thriller Idle 131.fbx'), + Script.resolvePath('./Animations/Thriller Part 1 896.fbx'), + Script.resolvePath('./Animations/Thriller Part 2 566.fbx'), + Script.resolvePath('./Animations/Thriller Part 3 768.fbx'), + Script.resolvePath('./Animations/Thriller Part 4 1113.fbx'), + Script.resolvePath('./Animations/Twerk it Twerk it 457.fbx'), + Script.resolvePath('./Animations/Twista 284.fbx'), + Script.resolvePath('./Animations/Wavy baby 213.fbx'), + Script.resolvePath('./Animations/Ymca Dance 136.fbx') +]; + +module.exports = danceurls; diff --git a/applications/DANCE/Images/Docs/4.jpg b/applications/DANCE/Images/Docs/4.jpg new file mode 100644 index 0000000..9c6bdf8 Binary files /dev/null and b/applications/DANCE/Images/Docs/4.jpg differ diff --git a/applications/DANCE/Images/Screen Shot 2018-11-30 at 1.41.53 PM.png b/applications/DANCE/Images/Screen Shot 2018-11-30 at 1.41.53 PM.png new file mode 100644 index 0000000..fcc8b32 Binary files /dev/null and b/applications/DANCE/Images/Screen Shot 2018-11-30 at 1.41.53 PM.png differ diff --git a/applications/DANCE/README.MD b/applications/DANCE/README.MD new file mode 100644 index 0000000..747e288 --- /dev/null +++ b/applications/DANCE/README.MD @@ -0,0 +1,340 @@ +# So you think you can DANCE! ...app + +DANCE! is a fun tablet application that lets you choose from different [Mixamo](https://www.mixamo.com/) dance animations. Using those animations, we can sequence them together to make your own funky dance routine! + + +From this README you will learn about: +- Using appUi to simplify the HIFI tablet making process +- Applying animations to your Avatar +- Working with Controller Actions +- How the Tablet and Interface communicate together +- Making more complex and interactive apps with the tablet using a framework like Vue.JS + + +# How it works + +Dance animations created in Mixamo are selected through a UI that is built with [Vue.JS](https://vuejs.org/). The animations are placed in an array that is cycled through and switch after the animation’s desired duration time is up. Easy, peezy, Beyonce boogie squeezy. + +![Beyonce boogie](./Images/Docs/4.jpg "Beyonce boogie") + +# Setup + +We first start with a file that lists all our possible dance URLs imported in as an array. + +Mixamo allows you to easily animate a HIFI Avatar Skeleton by importing an existing HIFI Avatar FST file. After customizing the dance moves the way you like, you can then download them and use them to animate your Avatar. + +This app is created with appUi which is a module included in the HIFI standard library to help simplify creating new apps. You can view the module [here](https://github.com/highfidelity/hifi/blob/91df342ae98b763fbe8eb194b0def9308ce66a9d/scripts/modules/appUi.js). There are instructions for how to set it up in the comments. + +The basic configuration looks like this: +``` +var appUi = Script.require('appUi'); +ui = new appUi({ + buttonName: BUTTON_NAME, + home: URL, + graphicsDirectory: Script.resolvePath("./icons/tablet-icons/"), + onMessage: onMessage, + updateUI: updateUI +}); +``` +Home is the main URL for the UI, onMessage is the function used to handle messages from the tablet, and updateUI is a custom function added to appUi that takes care of updating our Vue UI. + +*** + +### Note Re: [Vue.JS](https://vuejs.org/) + +Vue is a declarative JavaScript framework that is like a light-weight version of ReactJS. It takes care of all the data bindings and event handling for you. If you update an object/array contained in it, then the UI will update accordingly. We will not dive into too many Vue specific details here, but to help you understand the code flow, we will cover some of the essential basics. If you have further questions, feel free to ask on the forum! +*** + +# The Main App + +### Startup + +When the app starts, the function ```startup()``` is run. It contains a few basic wirings such as the appUi init above. We also make sure the Avatar's default animation is restored with ```MyAvatar.restoreAnimation()``` before any dancing happens. + +In HIFI, we use a concept called signals/slots on the C++ engine side that connects events with functions on objects. On the JavaScript side, if you ever see any code that says ```ClassName.connect(function)```, what that means is that the Interface client has emitted a signal, and we are connecting a function to run when it is received. + +The functions being connected in this case are ```onEnding``` to the signal ```Script.scriptEnding``` and ```onDomainChange``` to the signal ```Window.domainChanged```. These . run ```MyAvatar.restoreAnimation();``` . We want to make sure we do not continue to dance if the script ends or if we change domains. + +### Modules + +All the URLs are stored in a module file called Dance-URLS.js. If you aren't familiar with Javascript modules and how to use them in HIFI, they are a very nice way to reuse code between applications or to help break up large files to make them more manageable. + +The way module files work is that they are created in a separate file and has a “module.exports” line at the bottom +``` +// Create an object with functions like this: +function functionToUseInModule(){ ... } + +module.exports = { + functionToUseInModule: functionToUseInModule +}; + +// or if you are exporting a single function, array, or string you can do it directly with +module.exports = functionToUseInModule; +``` + +Then in the file you want to use that module in: +``` +var moduleToUse = Script.require("./moduleFile.js"); + +// Using it the first way: +moduleToUse.functionToUseInModule(); + +// using it the second way: +moduleToUse(); +``` + +The Dance-URLS.js is a module with an array that has files named like this: +``` +Script.resolvePath('./Animations/Ballet 372.fbx') +``` +The ```resolvePath``` function gives you an absolute file path to use without knowing it in advance. Very handy if you are moving your files around between testing and/or migrating servers. +The above file includes a name and the number of frames the animation is. + +In the setup function, we run ```splitDanceUrls()``` to create danceObjects. +First we break that string apart with some regex: +``` +var regex = /((?:https:|file:\/)\/\/.*\/)([a-zA-Z0-9 ]+) (\d+)(.fbx)/; +``` +The regex above gives us 4 different capture groups that are between all the ()s +Those capture groups are: +1. The substring before the file name +2. The file name +3. The total number of frames in the animation +4. The extension + +In Javascript, we can create Constructor functions to easily make new objects. +The Constructor that ```splitDanceUrls``` uses looks like this: +``` +function DanceAnimation(name, url, frames, fps, icon) { + this.name = name; + this.url = url; + this.startFrame = DEFAULT_START_FRAME; + this.endFrame = frames; + this.fps = fps; + this.duration = (this.endFrame / this.fps) * SECOND; + this.icon = icon; +} +``` +When you call a constructor function, you create a new object that takes in arguments to help speed up the process by dynamically creating unique objects. Helpful if you have a lot of objects to make that are similar. + +Using the regex above, and iterating over our list of danceUrls, we push to an array of objects created with the following call(paraphrased) +``` +dataStore.danceObjects.push( + new DanceAnimation( + nameFromRegex, DanceURL, totalNumberOfFrames, defaultFPSof30, graphicIconToUseInTheTablet + ) +) +``` + +To sum it up, this function transforms our list of dance animation URLs into usable Dance Animation objects. + +## The DataStore + +So what is the dataStore? Well, it's where the data is stored! :) +It is a collection of data that is important to the UI. This allows a very simple way to update the UI for the Vue framework. The process looks like this: + +DataStore Builds the UI ---> User Interacts with the UI ---> UI sends the change to the dataStore +and the cycle completes creating a one-way flow of data. + +This is what is done in the function updateUI: +``` +function updateUI(dataStore, slice) { + if (!slice) { + slice = {}; + } + var messageObject = { + type: UPDATE_UI, + value: dataStore + }; + Object.keys(slice).forEach(function(key){ + if (slice.hasOwnProperty(key)) { + messageObject[key] = slice[key]; + } + }); + ui.sendToHtml(messageObject); +} +``` +The above checks if you only want to update a slice of data or update the whole thing. The Vue UI takes care of it from there. To simplify things, we generally send the entire dataStore, but there are cases where sending only one slice is important. + +Next, appUi has a method sendToHTML that takes an object and creates a string to send over the EventBridge. The EventBridge is the HIFI class that communicates between different contexts like the Interface and the Tablet. If you weren't using appUi, then you would have to wire the EventBridge yourself. + +Before we talk about the Tablet app itself, let's look over a few of the functions that take care of the bulk of the work: + +### previewDanceAnimation + +This previews creates an animation overlay of your avatar in front of you to preview what the selected dance looks like. In HIFI, overlays are like entities, but only you can see them. They are made with var overlay = Overlay.addOverlay("type", options). To delete the overlay later, we assign a variable overlay returned from addOverlay to capture the overlay’s id. Here we are taking advantage of a model overlay’s ability to play animations. + +We would like the overlay to appear in front of your Avatar. We offset the overlay to appear 1 meter in front of your avatar or -1 on the z axis: +``` +var localOffset = [0, 0, -1], // creates an offset of -1 from a point of origin + worldOffset = Vec3.multiplyQbyV(MyAvatar.orientation, localOffset), // Gets the correct vector by multiplying that offset by your orientation + modelPosition = Vec3.sum(MyAvatar.position, worldOffset); // Adds that value to your current position +``` + +The rest of this function sets up features of the UI. One of the nice things about Vue is you have full control of how your UI looks by assigning flags to your UI, such as when you want a button to show up or not. + +We also include a timeout that checks to see how long this overlay is playing for so we don't get in a bad state where the overlay plays forever for some reason. + +### stopPreviewDanceAnimation + +The main thing here is our deletion of the overlay using ```Overlays.deleteOverlay(overlay)``` +Then we are setting up more UI related flags. After we set those flags, we use the update UI method. + +### addDanceAnimation + +Whenever a user clicks on one of the Dance Animation icons, this function is called. It uses another constructor function based on the original Dance Animation object maker above with a few extra items the dance playlist uses. + +### hmdCheck + +Instead of allowing the user to play the dance array playlist directly, first, we check to see if a user is in HMD using HMD.active and verify if the user checked the option to use the DANCE in HMD. +### enableZoom and disableZoom + +These functions are used to handle dancing in HMD and zoom the user’s camera out programmatically though using the boomIn and boomOut actions. BoomIn and boomOut are only exposed as Controller actions, so we are emulating a user using the scroll wheel to zoom (or “boom”) in and out. [Controller Actions]("https://docs.highfidelity.com/api-reference/namespaces/controller#.Actions") are pre-made functions that can be mapped to a variety of inputs. Let's examine enableZoom, as disableZoom is doing the same thing but reversed: +``` +HMD.closeTablet(); +zoomMapping = Controller.newMapping('zoom'); +numberOfZooms = 2; +zoomMapping.from(function () { + numberOfZooms = numberOfZooms - 1; + return numberOfZooms >= 0 ? 1 : ( + zoomMapping.disable(), 0); +}).to(Controller.Actions.BOOM_OUT); +Script.setTimeout(function(){ + HMD.openTablet(); +}, TABLET_OPEN_TIME); +zoomMapping.enable(); +``` +First, we close the tablet because when we zoom out, we leave the tablet where the first camera position was. +We then create a new Controller mapping for the emulation. These are made by passing in a string of what you would like the mapping to be called. + +Mappings take an input in the .from method and send them to a function in the .to method. When this is enabled with zoomMapping.enable, that function in .from will run every tick and subtract from numberOfZooms until it hits 0. You can think of that as using the scroll wheel numberOfZooms times. + +Most actions take a value from 0 to 1. 0, in this case, means do not do anything, 1 means perform that action. Once we hit 0, we disable the mapping from running. We also set a timer up to bring our tablet back after a short period. + +### playDanceArray + +This is how the danceArray gets kicked off when we click start. This inits us to start from the first dance by setting the ```currentIndex``` to 0 and then passing that to playNextDance, which takes in an index number to play. + +### playNextDance + +We first check that we are not at the end of the list then we get the actual danceObject from our danceArray based on the desired index. +After, we pass this object to ```tryDanceAnimation``` which takes care of the dance animation. After we pass it in, we do a timeout based on how long this danceAnimation should play by its set duration. Then we recursively call playNextDance again with the next index. + +### tryDanceAnimation + +Three things to take note here. + +#1 The animation is used on your avatar by MyAvatar.overrideAnimation. This method replaces your current main animation with the dance animation you have picked. Its parameters are basically the same ones we set in the dance object above. + +#2 If the user is in HMD mode, then the only difference is that we switch their camera mode. everal camera modes include first person, third person, independent, and entity mode. All of them allow different camera operation modes that are described in more depth in our API guide. We switch the camera mode into third person mode. When the user clicks stop, we change the camera mode back to first person. + +#3 We usea UI slice here. This time instead of the normal dataStore only update: +```ui.updateUI(dataStore, {slice: CURRENT_DANCE});``` + +We update only a data slice because we take advantage of the onBlur functionality of HTML inputs so we update the danceArray in real-time. If we didn't do only a slice, the entire app would keep getting dataStore updates which would affect inputting new values to our individual dances. Basically, if you didn't move off in time, the value you entered would go back to where it was before. This makes sure only the section marked to display the current dance is updated. + +### updateDanceArray + +Instead of updating a dance object directly,we simply overwrite the changes from the UI on the danceArray. That way this function is taken care of in just two lines. Wheeew. + +# The Tablet App + +We will not focus too deeply on the tablet app side, except to touch on a few key concepts. Much of it deals with how Vue operates. If anything is too confusing here, the [Vue.JS documentation](https://vuejs.org/v2/guide/) is fantastic. Hopefully, this gives you an idea of how to use Vue in conjunction with HIFI. + +We first begin with the onMessage function that is on the interface app side. + +### onMessage + +In an HTML app, we use a class called the EventBridge to send messages between the tablet's JS files to be received by the interface app. OnMessage handles these messages and uses a switch statement to handle the type. All the messages on the tablet side are set with a type and a value. The type determines which function gets called, and if necessary, passes in a value to be used in the handler function. All messages must be strings. JSON.stringify is used to make sure they are turned into strings so our objects can be handled properly. AppUi takes care of parsing these strings into actual objects inside our onMessage function. + +### General Vue Concepts + +Let's touch on a few key Vue concepts that will help you understand what is happening on the tablet side. First, we include a copy of Vue with: +`````` take out the .min if you would like better debug messages from Vue. + +We give Vue control of a section of our DOM by naming a tag an id we can reference on the JavaScript side. In our case it's a div tag with the id of "app". + +In our tablet JavaScript file, we create the app with: +``` +var app = new Vue({ + el: '#app', + data: { + dataStore: { + ui: { + currentDance: false, + danceList: false + } + } + } +}); +``` +el, is the element we marked in our HTML file that we want to let Vue use. The data field is where the magic of Vue happens. Anytime anything in data is updated, we create an automatic reaction that repaints our UI based on templates we give it. This is generally done in Vue components. + +### Vue components + +Vue components are JavaScript objects that can be used as HTML tags. We have 3 main ones which are ```, , and ``` +These are defined in the tablet JS file. + +Components have the following structure: + +``` +Vue.component('component-name), { // component names are lower case since they are HTML tags + props: ['prop1', 'prop2'], // props are a powerful way to pass data into components and change the way a tag looks/works. + methods: { + function1(){} // methods are functions you can give your component to call in event handlers and expressions. + }, + lifeCycleHooks: function() {}, // there are several such as mounted, unmounted...they are ways you can run a function at certain times during the creation, operation, and destruction of a component + data: function(){ // data is a function that returns an object that your component can reference. It returns an object so each unique + return { // component has their own unique data data, and not shared unless you have a certain reason for that. Your component can reference this as this.dataMember, or dataMember + dataMember: "string" // inside of an expression in your template + } + }, + computed: function(){ // computed is a way that you can manipulate/format data/props coming in and still retain reactivity. + return { + computedMember: function(){ + return formattedData; + } + } + }, + template: // this is a string containing the template in HTML format you would like to use. We use a VSCode plugin is used to give HTML syntax coloring in template strings that are activated by /*html*/ before the template string. + /*html*/` +
+ templates must have only one root element but can contain anything you want. This is the heart of your UI. + {{ dataMember }} // this is a JavaScript expression that evaluates to HTML. +
+ ` +} +``` + +### Vue bindings + +In order to distinguish from normal HTML attributes, Vue uses special bindings that allow you to have access to certain Vue functionality and work reactively with data changes. + +For example, if you want to dynamically change an img tag's source, you would change `````` to ``````. Url, in this case, may be a prop that is passed down, or a member of the data object. Since this is used often, its shorthand is . :src="url". + + +Other handy Vue attributes are v-if which you feed it an expression so it knows whether to render an element or not, v-on is how events are handled like clicking on an element with v-on:click. The shorthand for this would be @click="functionToRun". + +One of the best Vue features we use is v-for. It iterates through an array or object and creates html for each item. For example, we have an array of danceObjects and need to create a component for each. We first create a
root element and give it an attribute of v-for="dance in dances". Then we on put one tag in that div and give it props that customize how each one looks based on the element that is in the array. Updating our data member will automatically refresh this list. So cool! + +Vue has great [documentation](https://vuejs.org/v2/guide/). Look at the code and reference the Vue docs if there is anything you are curious about. Vue is also a great way to organize chunks of similar +HTML sections by creating custom elements. + +# Conclusion + +The dance app was a lot of fun to work on and was a constant source of amusement as well as irritation during all-hands meetings at the virtual office :) + +Some of the takeaways are: +- Using appUi to simplify the tablet making process +- Applying animations to your Avatar +- Working with Controller Actions +- How the Tablet and Interface communicate together +- Making more complex and interactive apps with the tablet using a framework like Vue.JS + +Some ideas for remixing: + +- Make up new dances to use +- Find a way to sync up playlists with people around you so you are dancing together +- Go beyond dances and try using other kinds of animations + +Let us know if you make something new! \ No newline at end of file diff --git a/applications/DANCE/Tablet/Assets/DANCE-a.svg b/applications/DANCE/Tablet/Assets/DANCE-a.svg new file mode 100644 index 0000000..a5d43b1 --- /dev/null +++ b/applications/DANCE/Tablet/Assets/DANCE-a.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Active Notification Indicator + Use this if your app icon includes + an active notification state + + + + + + + + + + + + + + + + + + + + + + + + + + + Maximum Art Limit + + App icon should not exceed this + + bounding area + + + Recommended Art Limit + + App icon should be scaled to fit a + + bounding area of approximately + + this size + + + + + App Icon States and File Naming + + It is necessary to make at least two versions of your app icon, an + + idle (white) state and a active (black) state, and if your app + + includes an active notification indicator, you will need to also + + create an active and idle version with the notification indicator. + + To clearly convey theses states, the following naming + + conventions are typically used: + + Idle: app-name-i.svg + + Active: app-name-a.svg + + Idle with notification: app-name-i-msg.svg + + Active with notification: app-name-a-msg.svg + + + + diff --git a/applications/DANCE/Tablet/Assets/DANCE-i.png b/applications/DANCE/Tablet/Assets/DANCE-i.png new file mode 100644 index 0000000..aed8bce Binary files /dev/null and b/applications/DANCE/Tablet/Assets/DANCE-i.png differ diff --git a/applications/DANCE/Tablet/Assets/DANCE-i.svg b/applications/DANCE/Tablet/Assets/DANCE-i.svg new file mode 100644 index 0000000..81d748e --- /dev/null +++ b/applications/DANCE/Tablet/Assets/DANCE-i.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Active Notification Indicator + Use this if your app icon includes + an active notification state + + + + + + + + + + + + + + + + + + + + + + + + + + + Maximum Art Limit + + App icon should not exceed this + + bounding area + + + Recommended Art Limit + + App icon should be scaled to fit a + + bounding area of approximately + + this size + + + + + App Icon States and File Naming + + It is necessary to make at least two versions of your app icon, an + + idle (white) state and a active (black) state, and if your app + + includes an active notification indicator, you will need to also + + create an active and idle version with the notification indicator. + + To clearly convey theses states, the following naming + + conventions are typically used: + + Idle: app-name-i.svg + + Active: app-name-a.svg + + Idle with notification: app-name-i-msg.svg + + Active with notification: app-name-a-msg.svg + + + + diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/1.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/1.jpg new file mode 100644 index 0000000..b0d440a Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/1.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/10.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/10.jpg new file mode 100644 index 0000000..d4bc6bc Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/10.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/11.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/11.jpg new file mode 100644 index 0000000..2676ac6 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/11.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/12.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/12.jpg new file mode 100644 index 0000000..3dd1286 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/12.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/13.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/13.jpg new file mode 100644 index 0000000..91e8040 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/13.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/14.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/14.jpg new file mode 100644 index 0000000..1432a3d Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/14.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/15.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/15.jpg new file mode 100644 index 0000000..3f1287e Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/15.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/16.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/16.jpg new file mode 100644 index 0000000..0a1c622 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/16.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/17.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/17.jpg new file mode 100644 index 0000000..6c0d257 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/17.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/18.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/18.jpg new file mode 100644 index 0000000..40ead90 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/18.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/19.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/19.jpg new file mode 100644 index 0000000..fca0393 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/19.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/2.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/2.jpg new file mode 100644 index 0000000..dc96966 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/2.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/20.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/20.jpg new file mode 100644 index 0000000..30e91b1 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/20.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/21.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/21.jpg new file mode 100644 index 0000000..00f1949 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/21.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/22.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/22.jpg new file mode 100644 index 0000000..affe6a2 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/22.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/23.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/23.jpg new file mode 100644 index 0000000..23978d7 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/23.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/24.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/24.jpg new file mode 100644 index 0000000..d7d5a12 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/24.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/25.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/25.jpg new file mode 100644 index 0000000..0bcebeb Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/25.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/26.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/26.jpg new file mode 100644 index 0000000..5c43b29 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/26.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/27.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/27.jpg new file mode 100644 index 0000000..12b608a Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/27.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/28.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/28.jpg new file mode 100644 index 0000000..a72bb5b Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/28.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/29.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/29.jpg new file mode 100644 index 0000000..acc9eb2 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/29.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/3.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/3.jpg new file mode 100644 index 0000000..605d77c Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/3.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/30.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/30.jpg new file mode 100644 index 0000000..e9c6667 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/30.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/31.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/31.jpg new file mode 100644 index 0000000..bdd0cb9 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/31.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/32.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/32.jpg new file mode 100644 index 0000000..1987049 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/32.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/33.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/33.jpg new file mode 100644 index 0000000..1d25885 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/33.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/34.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/34.jpg new file mode 100644 index 0000000..d27d1a8 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/34.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/35.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/35.jpg new file mode 100644 index 0000000..32f1f98 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/35.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/36.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/36.jpg new file mode 100644 index 0000000..24bb4ba Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/36.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/37.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/37.jpg new file mode 100644 index 0000000..2838df6 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/37.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/38.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/38.jpg new file mode 100644 index 0000000..cdc81cf Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/38.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/39.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/39.jpg new file mode 100644 index 0000000..f51789d Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/39.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/4.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/4.jpg new file mode 100644 index 0000000..9c6bdf8 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/4.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/5.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/5.jpg new file mode 100644 index 0000000..26898f7 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/5.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/6.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/6.jpg new file mode 100644 index 0000000..75a5bf3 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/6.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/7.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/7.jpg new file mode 100644 index 0000000..827c237 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/7.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/8.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/8.jpg new file mode 100644 index 0000000..c59dc9a Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/8.jpg differ diff --git a/applications/DANCE/Tablet/Assets/Dance-Images/9.jpg b/applications/DANCE/Tablet/Assets/Dance-Images/9.jpg new file mode 100644 index 0000000..7a534f5 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/Dance-Images/9.jpg differ diff --git a/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.eot b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.eot new file mode 100644 index 0000000..93f4bc8 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.eot differ diff --git a/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.svg b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.svg new file mode 100644 index 0000000..4f1fb2e --- /dev/null +++ b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.svg @@ -0,0 +1,157 @@ + + + +Generated by Fontastic.me + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.ttf b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.ttf new file mode 100644 index 0000000..e85c193 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.ttf differ diff --git a/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.woff b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.woff new file mode 100644 index 0000000..534f8e5 Binary files /dev/null and b/applications/DANCE/Tablet/Assets/glyphs/fonts/hifi-glyphs.woff differ diff --git a/applications/DANCE/Tablet/Assets/glyphs/icons-reference.html b/applications/DANCE/Tablet/Assets/glyphs/icons-reference.html new file mode 100644 index 0000000..a6ffbd5 --- /dev/null +++ b/applications/DANCE/Tablet/Assets/glyphs/icons-reference.html @@ -0,0 +1,1216 @@ + + + + + + + Font Reference - HiFi Glyphs + + + + + +
+

HiFi Glyphs

+

This font was created for use in High Fidelity

+

CSS mapping

+
    +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • + + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • + + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
+

Character mapping

+
    +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
+
+ + + diff --git a/applications/DANCE/Tablet/Assets/glyphs/styles.css b/applications/DANCE/Tablet/Assets/glyphs/styles.css new file mode 100644 index 0000000..06c14b1 --- /dev/null +++ b/applications/DANCE/Tablet/Assets/glyphs/styles.css @@ -0,0 +1,481 @@ +@charset "UTF-8"; + +@font-face { + font-family: "hifi-glyphs"; + src:url("fonts/hifi-glyphs.eot"); + src:url("fonts/hifi-glyphs.eot?#iefix") format("embedded-opentype"), + url("fonts/hifi-glyphs.woff") format("woff"), + url("fonts/hifi-glyphs.ttf") format("truetype"), + url("fonts/hifi-glyphs.svg#hifi-glyphs") format("svg"); + font-weight: normal; + font-style: normal; + +} + +[data-icon]:before { + font-family: "hifi-glyphs" !important; + content: attr(data-icon); + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +[class^="icon-"]:before, +[class*=" icon-"]:before { + font-family: "hifi-glyphs" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-hmd:before { + content: "\62"; +} +.icon-2d-screen:before { + content: "\63"; +} +.icon-keyboard:before { + content: "\64"; +} +.icon-hand-controllers:before { + content: "\65"; +} +.icon-headphones-mic:before { + content: "\66"; +} +.icon-gamepad:before { + content: "\67"; +} +.icon-headphones:before { + content: "\68"; +} +.icon-mic:before { + content: "\69"; +} +.icon-upload:before { + content: "\6a"; +} +.icon-script:before { + content: "\6b"; +} +.icon-text:before { + content: "\6c"; +} +.icon-cube:before { + content: "\6d"; +} +.icon-sphere:before { + content: "\6e"; +} +.icon-zone:before { + content: "\6f"; +} +.icon-light:before { + content: "\70"; +} +.icon-web:before { + content: "\71"; +} +.icon-web-2:before { + content: "\72"; +} +.icon-edit:before { + content: "\73"; +} +.icon-directory:before { + content: "\75"; +} +.icon-menu:before { + content: "\76"; +} +.icon-close:before { + content: "\77"; +} +.icon-close-inverted:before { + content: "\78"; +} +.icon-pin:before { + content: "\79"; +} +.icon-pin-inverted:before { + content: "\7a"; +} +.icon-resize-handle:before { + content: "\41"; +} +.icon-diclosure-expand:before { + content: "\42"; +} +.icon-reload-small:before { + content: "\61"; +} +.icon-close-small:before { + content: "\43"; +} +.icon-minimize:before { + content: "\49"; +} +.icon-maximize:before { + content: "\4a"; +} +.icon-maximize-inverted:before { + content: "\4b"; +} +.icon-disclosure-button-expand:before { + content: "\4c"; +} +.icon-disclosure-button-collapse:before { + content: "\4d"; +} +.icon-script-stop:before { + content: "\4e"; +} +.icon-script-reload:before { + content: "\4f"; +} +.icon-script-run:before { + content: "\50"; +} +.icon-script-new:before { + content: "\51"; +} +.icon-hifi-forum:before { + content: "\32"; +} +.icon-hifi-logo-small:before { + content: "\53"; +} +.icon-placemark:before { + content: "\55"; +} +.icon-box:before { + content: "\56"; +} +.icon-community:before { + content: "\30"; +} +.icon-grab-handle:before { + content: "\58"; +} +.icon-search:before { + content: "\59"; +} +.icon-disclosure-collapse:before { + content: "\5a"; +} +.icon-script-upload:before { + content: "\52"; +} +.icon-code:before { + content: "\57"; +} +.icon-avatar:before { + content: "\3c"; +} +.icon-arrows-h:before { + content: "\3a"; +} +.icon-arrows-v:before { + content: "\3b"; +} +.icon-arrows:before { + content: "\60"; +} +.icon-compress:before { + content: "\21"; +} +.icon-expand:before { + content: "\22"; +} +.icon-placemark-1:before { + content: "\23"; +} +.icon-circle:before { + content: "\24"; +} +.icon-hand-pointer:before { + content: "\39"; +} +.icon-plus-square-o:before { + content: "\25"; +} +.icon-square:before { + content: "\27"; +} +.icon-align-center:before { + content: "\38"; +} +.icon-align-justify:before { + content: "\29"; +} +.icon-align-left:before { + content: "\2a"; +} +.icon-align-right:before { + content: "\5e"; +} +.icon-bars:before { + content: "\37"; +} +.icon-circle-slash:before { + content: "\2c"; +} +.icon-sync:before { + content: "\28"; +} +.icon-key:before { + content: "\2d"; +} +.icon-link:before { + content: "\2e"; +} +.icon-location:before { + content: "\2f"; +} +.icon-carat-r:before { + content: "\33"; +} +.icon-carat-l:before { + content: "\34"; +} +.icon-folder-lg:before { + content: "\3e"; +} +.icon-folder-sm:before { + content: "\3f"; +} +.icon-level-up:before { + content: "\31"; +} +.icon-info:before { + content: "\5b"; +} +.icon-question:before { + content: "\5d"; +} +.icon-alert:before { + content: "\2b"; +} +.icon-home:before { + content: "\5f"; +} +.icon-error:before { + content: "\3d"; +} +.icon-settings:before { + content: "\40"; +} +.icon-trash:before { + content: "\7b"; +} +.icon-object-group:before { + content: "\e000"; +} +.icon-cm:before { + content: "\7d"; +} +.icon-msvg:before { + content: "\7e"; +} +.icon-deg:before { + content: "\5c"; +} +.icon-px:before { + content: "\7c"; +} +.icon-m-sq:before { + content: "\e001"; +} +.icon-m-cubed:before { + content: "\e002"; +} +.icon-acceleration:before { + content: "\e003"; +} +.icon-particles:before { + content: "\e004"; +} +.icon-voxels:before { + content: "\e005"; +} +.icon-lock:before { + content: "\e006"; +} +.icon-visible:before { + content: "\e007"; +} +.icon-model:before { + content: "\e008"; +} +.icon-avatar-2:before { + content: "\e009"; +} +.icon-arrow-dn:before { + content: "\35"; +} +.icon-arrow-up:before { + content: "\36"; +} +.icon-time:before { + content: "\e00a"; +} +.icon-transparency:before { + content: "\e00b"; +} +.icon-unmuted:before { + content: "\47"; +} +.icon-user:before { + content: "\e00c"; +} +.icon-edit-pencil:before { + content: "\e00d"; +} +.icon-muted:before { + content: "\48"; +} +.icon-vol-0:before { + content: "\e00e"; +} +.icon-vol-1:before { + content: "\e00f"; +} +.icon-vol-2:before { + content: "\e010"; +} +.icon-vol-3:before { + content: "\e011"; +} +.icon-vol-4:before { + content: "\e012"; +} +.icon-vol-x-0:before { + content: "\e013"; +} +.icon-vol-x-1:before { + content: "\e014"; +} +.icon-vol-x-2:before { + content: "\e015"; +} +.icon-vol-x-3:before { + content: "\e016"; +} +.icon-vol-x-4:before { + content: "\e017"; +} +.icon-share-ext:before { + content: "\e018"; +} +.icon-ellipsis:before { + content: "\e019"; +} +.icon-check:before { + content: "\e01a"; +} +.icon-sliders:before { + content: "\26"; +} +.icon-polyline:before { + content: "\e01b"; +} +.icon-source:before { + content: "\e01c"; +} +.icon-playback-play:before { + content: "\e01d"; +} +.icon-stop-square:before { + content: "\e01e"; +} +.icon-avatar-t-pose:before { + content: "\e01f"; +} +.icon-check-1:before { + content: "\e020"; +} +.icon-exchange:before { + content: "\e021"; +} +.icon-hfc:before { + content: "\e022"; +} +.icon-home-1:before { + content: "\e023"; +} +.icon-private-key:before { + content: "\e024"; +} +.icon-security-pic:before { + content: "\e026"; +} +.icon-wallet:before { + content: "\e027"; +} +.icon-send:before { + content: "\e028"; +} +.icon-password:before { + content: "\e029"; +} +.icon-rez:before { + content: "\e025"; +} +.icon-keyboard-collapse:before { + content: "\e02b"; +} +.icon-image:before { + content: "\e02a"; +} +.icon-environments:before { + content: "\e02c"; +} +.icon-wand:before { + content: "\e02d"; +} +.icon-market:before { + content: "\74"; +} +.icon-wear:before { + content: "\e02e"; +} +.icon-certificate:before { + content: "\e030"; +} +.icon-gift:before { + content: "\e031"; +} +.icon-update:before { + content: "\e032"; +} +.icon-uninstall:before { + content: "\e033"; +} +.icon-install:before { + content: "\e02f"; +} +.icon-ellipsis-vertical:before { + content: "\e034"; +} +.icon-backward:before { + content: "\45"; +} +.icon-40-reload:before { + content: "\46"; +} +.icon-forward:before { + content: "\44"; +} +.icon-avatar-1:before { + content: "\54"; +} diff --git a/applications/DANCE/Tablet/DANCE_Tablet.html b/applications/DANCE/Tablet/DANCE_Tablet.html new file mode 100644 index 0000000..dfde566 --- /dev/null +++ b/applications/DANCE/Tablet/DANCE_Tablet.html @@ -0,0 +1,42 @@ + + + + DANCE + + + + + + + + + + + +
+
+ +
+ +
+ +
+
+ + + + + + + + + diff --git a/applications/DANCE/Tablet/css/app.css b/applications/DANCE/Tablet/css/app.css new file mode 100644 index 0000000..abded75 --- /dev/null +++ b/applications/DANCE/Tablet/css/app.css @@ -0,0 +1,196 @@ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + body { + /* font-family: 'Roboto', sans-serif; */ + /* font-family: 'Black Han Sans', sans-serif; */ + /* font-family: 'Neucha', cursive; */ + /* font-family: 'Audiowide', cursive; */ + /* font-family: 'Nanum Gothic Coding', monospace; */ + font-family: 'Mitr', sans-serif; + /* font-family: 'Roboto', sans-serif; */ + margin: 0; + padding: 0; + } + + .maindiv { + top: 0; + left: 0; + right: 0; + bottom: 0; + } + + .background { + background: linear-gradient(to bottom, #FFAAFF 0%,#2D5D7B 100%); + + } + + .header-background { + background-color: rgb(91,64,250); + } + + .jumbotron-logo { + background-color: rgba(190, 200, 255, 0.0); + } + + .logo { + /* background-color: #C2AFF0; */ + border-color: #FFFFFF !important; + border-width: 1rem !important; + min-height: 1.9rem; + max-height: 1.9rem; + } + + .input-size { + min-width: 5.75rem; + max-width: 5.75rem; + } + + .field-size { + min-width: 5.75rem; + max-width: 5.75rem; + } + + .blue { + background-color: #457EAC; + + } + + .label-text { + position: absolute; + top: 4rem; + left: 2rem; + color: rgb(250,200,220); + } + + .options-left { + position: absolute; + left: 2rem; + top: 5.7rem; + } + + .options-right { + position: absolute; + left: 17rem; + top: 5.1rem; + } + + .dance-name { + position: absolute; + left: 6.55rem; + top: 3.5rem; + font-size: 1.4rem; + vertical-align: baseline; + + } + .divider { + background-color: #FFFFFF; + min-height: 0.05rem; + height: 0.05rem; + } + + .dance-names { + background-color: #9191E9; + + } + + .sticky-top { + background-color: #2D5D7B; + } + + .instructions { + min-height: 6rem; + max-height: 6rem; + } + + .menu { + position: relative; + color: #FFFFFF; + font-size: 1rem; + vertical-align: baseline; + top: 3px; + } + + .delete { + color: #000000; + font-size: 1.5rem; + } + + .grid { + min-width: 85px; + min-height: 170px; + max-width: 85px; + max-height: 170px; + /* height: 20%; */ + } + + .dance-toggle-start { + background-color: rgb(102,151,252); + color: #FFFFFF; + } + + .list-background { + background-color: rgb(102,151,252); + } + + .dance-toggle-stop { + background-color: rgb(237,149,208); + color: #FFFFFF; + } + + .dance { + width: 18% + } + + .border-3 { + border-width:3px !important; + } + + .select-border { + border-width: 2rem; + border-color: white; + } + + .current-dance-background-header { + background-color: rgba(20, 50, 80, 0.6); + background-image: url("./hifi-dance-a.svg"); + } + + .current-dance-background { + background-color: rgba(40, 70, 100, 0.6); + background-image: url("./hifi-dance-a.svg"); + } + + .current-dance-text { + color: rgba(255, 255, 255, 1.0); + } + + .white-text { + color: rgba(255, 255, 255, 1.0); + } + + .red { + color: red; + } + + .transparent { + background-color: rgba(255, 255, 255, 0.0); + } + + .main-font-size { + font-size: 0.75rem; + } + + .list-complete-item { + padding: 4px; + margin-top: 4px; + border: solid 1px; + transition: all 0.2s; + } + + .list-complete-enter, .list-complete-leave-active { + opacity: 0; + } \ No newline at end of file diff --git a/applications/DANCE/Tablet/css/images/hifi-dance-a.svg b/applications/DANCE/Tablet/css/images/hifi-dance-a.svg new file mode 100644 index 0000000..e1f886f --- /dev/null +++ b/applications/DANCE/Tablet/css/images/hifi-dance-a.svg @@ -0,0 +1 @@ +Dance_App-a \ No newline at end of file diff --git a/applications/DANCE/Tablet/css/images/hifi-dance-i.svg b/applications/DANCE/Tablet/css/images/hifi-dance-i.svg new file mode 100644 index 0000000..fab1c82 --- /dev/null +++ b/applications/DANCE/Tablet/css/images/hifi-dance-i.svg @@ -0,0 +1 @@ +Dance_App-i \ No newline at end of file diff --git a/applications/DANCE/Tablet/js/DANCE_Tablet.js b/applications/DANCE/Tablet/js/DANCE_Tablet.js new file mode 100644 index 0000000..a664034 --- /dev/null +++ b/applications/DANCE/Tablet/js/DANCE_Tablet.js @@ -0,0 +1,298 @@ +(function() { + "use strict"; + + // Consts + // ///////////////////////////////////////////////////////////////////////// + var + BUTTON_NAME = "DANCE", + EVENT_BRIDGE_OPEN_MESSAGE = "eventBridgeOpen", + UPDATE_UI = BUTTON_NAME + "_update_ui", + TRY_DANCE = "try_dance", + STOP_DANCE = "stop_dance", + START_DANCING = "start_dancing", + REMOVE_DANCE = "remove_dance", + REMOVE_DANCE_FROM_MENU = "remove_dance_from_menu", + ADD_DANCE = "add_dance", + PREVIEW_DANCE = "preview_dance", + PREVIEW_DANCE_STOP = "preview_dance_stop", + UPDATE_DANCE_ARRAY = "update_dance_array", + CURRENT_DANCE = "current_dance", + TOGGLE_HMD = "toggle_hmd", + EVENTBRIDGE_SETUP_DELAY = 10 + ; + + // Components + // ///////////////////////////////////////////////////////////////////////// + Vue.component('current-dance', { + props: { + add_this_dance: { type: Boolean }, + current_dance: { type: Boolean }, + should_be_running: { type: Boolean }, + dance_array: { type: Boolean }, + add_dance_name: { type: String }, + current_dance_name: { type: String }, + toggle_hmd: {type: Boolean} + }, + methods: { + startDancing(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: START_DANCING + })); + }, + stopDance(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: STOP_DANCE + })); + }, + toggleHMD(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: TOGGLE_HMD + })); + } + }, + template: /*html*/` +
+ +
+
+
+ Preview: + Current: + Choose dances below + + {{current_dance_name}} + + + {{add_dance_name}} + +
+ +
+ + + + + + + + +
+
+
+ + ` + }) + + Vue.component('dance-list-item', { + props: ['dance', 'index'], + data: function() { + return { + clicked: false, + maxEndFrame: this.dance.endFrame + } + }, + methods: { + removeDance(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: REMOVE_DANCE, + value: this.index + })); + }, + onBlur(){ + + var sanitizedObject = Object.assign({}, this.dance, { + startFrame: parseInt(Math.max(this.dance.startFrame, 0)), + endFrame: parseInt(Math.min(this.dance.endFrame, this.maxEndFrame)), + duration: parseInt(Math.max(1, this.dance.duration)), + fps: parseInt(Math.min(this.dance.fps, 500)) + }); + EventBridge.emitWebEvent(JSON.stringify({ + type: UPDATE_DANCE_ARRAY, + value: { + dance: sanitizedObject, + index: this.index + } + })); + }, + onClicked(){ + this.clicked = !this.clicked; + } + }, + template: /*html*/` +
+
+ {{dance.name}} + + + + + + +
+
+
+
+
+
+ Start Frame +
+ +
+
+
+
+
+ End Frame +
+ +
+
+
+
+
+ Duration(ms) +
+ +
+
+
+
+
+ Frames/Sec +
+ +
+
+
+
+
+ ` + }) + + Vue.component('dance-list', { + props: ['dances', 'should_be_running'], + + template: /*html*/` +
+
+
+ +
+ +
+
+ ` + }) + + Vue.component('dance', { + props: ['dance', 'index'], + methods: { + addDance(){ + if (!this.dance.selected) { + EventBridge.emitWebEvent(JSON.stringify({ + type: ADD_DANCE, + value: { + dance: this.dance, + index: this.index + } + })); + } else { + EventBridge.emitWebEvent(JSON.stringify({ + type: REMOVE_DANCE_FROM_MENU, + value: { + dance: this.dance, + index: this.index + } + })); + } + + }, + tryDance(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: TRY_DANCE, + value: this.dance + })); + }, + previewDance(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: PREVIEW_DANCE, + value: this.dance + })); + }, + previewDanceStop(){ + EventBridge.emitWebEvent(JSON.stringify({ + type: PREVIEW_DANCE_STOP, + value: this.dance + })); + }, + }, + template: /*html*/` + + ` + }) + + // App + // ///////////////////////////////////////////////////////////////////////// + var app = new Vue({ + el: '#app', + data: { + dataStore: { + ui: { + currentDance: false, + danceList: false + } + } + } + }); + + // Procedural + // ///////////////////////////////////////////////////////////////////////// + function onScriptEventReceived(message) { + var data; + try { + data = JSON.parse(message); + switch (data.type) { + case UPDATE_UI: + if (data.slice === CURRENT_DANCE) { + app.dataStore.currentDance = data.value.currentDance; + } else { + app.dataStore = data.value; + } + break; + default: + } + } catch (e) { + console.log(e) + return; + } + } + + function onLoad() { + + // Initial button active state is communicated via URL parameter. + // isActive = location.search.replace("?active=", "") === "true"; + + setTimeout(function () { + // Open the EventBridge to communicate with the main script. + // Allow time for EventBridge to become ready. + EventBridge.scriptEventReceived.connect(onScriptEventReceived); + EventBridge.emitWebEvent(JSON.stringify({ + type: EVENT_BRIDGE_OPEN_MESSAGE + })); + }, EVENTBRIDGE_SETUP_DELAY); + } + + // Main + // ///////////////////////////////////////////////////////////////////////// + onLoad(); + +}()); diff --git a/applications/DANCE/icons/tablet-icons/DANCE-a.svg b/applications/DANCE/icons/tablet-icons/DANCE-a.svg new file mode 100644 index 0000000..a5d43b1 --- /dev/null +++ b/applications/DANCE/icons/tablet-icons/DANCE-a.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Active Notification Indicator + Use this if your app icon includes + an active notification state + + + + + + + + + + + + + + + + + + + + + + + + + + + Maximum Art Limit + + App icon should not exceed this + + bounding area + + + Recommended Art Limit + + App icon should be scaled to fit a + + bounding area of approximately + + this size + + + + + App Icon States and File Naming + + It is necessary to make at least two versions of your app icon, an + + idle (white) state and a active (black) state, and if your app + + includes an active notification indicator, you will need to also + + create an active and idle version with the notification indicator. + + To clearly convey theses states, the following naming + + conventions are typically used: + + Idle: app-name-i.svg + + Active: app-name-a.svg + + Idle with notification: app-name-i-msg.svg + + Active with notification: app-name-a-msg.svg + + + + diff --git a/applications/DANCE/icons/tablet-icons/DANCE-i.svg b/applications/DANCE/icons/tablet-icons/DANCE-i.svg new file mode 100644 index 0000000..81d748e --- /dev/null +++ b/applications/DANCE/icons/tablet-icons/DANCE-i.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Active Notification Indicator + Use this if your app icon includes + an active notification state + + + + + + + + + + + + + + + + + + + + + + + + + + + Maximum Art Limit + + App icon should not exceed this + + bounding area + + + Recommended Art Limit + + App icon should be scaled to fit a + + bounding area of approximately + + this size + + + + + App Icon States and File Naming + + It is necessary to make at least two versions of your app icon, an + + idle (white) state and a active (black) state, and if your app + + includes an active notification indicator, you will need to also + + create an active and idle version with the notification indicator. + + To clearly convey theses states, the following naming + + conventions are typically used: + + Idle: app-name-i.svg + + Active: app-name-a.svg + + Idle with notification: app-name-i-msg.svg + + Active with notification: app-name-a-msg.svg + + + + diff --git a/applications/metadata.js b/applications/metadata.js index 616b9a2..c1d037f 100644 --- a/applications/metadata.js +++ b/applications/metadata.js @@ -180,6 +180,15 @@ var metadata = { "applications": "icon": "cam360/resources/images/icons/cam360-i.svg", "caption": "CAM360" }, + { + "isActive": true, + "directory": "DANCE", + "name": "Dance App", + "description": "Dance Like nobody is watching.
You can queue up different dance animations and let your avatar do all the dancing while you sit back and relax.", + "jsfile": "BodyPaint4/BodyPaint4.js", + "icon": "DANCE/icons/tablet-icons/DANCE-i.svg", + "caption": "BODY DANCE" + }, { "isActive": true, "directory": "cameras", @@ -188,6 +197,6 @@ var metadata = { "applications": "jsfile": "cameras/CameraPositions.js", "icon": "cameras/CameraPos-inactive.svg", "caption": "CAMERAS" - } + } ] }; \ No newline at end of file