Add save and restore last user settings;

Fix multiple dynamic brushes not working in some cases (mixing axis
would not work neither for rotation nor for translation);
Fix tablet hovering detection only working for right hand;
This commit is contained in:
Artur Gomes 2017-07-17 16:53:29 +01:00
parent e70303c53e
commit 9d35cdcda3
8 changed files with 250 additions and 46 deletions

View file

@ -6,7 +6,7 @@ function DynamicRotationBrushClass(settings) {
DynamicBrush.call(this);
print("Starting dynamic rotation brush");
this.angle = 0;
this.identityAxis = {x: settings.axis == "pitch" ? 1 : 0, y: settings.axis == "yaw" ? 1 : 0, z: settings.axis == "roll" ? 1 : 0};
this.activeAxis = settings.axis;
}
DynamicRotationBrushClass.prototype.constructor = DynamicRotationBrushClass;
@ -17,10 +17,10 @@ DynamicRotationBrushClass.prototype.DYNAMIC_BRUSH_INCREMENT = 5; //linear increm
DynamicRotationBrushClass.prototype.NAME = "DynamicRotationBrush"; //linear increment of brush size;
DynamicRotationBrushClass.prototype.onUpdate = function(deltaSeconds, entityID) {
print("Dynamic rotation this: " + JSON.stringify(rotation));
this.angle = this.angle + ((deltaSeconds * this.DYNAMIC_BRUSH_INCREMENT)/this.DYNAMIC_BRUSH_TIME);
this.angle = this.angle >= 360 ? 0 : this.angle; //restart hue cycle
var rotation = Vec3.multiply(this.angle, this.identityAxis);
//print("rotation " + JSON.stringify(rotation));
var rotation = Vec3.multiply(this.angle, this.activeAxis);
Entities.editEntity(entityID, {rotation : Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z)});
this.parent.updateUserData(entityID, this);
}

View file

@ -7,7 +7,7 @@ function DynamicTranslationBrushClass(settings) {
print("Starting dynamic Translation brush");
this.startingPosition = null;
this.translation = 0;
this.translationAxis = settings.axis;
this.activeAxis = settings.axis;
}
DynamicTranslationBrushClass.prototype.constructor = DynamicTranslationBrushClass;
@ -19,18 +19,25 @@ DynamicTranslationBrushClass.prototype.MAX_TRANSLATION = 2;
DynamicTranslationBrushClass.prototype.NAME = "DynamicTranslationBrush"; //linear increment of brush size;
DynamicTranslationBrushClass.prototype.onUpdate = function(deltaSeconds, entityID) {
print("translation this: " + JSON.stringify(this) + " : " + JSON.stringify(this.activeAxis));
var currentPosition = Entities.getEntityProperties(entityID).position;
//print("currentPosition " + JSON.stringify(currentPosition));
if (this.startingPosition == null) {
//print("setting starting position ");
this.startingPosition = currentPosition;
}
this.translation = this.translation + ((deltaSeconds * this.DYNAMIC_BRUSH_INCREMENT)/this.DYNAMIC_BRUSH_TIME);
this.translation = Math.abs(this.startingPosition[this.translationAxis]) + this.translation >=
Math.abs(this.startingPosition[this.translationAxis]) + this.MAX_TRANSLATION ? 0 : this.translation;
//print(Math.abs(this.startingPosition.z) + this.translation + " >= " + Math.abs(this.startingPosition.z) + this.MAX_TRANSLATION);
var nextPosition = {x: this.startingPosition.x, y: this.startingPosition.y, z: this.startingPosition.z};
nextPosition[this.translationAxis] = this.translation + nextPosition[this.translationAxis];
var translationVec = Vec3.multiply(this.translation, this.activeAxis);
var nextPosition = {
x: this.startingPosition.x + translationVec.x,
y: this.startingPosition.y + translationVec.y,
z: this.startingPosition.z + translationVec.z
};
if (Vec3.distance(nextPosition, this.startingPosition) > this.MAX_TRANSLATION) {
this.translation = 0;
nextPosition = this.startingPosition;
}
Entities.editEntity(entityID, {position : nextPosition});
this.parent.updateUserData(entityID, this);
}

View file

@ -27,12 +27,13 @@
rightBrush = null,
isBrushColored = false,
isLeftHandDominant = false,
savedSettings = null,
CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint",
isTabletDisplayed = false,
HIFI_POINT_INDEX_MESSAGE_CHANNEL = "Hifi-Point-Index",
HIFI_GRAB_DISABLE_MESSAGE_CHANNEL = "Hifi-Grab-Disable",
HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable",
SCRIPT_PATH = Script.resolvePath('')
SCRIPT_PATH = Script.resolvePath(''),
CONTENT_PATH = SCRIPT_PATH.substr(0, SCRIPT_PATH.lastIndexOf('/')),
ANIMATION_SCRIPT_PATH = Script.resolvePath("content/brushes/dynamicBrushes/dynamicBrushScript.js"),
APP_URL = CONTENT_PATH + "/html/main.html";
@ -54,7 +55,7 @@
function paintBrush(name) {
// Paints in 3D.
var brushName = name,
STROKE_COLOR = { red: 250, green: 0, blue: 0 },
STROKE_COLOR = savedSettings.currentColor,
ERASE_SEARCH_RADIUS = 0.1, // m
STROKE_DIMENSIONS = { x: 10, y: 10, z: 10 },
isDrawingLine = false,
@ -64,9 +65,9 @@
strokeNormals,
strokeWidths,
timeOfLastPoint,
texture = null ,
texture = savedSettings.currentTexture,
//'https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Caris_Tessellation.svg/1024px-Caris_Tessellation.svg.png', // Daantje
strokeWidthMultiplier = 0.6,
strokeWidthMultiplier = savedSettings.currentStrokeWidth,
IS_UV_MODE_STRETCH = true,
MIN_STROKE_LENGTH = 0.005, // m
MIN_STROKE_INTERVAL = 66, // ms
@ -442,7 +443,9 @@
}
function checkTabletHasFocus() {
var controllerPose = getControllerWorldLocation(Controller.Standard.RightHand, true); // note: this will return head pose if hand pose is invalid (third eye)
var controllerPose = isLeftHandDominant ? getControllerWorldLocation(Controller.Standard.LeftHand, true)
: getControllerWorldLocation(Controller.Standard.RightHand, true);
var fingerTipRotation = controllerPose.rotation;//Quat.inverse(MyAvatar.orientation);
var fingerTipPosition = controllerPose.position;//MyAvatar.getJointPosition(handName === "left" ? "LeftHandIndex4" : "RightHandIndex4");
var pickRay = {
@ -528,6 +531,7 @@
}
updateTriggerPress();
updateGripPress();
}
function setUp(onTriggerPressed, onTriggerPressing, onTriggerReleased, onGripPressed) {
@ -825,7 +829,24 @@
//window.close(); //uncomment for qml interface
}
//Load last fingerpaint settings
function restoreLastValues() {
savedSettings = new Object();
savedSettings.currentColor = Settings.getValue("currentColor", {red: 250, green: 0, blue: 0}),
savedSettings.currentStrokeWidth = Settings.getValue("currentStrokeWidth", 0.25);
savedSettings.currentTexture = Settings.getValue("currentTexture", null);
savedSettings.currentDrawingHand = Settings.getValue("currentDrawingHand", false);
savedSettings.currentDynamicBrushes = Settings.getValue("currentDynamicBrushes", []);
savedSettings.customColors = Settings.getValue("customColors", []);
savedSettings.currentTab = Settings.getValue("currentTab", 0);
print("Restoring data: " + JSON.stringify(savedSettings));
isLeftHandDominant = savedSettings.currentDrawingHand;
}
function onButtonClicked() {
restoreLastValues();
isTabletFocused = false; //should always start false so onUpdate updates this variable to true in the beggining
var wasFingerPainting = isFingerPainting;
@ -875,8 +896,16 @@
event = JSON.parse(event);
}
switch (event.type) {
case "ready":
print("Setting up the tablet");
tablet.emitScriptEvent(JSON.stringify(savedSettings));
break;
case "changeTab":
Settings.setValue("currentTab", event.currentTab);
break;
case "changeColor":
if (!isBrushColored) {
Settings.setValue("currentColor", event);
print("changing color...");
leftBrush.changeStrokeColor(event.red, event.green, event.blue);
rightBrush.changeStrokeColor(event.red, event.green, event.blue);
@ -886,9 +915,20 @@
}
break;
case "addCustomColor":
print("Adding custom color");
var customColors = Settings.getValue("customColors", []);
customColors.push({red: event.red, green: event.green, blue: event.blue});
if (customColors.length > event.maxColors) {
customColors.splice(0, 1); //remove first color
}
Settings.setValue("customColors", customColors);
break;
case "changeBrush":
print("abrushType: " + event.brushType);
Settings.setValue("currentTexture", event);
if (event.brushType === "repeat") {
print("brushType: " + event.brushType);
leftBrush.changeUVMode(false);
@ -919,6 +959,7 @@
break;
case "changeLineWidth":
Settings.setValue("currentStrokeWidth", event.brushWidth);
var dim = event.brushWidth*2 +0.1;
print("changing brush width dim to " + dim);
//var dim2 = Math.floor( Math.random()*40 + 5);
@ -940,13 +981,23 @@
break;
case "changeBrushHand":
Settings.setValue("currentDrawingHand", event.DrawingHand == "left");
isLeftHandDominant = event.DrawingHand == "left";
updateHandAnimations();
break;
case "switchDynamicBrush":
var dynamicBrushes = Settings.getValue("currentDynamicBrushes", []);
var brushSettingsIndex = dynamicBrushes.indexOf(event.dynamicBrushID);
if (brushSettingsIndex > -1) { //already exists so we are disabling it
dynamicBrushes.splice(brushSettingsIndex, 1);
} else { //doesn't exist yet so we are just adding it
dynamicBrushes.push(event.dynamicBrushID);
}
Settings.setValue("currentDynamicBrushes", dynamicBrushes);
DynamicBrushesInfo[event.dynamicBrushName].isEnabled = event.enabled;
DynamicBrushesInfo[event.dynamicBrushName].settings = event.settings;
//print("SEtting dynamic brush" + JSON.stringify(DynamicBrushesInfo[event.dynamicBrushName]));
break;
default:

View file

@ -27,14 +27,14 @@
<div><input onchange="setDynamicBrush(this)" animationType="DynamicHueBrush" type="checkbox" id="dynamicBrush"> Use Dynamic Hue </input></div>
<div>
<div style="float: left; margin-right: 20px">
<div><input onchange="setDynamicBrush(this)" settings='{"axis": "yaw"}' animationType="DynamicRotationBrush" type="checkbox" id="dynamicBrush"> Use Yaw Rotation </input></div>
<div><input onchange="setDynamicBrush(this)" settings='{"axis": "pitch"}' animationType="DynamicRotationBrush" type="checkbox" id="dynamicBrush"> Use Pitch Rotation </input></div>
<div><input onchange="setDynamicBrush(this)" settings='{"axis": "roll"}' animationType="DynamicRotationBrush" type="checkbox" id="dynamicBrush"> Use Roll Rotation </input></div>
<div><input onchange="setDynamicBrush(this)" animationType="DynamicRotationBrush" type="checkbox" id="yawRotationBrush"> Use Yaw Rotation </input></div>
<div><input onchange="setDynamicBrush(this)" animationType="DynamicRotationBrush" type="checkbox" id="pitchRotationBrush"> Use Pitch Rotation </input></div>
<div><input onchange="setDynamicBrush(this)" animationType="DynamicRotationBrush" type="checkbox" id="rollRotationBrush"> Use Roll Rotation </input></div>
</div>
<div >
<div><input onchange="setDynamicBrush(this)" settings='{"axis": "x"}' animationType="DynamicTranslationBrush" type="checkbox" id="dynamicBrush"> Use Translation x</input></div>
<div><input onchange="setDynamicBrush(this)" settings='{"axis": "y"}' animationType="DynamicTranslationBrush" type="checkbox" id="dynamicBrush"> Use Translation y</input></div>
<div><input onchange="setDynamicBrush(this)" settings='{"axis": "z"}' animationType="DynamicTranslationBrush" type="checkbox" id="dynamicBrush"> Use Translation z</input></div>
<div><input onchange="setDynamicBrush(this)" animationType="DynamicTranslationBrush" type="checkbox" id="xTranslationBrush"> Use Translation x</input></div>
<div><input onchange="setDynamicBrush(this)" animationType="DynamicTranslationBrush" type="checkbox" id="yTranslationBrush"> Use Translation y</input></div>
<div><input onchange="setDynamicBrush(this)" animationType="DynamicTranslationBrush" type="checkbox" id="zTranslationBrush"> Use Translation z</input></div>
</div>
</div>
@ -121,27 +121,72 @@
<script type="text/javascript">
var currentBrush = 5;
function changePaintBrush(brushIndex) {
var bruhes = document.getElementById("brushesCointainer").children;
bruhes[currentBrush].classList.remove("selectedBrush");
var brushes = document.getElementById("brushesCointainer").children;
brushes[currentBrush].classList.remove("selectedBrush");
currentBrush = brushIndex;
bruhes[currentBrush].classList.add("selectedBrush");
console.log(bruhes[currentBrush].getAttribute("colored"));
brushes[currentBrush].classList.add("selectedBrush");
var changedBrushEvent = {
"type" : "changeBrush",
"brushName": bruhes[currentBrush].id,
"brushType": bruhes[currentBrush].getAttribute("brushType"),
"isColored": bruhes[currentBrush].getAttribute("colored"),
"brushName": brushes[currentBrush].id,
"brushType": brushes[currentBrush].getAttribute("brushType"),
"isColored": brushes[currentBrush].getAttribute("colored"),
"brushID" : brushIndex
};
parent.postMessage(JSON.stringify(changedBrushEvent), "*");
}
function calculateDynamicAxis(checkbox) {
if (checkbox.getAttribute("animationType") == "DynamicRotationBrush") {
return {
axis: {
x: document.getElementById("pitchRotationBrush").checked ? 1 : 0,
y: document.getElementById("rollRotationBrush").checked ? 1 : 0,
z: document.getElementById("yawRotationBrush").checked ? 1 : 0
}
}
}
if (checkbox.getAttribute("animationType") == "DynamicTranslationBrush") {
return {
axis: {
x: document.getElementById("xTranslationBrush").checked ? 1 : 0,
y: document.getElementById("yTranslationBrush").checked ? 1 : 0,
z: document.getElementById("zTranslationBrush").checked ? 1 : 0
}
}
} else return null;
}
function calculateEnabledStatus(checkbox, settings) {
if (checkbox.getAttribute("animationType") == "DynamicHueBrush") {
return checkbox.checked;
}
return settings.axis.x == 1 || settings.axis.y == 1 || settings.axis.z == 1;
}
function setDynamicBrush(checkbox) {
var settings = calculateDynamicAxis(checkbox);
var switchDynamicBrushEvent = {
"type" : "switchDynamicBrush",
"dynamicBrushName": checkbox.getAttribute("animationType"),
"enabled" : checkbox.checked,
"settings" : JSON.parse(checkbox.getAttribute("settings")),
"enabled" : calculateEnabledStatus(checkbox, settings),
"settings" : settings,
"dynamicBrushID" : checkbox.id
};
parent.postMessage(JSON.stringify(switchDynamicBrushEvent), "*");
}
window.addEventListener("message", restoreSavedBrushes, false);
function restoreSavedBrushes() {
var brush = JSON.parse(event.data);
var dynamicBrushes = brush.currentDynamicBrushes;
if (brush.currentTexture) {
changePaintBrush(brush.currentTexture.brushID);
}
if (dynamicBrushes) {
for (var i = 0; i < dynamicBrushes.length; i++) {
document.getElementById(dynamicBrushes[i]).checked = true;
}
}
}
</script>

View file

@ -32,4 +32,14 @@
};
parent.postMessage(JSON.stringify(chooseHandEvent), "*");
}
window.addEventListener("message", restoreCurrentDrawingHand, false);
function restoreCurrentDrawingHand() {
var currentHand = JSON.parse(event.data);
if (currentHand) {
chooseHand(0);
} else {
chooseHand(1);
}
}
</script>

View file

@ -17,7 +17,6 @@
height: 50px;
}
</style>
<div id="colorpicker"></div>
<table id="color_picker_table">
</table>
@ -74,10 +73,10 @@
function update(colorArray) {
// 'jscolor' instance can be used as a string
var changedColorEvent = {
"type" : "changeColor",
"red" : colorArray[0],
"green": colorArray[1],
"blue" : colorArray[2]
"type" : "changeColor",
"red" : colorArray[0],
"green" : colorArray[1],
"blue" : colorArray[2]
};
parent.postMessage(JSON.stringify(changedColorEvent), "*");
}
@ -90,11 +89,11 @@
function updateColorFromCustomPicker(rgbColor) {
var colorArray = [rgbColor.r, rgbColor.g, rgbColor.b];
addCustomColor(colorArray);
addCustomColor(colorArray, true);
update(colorArray);
}
function addCustomColor(colorArray) {
function addCustomColor(colorArray, notify) {
var lastPickedColorsContainer = document.getElementById("last_picked_colors");
var lastPickedColors = lastPickedColorsContainer.children;
for (var i = 0; i < lastPickedColors.length; i++) {
@ -107,7 +106,7 @@
return;
}
}
if (lastPickedColors.length >= COLUMNS) {
if (lastPickedColors.length + 1 >= COLUMNS) {
lastPickedColorsContainer.removeChild(lastPickedColors[lastPickedColors.length-1]);
}
var colorCell = document.createElement("input");
@ -116,5 +115,30 @@
colorCell.className = "color_picker_cell";
colorCell.onclick = function() { updateColorFromTable(this) };
lastPickedColorsContainer.insertBefore(colorCell, lastPickedColorsContainer.firstChild);
if (notify) {
var addCustomColorEvent = {
"type" : "addCustomColor",
"maxColors": COLUMNS,
"red" : colorArray[0],
"green" : colorArray[1],
"blue" : colorArray[2]
};
parent.postMessage(JSON.stringify(addCustomColorEvent), "*");
}
}
window.addEventListener("message", restoreLastColor, false);
function restoreLastColor(event) {
var color = JSON.parse(event.data);
var newColor = color.currentColor;
var customColors = color.customColors;
if (newColor) {
$('#colorpicker').colpickSetColor({'r': newColor.red, 'g': newColor.green, 'b': newColor.blue}, true);
}
if (customColors) {
for (var i = 0; i < customColors.length; i++) {
addCustomColor([customColors[i].red, customColors[i].green, customColors[i].blue], false);
}
}
}
</script>

View file

@ -34,7 +34,7 @@
</style>
<div id="lineWidthContainer">
<input type="range" id="myRange" value=0.25 min=0 max=1 step=0.01 onchange="changeLineWidth(this)">
<input type="range" id="lineWidthRange" value=0.25 min=0 max=1 step=0.01 onchange="changeLineWidth(this)">
<span id="lineWidthText">0.25</span>
</div>
@ -47,4 +47,11 @@
};
parent.postMessage(JSON.stringify(changeLineWidthEvent), "*");
}
window.addEventListener("message", restoreLineWidth, false);
function restoreLineWidth() {
var width = JSON.parse(event.data);
document.getElementById("lineWidthRange").value = width;
changeLineWidth({value: width});
}
</script>

View file

@ -1,7 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<script src="../../html/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="../../html/js/jquery-2.1.4.min.js"></script>
<style>
iframe {
height:100%;
@ -37,19 +38,22 @@
<span class="tabButton" onclick="selectTab(3)"><img class="tabIcon" src="../content/tabicons/linewidthBtn.png"/>Line Width</span>
<span class="tabButton" onclick="selectTab(4)"><img class="tabIcon" src="../content/tabicons/pointingfinger128px.png"/>Hand</span>
</div>
<div id="settingsLoading" style="display: none; background-color: #F44336; color: white; padding: 8px">Loading previous settings</div>
<div id="content">
<iframe frameborder="0" src="colorsTab.html" seamless></iframe>
<iframe frameborder="0" src="brushesTab.html" seamless style="display: none"></iframe>
<iframe frameborder="0" src="eraserTab.html" seamless style="display: none"></iframe>
<iframe frameborder="0" src="lineWidthTab.html" seamless style="display: none"></iframe>
<iframe frameborder="0" src="chooseHandTab.html" seamless style="display: none"></iframe>
<iframe frameborder="0" src="colorsTab.html" onLoad="notifyFrameLoaded(this)" id="colorTab" seamless></iframe>
<iframe frameborder="0" src="brushesTab.html" onLoad="notifyFrameLoaded(this)" id="brushesTab" seamless style="display: none"></iframe>
<iframe frameborder="0" src="eraserTab.html" onLoad="notifyFrameLoaded(this)" id="eraserTab" seamless style="display: none"></iframe>
<iframe frameborder="0" src="lineWidthTab.html" onLoad="notifyFrameLoaded(this)" id="lineWidthTab" seamless style="display: none"></iframe>
<iframe frameborder="0" src="chooseHandTab.html" onLoad="notifyFrameLoaded(this)" id="chooseHandTab" seamless style="display: none"></iframe>
</div>
</body>
</html>
<script type="text/javascript">
var currentTab = 0;
selectTab(0);
var settings;
var iframesLoaded = 0;
function selectTab(tabIndex) {
var tabs = document.getElementById("tabs").children;
var contentPanels = document.getElementById("content").children;
@ -58,6 +62,11 @@
contentPanels[tabIndex].style.display = "block";
tabs[tabIndex].classList.add("selected");
currentTab = tabIndex;
var changeTabEvent = {
"type" : "changeTab",
"currentTab": tabIndex
};
EventBridge.emitWebEvent(JSON.stringify(changeTabEvent));
}
//Accept events from iframes
@ -66,6 +75,57 @@
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
function receiveDataSetup() {
readyEvent = {"type": "ready"};
EventBridge.emitWebEvent(JSON.stringify(readyEvent));
EventBridge.scriptEventReceived.connect(function (message) {
//EventBridge.emitWebEvent("HTML side received message: " + message);
//TODO: read settings and set stuff accordingly
//Web Entity JS message:
//debugger;
settings = JSON.parse(message); //setup the settings so they can be added once the iframes load
setupSettings();
});
}
function notifyFrameLoaded(e) {
iframesLoaded++;
setupSettings();
}
function setupSettings() {
//run only when all the tabs have been loaded and the settings have been received
//no matter the order at which these occur
if (!settings || iframesLoaded != 5) {
return;
}
$("#settingsLoading").hide();
if (settings.currentTab) {
selectTab(settings.currentTab);
}
if (settings.currentColor) {
document.getElementById("colorTab").contentWindow.postMessage(JSON.stringify({currentColor: settings.currentColor}), "*");
}
if (settings.customColors) {
document.getElementById("colorTab").contentWindow.postMessage(JSON.stringify({customColors: settings.customColors}), "*");
}
if (settings.currentTexture) {
document.getElementById("brushesTab").contentWindow.postMessage(JSON.stringify({currentTexture: settings.currentTexture}), "*");
}
if (settings.currentDynamicBrushes) {
document.getElementById("brushesTab").contentWindow.postMessage(JSON.stringify({currentDynamicBrushes: settings.currentDynamicBrushes}), "*");
}
if (settings.currentStrokeWidth) {
document.getElementById("lineWidthTab").contentWindow.postMessage(JSON.stringify(settings.currentStrokeWidth), "*");
}
if (settings.currentDrawingHand) {
document.getElementById("chooseHandTab").contentWindow.postMessage(JSON.stringify(settings.currentDrawingHand), "*");
}
}
$(document).ready(receiveDataSetup);
// Listen to message from child window
eventer(messageEvent,function(e) {
EventBridge.emitWebEvent(e.data);