Add drawing in Desktop mode.

Remove dynamic rotation and translation brushes since the movement would
be unsynced after a while, resulting in a poor user experience.
Fix restoring last used settings taking to long, which caused the user
to see the values to change after the tablet application was open.
Fix using a different brush after restarting the app, if drawing before
the brush was reset.
This commit is contained in:
Artur Gomes 2017-07-25 09:55:23 +01:00
parent dffbc442be
commit 5c40a6810e
12 changed files with 340 additions and 358 deletions

View file

@ -144,16 +144,37 @@ void RenderablePolyLineEntityItem::updateGeometry() {
float uCoord, vCoord;
uCoord = 0.0f;
float uCoordInc = 1.0 / (_vertices.size() / 2);
float accumulatedDistance = 0;
float distanceToLastPoint = 0;
float accumulatedDistance = 0.0f;
float distanceToLastPoint = 0.0f;
float accumulatedStrokeWidth = 0.0f;
bool doesStrokeWidthVary = false;
for (int i = 0; i < _strokeWidths.size(); i++) {
if (i > 1 && _strokeWidths[i] != _strokeWidths[i - 1]) {
doesStrokeWidthVary = true;
break;
}
}
for (int i = 0; i < _vertices.size() / 2; i++) {
vCoord = 0.0f;
if (!_isUVModeStretch && vertexIndex > 2) {
distanceToLastPoint = glm::abs(glm::distance(_vertices.at(vertexIndex), _vertices.at(vertexIndex - 2)));
float strokeWidth = i > 1 ? _strokeWidths[i] : (_strokeWidths[i - 2] + _strokeWidths[i - 1]) / 2;
uCoord = (_textureAspectRatio * (accumulatedDistance + distanceToLastPoint)) / strokeWidth;
distanceToLastPoint = glm::distance(_vertices.at(vertexIndex), _vertices.at(vertexIndex - 2));
if (doesStrokeWidthVary) {
//If the stroke varies along the line the texture will stretch more or less depending on the speed
//because it looks better than using the same method as below
accumulatedStrokeWidth += 2 * _strokeWidths[i];
float strokeWidth = 2 * _strokeWidths[i];
float newUcoord = glm::ceil((_textureAspectRatio * (accumulatedDistance + distanceToLastPoint)) / (accumulatedStrokeWidth / i));
float increaseValue = newUcoord - uCoord;
increaseValue = increaseValue > 0 ? increaseValue : 1;
uCoord += increaseValue;
} else {
//If the stroke width is constant then the textures should keep the aspect ratio along the line
uCoord = (_textureAspectRatio * (accumulatedDistance + distanceToLastPoint)) / (2 * _strokeWidths[i]);
}
accumulatedDistance += distanceToLastPoint;
}
@ -183,6 +204,7 @@ void RenderablePolyLineEntityItem::updateGeometry() {
}
*/
}
_pointsChanged = false;
_normalsChanged = false;
_strokeWidthsChanged = false;

View file

@ -10,27 +10,28 @@ function DynamicBrushClass() {}
* @param fingerOverlayID: the id of the overlay that shows over the finger when using fingerpaint
*/
DynamicBrushClass.prototype.onUpdate = function(deltaSeconds, entityIDs) {
//To be implemented on the child
//To be implemented on the child
throw "Abstract method onUpdate not implemented";
}
/**
* This function updates the user data so in the next frame the animation gets the previous values.
*
*
* @param entityID: the id of the polyline being animated
* @param dynamicBrushObject: the animation object (should be a subclass of dynamicBrush)
*/
DynamicBrushClass.prototype.updateUserData = function(entityID, dynamicBrushObject) {
//print("Saving class " + dynamicBrushObject.NAME);
var prevUserData = Entities.getEntityProperties(entityID).userData;
if (prevUserData) {
prevUserData = prevUserData == "" ? new Object() : JSON.parse(prevUserData); //preserve other possible user data
if (prevUserData.animations != null && prevUserData.animations[dynamicBrushObject.NAME] != null) {
delete prevUserData.animations[dynamicBrushObject.NAME];
prevUserData.animations[dynamicBrushObject.NAME] = dynamicBrushObject;
}
Entities.editEntity(entityID, {userData: JSON.stringify(prevUserData)});
}
//print("Saving class " + dynamicBrushObject.NAME);
var prevUserData = Entities.getEntityProperties(entityID).userData;
if (prevUserData) {
prevUserData = prevUserData == "" ? new Object() : JSON.parse(prevUserData); //preserve other possible user data
if (prevUserData.animations != null && prevUserData.animations[dynamicBrushObject.NAME] != null) {
delete prevUserData.animations[dynamicBrushObject.NAME];
prevUserData.animations[dynamicBrushObject.NAME] = dynamicBrushObject;
}
prevUserData.timeFromLastAnimation = Date.now();
Entities.editEntity(entityID, {userData: JSON.stringify(prevUserData)});
}
}
DynamicBrush = DynamicBrushClass;

View file

@ -1,64 +1,34 @@
(function() {
Script.include("dynamicBrushesList.js");
var UPDATE_TIME = 33; //run at aproximatelly 30fps
(function() {
Script.include("dynamicBrushesList.js");
var UPDATE_TIME = 33; //run at aproximatelly 30fps
var self = this;
this.preload = function(entityID) {
print("After adding script 2 : " + JSON.stringify(Entities.getEntityProperties(entityID)));
self.intervalID = Script.setInterval(function() {
if (Vec3.withinEpsilon(MyAvatar.position, Entities.getEntityProperties(entityID).position, 3)) {
var userData = Entities.getEntityProperties(entityID).userData;
//print("UserData: " + userData);
if (userData) {
var userDataObject = JSON.parse(userData);
var animationObject = userDataObject.animations;
//print("Playing animation " + JSON.stringify(animationObject));
var newAnimationObject = null;
Object.keys(animationObject).forEach(function(animationName) {
newAnimationObject = animationObject[animationName];
//print("Proto 0001: " + JSON.stringify(newAnimationObject));
newAnimationObject.__proto__ = DynamicBrushesInfo[animationName].proto;
newAnimationObject.onUpdate(UPDATE_TIME, entityID);
});
}
}
}, UPDATE_TIME);
//print("After adding script 2 : " + JSON.stringify(Entities.getEntityProperties(entityID)));
self.intervalID = Script.setInterval(function() {
if (Vec3.withinEpsilon(MyAvatar.position, Entities.getEntityProperties(entityID).position, 3)) {
var userData = Entities.getEntityProperties(entityID).userData;
//print("UserData: " + userData);
if (userData) {
var userDataObject = JSON.parse(userData);
var animationObject = userDataObject.animations;
//print("Playing animation " + JSON.stringify(animationObject));
var newAnimationObject = null;
if (!userDataObject.timeFromLastAnimation) {
userDataObject.timeFromLastAnimation = Date.now();
}
Object.keys(animationObject).forEach(function(animationName) {
newAnimationObject = animationObject[animationName];
//print("Proto 0001: " + JSON.stringify(newAnimationObject));
newAnimationObject.__proto__ = DynamicBrushesInfo[animationName].proto;
//print("time from last draw " + (Date.now() - userDataObject.animations.timeFromLastDraw));
newAnimationObject.onUpdate(Date.now() - userDataObject.timeFromLastAnimation, entityID);
});
}
}
}, UPDATE_TIME);
};
this.unload = function() {
Script.clearInterval(self.intervalID);
}
this.unload = function() {
Script.clearInterval(self.intervalID);
}
});
/*
(function() {
Script.include("dynamicBrushesList.js");
var UPDATE_TIME = 10;
var self = this;
this.preload = function(entityID) {
Script.setTimeout(playAnimations, UPDATE_TIME);
function playAnimations() {
var userData = Entities.getEntityProperties(entityID).userData;
//print("UserData: " + userData);
if (userData) {
var userDataObject = JSON.parse(userData);
var animationObject = userDataObject.animations;
//print("Playing animation " + JSON.stringify(animationObject));
var newAnimationObject = null;
Object.keys(animationObject).forEach(function(animationName) {
newAnimationObject = animationObject[animationName];
//print("Proto 0001: " + JSON.stringify(newAnimationObject));
newAnimationObject.__proto__ = DynamicBrushesInfo[animationName].proto;
if (userDataObject.isDrawing) {
newAnimationObject.onDraw(UPDATE_TIME, entityID, null);
} else {
newAnimationObject.onUpdate(UPDATE_TIME, entityID, null);
}
});
}
Script.setTimeout(playAnimations, UPDATE_TIME);
}
};
});*/

View file

@ -4,33 +4,33 @@ Script.include("dynamicTranslationBrush.js");
DynamicBrushesInfo = {
DynamicHueBrush: {
isEnabled: false,
proto: DynamicHueBrush.prototype,
settings: null,
isEnabled: false,
proto: DynamicHueBrush.prototype,
settings: null,
},
DynamicRotationBrush: {
isEnabled: false,
proto: DynamicRotationBrush.prototype,
settings: null,
isEnabled: false,
proto: DynamicRotationBrush.prototype,
settings: null,
},
DynamicTranslationBrush: {
isEnabled: false,
proto: DynamicTranslationBrush.prototype,
settings: null,
isEnabled: false,
proto: DynamicTranslationBrush.prototype,
settings: null,
},
}
dynamicBrushFactory = function(dynamicBrushName, settings) {
switch (dynamicBrushName) {
case "DynamicHueBrush":
return new DynamicHueBrush(settings);
case "DynamicRotationBrush":
return new DynamicRotationBrush(settings);
case "DynamicTranslationBrush":
return new DynamicTranslationBrush(settings);
default:
throw new Error("Could not instantiate " + dynamicBrushName);
case "DynamicHueBrush":
return new DynamicHueBrush(settings);
case "DynamicRotationBrush":
return new DynamicRotationBrush(settings);
case "DynamicTranslationBrush":
return new DynamicTranslationBrush(settings);
default:
throw new Error("Could not instantiate " + dynamicBrushName);
}
}

View file

@ -2,11 +2,11 @@
Script.include("dynamicBrush.js");
function DynamicHueBrushClass(settings) {
//dynamic brush vars
DynamicBrush.call(this);
print("Starting dynamic hue brush");
this.hsvColor = {hue: 0, saturation: 1.0, value: 1.0};
this.dynamicColor = {red: 0, green: 0, blue: 0};
//dynamic brush vars
DynamicBrush.call(this);
//print("Starting dynamic hue brush");
this.hsvColor = {hue: 0, saturation: 1.0, value: 1.0};
this.dynamicColor = {red: 0, green: 0, blue: 0};
}
DynamicHueBrushClass.prototype.DYNAMIC_BRUSH_TIME = 10; //inteval in milliseconds to update the brush width;
@ -14,7 +14,7 @@ DynamicHueBrushClass.prototype.DYNAMIC_BRUSH_INCREMENT = 0.5; //linear increment
DynamicHueBrushClass.prototype.NAME = "DynamicHueBrush"; //linear increment of brush size;
DynamicHueBrushClass.prototype.onUpdate = function(deltaSeconds, entityID) {
print("Dynamic Hue Brush");
//print("Dynamic Hue Brush");
this.hsvColor.hue = this.hsvColor.hue + ((deltaSeconds * this.DYNAMIC_BRUSH_INCREMENT)/this.DYNAMIC_BRUSH_TIME);
this.hsvColor.hue = this.hsvColor.hue >= 360 ? 0 : this.hsvColor.hue; //restart hue cycle
this.dynamicColor = this.convertHsvToRgb(this.hsvColor);

View file

@ -2,10 +2,10 @@
Script.include("dynamicBrush.js");
function DynamicRotationBrushClass(settings) {
//dynamic brush vars
DynamicBrush.call(this);
print("Starting dynamic rotation brush");
this.angle = 0;
//dynamic brush vars
DynamicBrush.call(this);
//print("Starting dynamic rotation brush");
this.angle = 0;
this.activeAxis = settings.axis;
}
@ -17,7 +17,7 @@ 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));
//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.activeAxis);

View file

@ -2,12 +2,12 @@
Script.include("dynamicBrush.js");
function DynamicTranslationBrushClass(settings) {
//dynamic brush vars
DynamicBrush.call(this);
print("Starting dynamic Translation brush");
this.startingPosition = null;
this.translation = 0;
this.activeAxis = settings.axis;
//dynamic brush vars
DynamicBrush.call(this);
//print("Starting dynamic Translation brush");
this.startingPosition = null;
this.translation = 0;
this.activeAxis = settings.axis;
}
DynamicTranslationBrushClass.prototype.constructor = DynamicTranslationBrushClass;
@ -19,25 +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) {
this.startingPosition = currentPosition;
}
this.translation = this.translation + ((deltaSeconds * this.DYNAMIC_BRUSH_INCREMENT)/this.DYNAMIC_BRUSH_TIME);
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
};
//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) {
this.startingPosition = currentPosition;
}
this.translation = this.translation + ((deltaSeconds * this.DYNAMIC_BRUSH_INCREMENT)/this.DYNAMIC_BRUSH_TIME);
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;
}
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,6 +27,7 @@
rightBrush = null,
isBrushColored = false,
isLeftHandDominant = false,
isMouseDrawing = false,
savedSettings = null,
CONTROLLER_MAPPING_NAME = "com.highfidelity.fingerPaint",
isTabletDisplayed = false,
@ -45,11 +46,11 @@
//var window = null;
//var inkSource = null;
var inkSourceOverlay = null;
// Set path for finger paint hand animations
var RIGHT_ANIM_URL = Script.resourcesPath() + 'avatar/animations/touch_point_closed_right.fbx';
var inkSourceOverlay = null;
// Set path for finger paint hand animations
var RIGHT_ANIM_URL = Script.resourcesPath() + 'avatar/animations/touch_point_closed_right.fbx';
var LEFT_ANIM_URL = Script.resourcesPath() + 'avatar/animations/touch_point_closed_left.fbx';
var RIGHT_ANIM_URL_OPEN = Script.resourcesPath() + 'avatar/animations/touch_point_open_right.fbx';
var RIGHT_ANIM_URL_OPEN = Script.resourcesPath() + 'avatar/animations/touch_point_open_right.fbx';
var LEFT_ANIM_URL_OPEN = Script.resourcesPath() + 'avatar/animations/touch_point_open_left.fbx';
function paintBrush(name) {
@ -66,10 +67,10 @@
strokeNormals,
strokeWidths,
timeOfLastPoint,
texture = savedSettings.currentTexture,
texture = CONTENT_PATH + "/" + savedSettings.currentTexture.brushName,
//'https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Caris_Tessellation.svg/1024px-Caris_Tessellation.svg.png', // Daantje
strokeWidthMultiplier = savedSettings.currentStrokeWidth,
IS_UV_MODE_STRETCH = true,
strokeWidthMultiplier = savedSettings.currentStrokeWidth * 2 + 0.1,
IS_UV_MODE_STRETCH = savedSettings.currentTexture.brushType == "stretch",
MIN_STROKE_LENGTH = 0.005, // m
MIN_STROKE_INTERVAL = 66, // ms
MAX_POINTS_PER_LINE = 70; // Hard-coded limit in PolyLineEntityItem.h.
@ -101,8 +102,8 @@
function setTriggerPressureWidthEnabled(isEnabled) {
isTriggerPressureWidthEnabled = isEnabled;
}
function changeUVMode(isUVModeStretch) {
function changeUVMode(isUVModeStretch) {
IS_UV_MODE_STRETCH = isUVModeStretch;
}
@ -113,7 +114,7 @@
function getEntityID() {
return entityID;
}
function changeTexture(textureURL) {
texture = textureURL;
}
@ -161,10 +162,8 @@
normals: strokeNormals,
strokeWidths: strokeWidths,
textures: texture, // Daantje
isUVModeStretch: IS_UV_MODE_STRETCH,
isUVModeStretch: IS_UV_MODE_STRETCH,
dimensions: STROKE_DIMENSIONS,
shapeType: "box",
collisionless: true,
});
isDrawingLine = true;
addAnimationToBrush(entityID);
@ -206,6 +205,8 @@
normals: strokeNormals,
strokeWidths: strokeWidths
});
print(JSON.stringify(Entities.getEntityProperties(entityID)));
}
}
@ -309,7 +310,7 @@
getStrokeColor: getStrokeColor,
getStrokeWidth: getStrokeWidth,
getEntityID: getEntityID,
changeUVMode: changeUVMode,
changeUVMode: changeUVMode,
setTriggerPressureWidthEnabled: setTriggerPressureWidthEnabled
};
}
@ -562,7 +563,7 @@
//Entities
//if (inkSource){
// Entities.deleteEntity(inkSource);
// inkSource = null;
// inkSource = null;
//}
}
@ -601,86 +602,86 @@
pointIndex: !enabled
}), true);
}
function updateHandAnimations(){
var ANIM_URL = (isLeftHandDominant? LEFT_ANIM_URL: RIGHT_ANIM_URL );
var ANIM_OPEN = (isLeftHandDominant? LEFT_ANIM_URL_OPEN: RIGHT_ANIM_URL_OPEN );
var handLiteral = (isLeftHandDominant? "left": "right" );
function updateHandAnimations(){
var ANIM_URL = (isLeftHandDominant? LEFT_ANIM_URL: RIGHT_ANIM_URL );
var ANIM_OPEN = (isLeftHandDominant? LEFT_ANIM_URL_OPEN: RIGHT_ANIM_URL_OPEN );
var handLiteral = (isLeftHandDominant? "left": "right" );
//Clear previous hand animation override
restoreAllHandAnimations();
//"rightHandGraspOpen","rightHandGraspClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "HandGraspOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "HandGraspClosed", ANIM_URL, 30, false, 19, 20);
//Clear previous hand animation override
restoreAllHandAnimations();
//"rightHandGraspOpen","rightHandGraspClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "HandGraspOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "HandGraspClosed", ANIM_URL, 30, false, 19, 20);
//"rightIndexPointOpen","rightIndexPointClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointClosed", ANIM_URL, 30, false, 19, 20);
//"rightIndexPointOpen","rightIndexPointClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointClosed", ANIM_URL, 30, false, 19, 20);
//"rightThumbRaiseOpen","rightThumbRaiseClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "ThumbRaiseOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "ThumbRaiseClosed", ANIM_URL, 30, false, 19, 20);
//"rightThumbRaiseOpen","rightThumbRaiseClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "ThumbRaiseOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "ThumbRaiseClosed", ANIM_URL, 30, false, 19, 20);
//"rightIndexPointAndThumbRaiseOpen","rightIndexPointAndThumbRaiseClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointAndThumbRaiseOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointAndThumbRaiseClosed", ANIM_URL, 30, false, 19, 20);
//turn off lasers and other interactions
Messages.sendLocalMessage("Hifi-Hand-Disabler", "none");
Messages.sendLocalMessage("Hifi-Hand-Disabler", handLiteral);
//update ink Source
//"rightIndexPointAndThumbRaiseOpen","rightIndexPointAndThumbRaiseClosed",
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointAndThumbRaiseOpen", ANIM_OPEN, 30, false, 19, 20);
MyAvatar.overrideRoleAnimation(handLiteral + "IndexPointAndThumbRaiseClosed", ANIM_URL, 30, false, 19, 20);
//turn off lasers and other interactions
Messages.sendLocalMessage("Hifi-Hand-Disabler", "none");
Messages.sendLocalMessage("Hifi-Hand-Disabler", handLiteral);
//update ink Source
var strokeColor = leftBrush.getStrokeColor();
var strokeWidth = leftBrush.getStrokeWidth()*0.06;
if (inkSourceOverlay == null){
inkSourceOverlay = Overlays.addOverlay("sphere", { parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(handLiteral === "left" ? "LeftHandIndex4" : "RightHandIndex4"), localPosition: { x: 0, y: 0, z: 0 }, size: strokeWidth, color: strokeColor , solid: true });
} else {
Overlays.editOverlay(inkSourceOverlay, {
if (inkSourceOverlay == null){
inkSourceOverlay = Overlays.addOverlay("sphere", { parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(handLiteral === "left" ? "LeftHandIndex4" : "RightHandIndex4"), localPosition: { x: 0, y: 0, z: 0 }, size: strokeWidth, color: strokeColor , solid: true });
} else {
Overlays.editOverlay(inkSourceOverlay, {
parentJointIndex: MyAvatar.getJointIndex(handLiteral === "left" ? "LeftHandIndex4" : "RightHandIndex4"),
localPosition: { x: 0, y: 0, z: 0 },
size: strokeWidth,
color: strokeColor
localPosition: { x: 0, y: 0, z: 0 },
size: strokeWidth,
color: strokeColor
});
}
}
}
function restoreAllHandAnimations(){
//"rightHandGraspOpen","rightHandGraspClosed",
MyAvatar.restoreRoleAnimation("rightHandGraspOpen");
MyAvatar.restoreRoleAnimation("rightHandGraspClosed");
}
function restoreAllHandAnimations(){
//"rightHandGraspOpen","rightHandGraspClosed",
MyAvatar.restoreRoleAnimation("rightHandGraspOpen");
MyAvatar.restoreRoleAnimation("rightHandGraspClosed");
//"rightIndexPointOpen","rightIndexPointClosed",
MyAvatar.restoreRoleAnimation("rightIndexPointOpen");
MyAvatar.restoreRoleAnimation("rightIndexPointClosed");
//"rightIndexPointOpen","rightIndexPointClosed",
MyAvatar.restoreRoleAnimation("rightIndexPointOpen");
MyAvatar.restoreRoleAnimation("rightIndexPointClosed");
//"rightThumbRaiseOpen","rightThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("rightThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("rightThumbRaiseClosed");
//"rightThumbRaiseOpen","rightThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("rightThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("rightThumbRaiseClosed");
//"rightIndexPointAndThumbRaiseOpen","rightIndexPointAndThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("rightIndexPointAndThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("rightIndexPointAndThumbRaiseClosed");
//"leftHandGraspOpen","leftHandGraspClosed",
MyAvatar.restoreRoleAnimation("leftHandGraspOpen");
MyAvatar.restoreRoleAnimation("leftHandGraspClosed");
//"rightIndexPointAndThumbRaiseOpen","rightIndexPointAndThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("rightIndexPointAndThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("rightIndexPointAndThumbRaiseClosed");
//"leftHandGraspOpen","leftHandGraspClosed",
MyAvatar.restoreRoleAnimation("leftHandGraspOpen");
MyAvatar.restoreRoleAnimation("leftHandGraspClosed");
//"leftIndexPointOpen","leftIndexPointClosed",
MyAvatar.restoreRoleAnimation("leftIndexPointOpen");
MyAvatar.restoreRoleAnimation("leftIndexPointClosed");
//"leftIndexPointOpen","leftIndexPointClosed",
MyAvatar.restoreRoleAnimation("leftIndexPointOpen");
MyAvatar.restoreRoleAnimation("leftIndexPointClosed");
//"leftThumbRaiseOpen","leftThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("leftThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("leftThumbRaiseClosed");
//"leftThumbRaiseOpen","leftThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("leftThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("leftThumbRaiseClosed");
//"leftIndexPointAndThumbRaiseOpen","leftIndexPointAndThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("leftIndexPointAndThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("leftIndexPointAndThumbRaiseClosed");
}
//"leftIndexPointAndThumbRaiseOpen","leftIndexPointAndThumbRaiseClosed",
MyAvatar.restoreRoleAnimation("leftIndexPointAndThumbRaiseOpen");
MyAvatar.restoreRoleAnimation("leftIndexPointAndThumbRaiseClosed");
}
function pauseProcessing() {
//Script.update.disconnect(leftHand.onUpdate);
@ -708,15 +709,18 @@
Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL);
Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL);
}
function enableProcessing() {
// Connect controller API to handController objects.
leftHand = handController("left");
rightHand = handController("right");
// Connect handController outputs to paintBrush objects.
leftBrush = paintBrush("left");
leftHand.setUp(leftBrush.startLine, leftBrush.drawLine, leftBrush.finishLine, leftBrush.eraseClosestLine);
rightBrush = paintBrush("right");
rightHand.setUp(rightBrush.startLine, rightBrush.drawLine, rightBrush.finishLine, rightBrush.eraseClosestLine);
var controllerMapping = Controller.newMapping(CONTROLLER_MAPPING_NAME);
controllerMapping.from(Controller.Standard.LT).to(leftHand.onTriggerPress);
controllerMapping.from(Controller.Standard.LeftGrip).to(leftHand.onGripPress);
@ -724,15 +728,9 @@
controllerMapping.from(Controller.Standard.RightGrip).to(rightHand.onGripPress);
Controller.enableMapping(CONTROLLER_MAPPING_NAME);
// Connect handController outputs to paintBrush objects.
leftBrush = paintBrush("left");
leftHand.setUp(leftBrush.startLine, leftBrush.drawLine, leftBrush.finishLine, leftBrush.eraseClosestLine);
rightBrush = paintBrush("right");
rightHand.setUp(rightBrush.startLine, rightBrush.drawLine, rightBrush.finishLine, rightBrush.eraseClosestLine);
//Change to finger paint hand animation
updateHandAnimations();
//Change to finger paint hand animation
updateHandAnimations();
// Messages channels for enabling/disabling other scripts' functions.
Messages.subscribe(HIFI_POINT_INDEX_MESSAGE_CHANNEL);
Messages.subscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL);
@ -742,7 +740,7 @@
Script.update.connect(leftHand.onUpdate);
Script.update.connect(rightHand.onUpdate);
// enable window palette
/*window = new OverlayWindow({
title: 'Paint Window',
@ -761,8 +759,8 @@
if (message[0] === "color"){
leftBrush.changeStrokeColor(message[1], message[2], message[3]);
rightBrush.changeStrokeColor(message[1], message[2], message[3]);
Overlays.editOverlay(inkSourceOverlay, {
color: {red: message[1], green: message[2], blue: message[3]}
Overlays.editOverlay(inkSourceOverlay, {
color: {red: message[1], green: message[2], blue: message[3]}
});
return;
}
@ -773,9 +771,9 @@
//var dim2 = Math.floor( Math.random()*40 + 5);
leftBrush.changeStrokeWidthMultiplier(dim);
rightBrush.changeStrokeWidthMultiplier(dim);
Overlays.editOverlay(inkSourceOverlay, {
size: dim * 0.06
Overlays.editOverlay(inkSourceOverlay, {
size: dim * 0.06
});
return;
}
@ -785,17 +783,17 @@
//var dim2 = Math.floor( Math.random()*40 + 5);
leftBrush.changeTexture(message[1]);
rightBrush.changeTexture(message[1]);
if (message[1] === "content/brushes/paintbrush1.png") {
leftBrush.changeUVMode(true);
rightBrush.changeUVMode(true);
}else if (message[1] === "content/brushes/paintbrush3.png") {
leftBrush.changeUVMode(true);
rightBrush.changeUVMode(true);
}else{
leftBrush.changeUVMode(false);
rightBrush.changeUVMode(false);
}
if (message[1] === "content/brushes/paintbrush1.png") {
leftBrush.changeUVMode(true);
rightBrush.changeUVMode(true);
}else if (message[1] === "content/brushes/paintbrush3.png") {
leftBrush.changeUVMode(true);
rightBrush.changeUVMode(true);
}else{
leftBrush.changeUVMode(false);
rightBrush.changeUVMode(false);
}
return;
}
if (message[0] === "undo"){
@ -805,7 +803,7 @@
}
if (message[0] === "hand"){
isLeftHandDominant = !isLeftHandDominant;
updateHandAnimations();
updateHandAnimations();
return;
}
});*/ //uncomment for qml interface
@ -817,8 +815,8 @@
Controller.disableMapping(CONTROLLER_MAPPING_NAME);
Messages.sendLocalMessage("Hifi-Hand-Disabler", "none");
Messages.sendLocalMessage("Hifi-Hand-Disabler", "none");
leftBrush.tearDown();
leftBrush = null;
leftHand.tearDown();
@ -833,14 +831,14 @@
Messages.unsubscribe(HIFI_GRAB_DISABLE_MESSAGE_CHANNEL);
Messages.unsubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL);
//Restores and clears hand animations
restoreAllHandAnimations();
//clears Overlay sphere
Overlays.deleteOverlay(inkSourceOverlay);
inkSourceOverlay = null;
//Restores and clears hand animations
restoreAllHandAnimations();
//clears Overlay sphere
Overlays.deleteOverlay(inkSourceOverlay);
inkSourceOverlay = null;
// disable window palette
//window.close(); //uncomment for qml interface
}
@ -856,18 +854,18 @@
savedSettings.customColors = Settings.getValue("customColors", []);
savedSettings.currentTab = Settings.getValue("currentTab", 0);
savedSettings.currentTriggerWidthEnabled = Settings.getValue("currentTriggerWidthEnabled", true);
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;
isFingerPainting = !isFingerPainting;
if (!isFingerPainting) {
tablet.gotoHomeScreen();
}
button.editProperties({ isActive: isFingerPainting });
print("Finger painting: " + isFingerPainting ? "on" : "off");
@ -878,10 +876,9 @@
}
if (isFingerPainting) {
tablet.gotoWebScreen(APP_URL);
tablet.gotoWebScreen(APP_URL + "?" + encodeURIComponent(JSON.stringify(savedSettings)));
enableProcessing();
}
updateHandFunctions();
if (!isFingerPainting) {
@ -913,15 +910,12 @@
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) {
print("HMD ACTIVE: " + HMD.active);
Settings.setValue("currentColor", event);
//print("changing color...");
leftBrush.changeStrokeColor(event.red, event.green, event.blue);
@ -989,11 +983,10 @@
case "undo":
//print("Going to undo");
/**
The undo is called only on the right brush because the undo stack is global, meaning that
calling undoErasing on both the left and right brush would cause the stack to pop twice.
Using the leftBrush instead of the rightBrush would have the exact same effect.
*/
//The undo is called only on the right brush because the undo stack is global, meaning that
//calling undoErasing on both the left and right brush would cause the stack to pop twice.
//Using the leftBrush instead of the rightBrush would have the exact same effect.
rightBrush.undoErasing();
break;
@ -1023,21 +1016,19 @@
}
function addAnimationToBrush(entityID) {
//print("Brushes INfo 0" + JSON.stringify(DynamicBrushesInfo));
Object.keys(DynamicBrushesInfo).forEach(function(animationName) {
print(animationName + "Brushes INfo 0" + JSON.stringify(DynamicBrushesInfo));
if (DynamicBrushesInfo[animationName].isEnabled) {
var prevUserData = Entities.getEntityProperties(entityID).userData;
prevUserData = prevUserData == "" ? new Object() : JSON.parse(prevUserData); //preserve other possible user data
if (prevUserData.animations == null) {
prevUserData.animations = {};
}
prevUserData.animations[animationName] = dynamicBrushFactory(animationName, DynamicBrushesInfo[animationName].settings);
Entities.editEntity(entityID, {userData: JSON.stringify(prevUserData)});
//Entities.editEntity(entityID, {script: Script.resolvePath("content/brushes/dynamicBrushes/dynamicBrushScript.js")});
Object.keys(DynamicBrushesInfo).forEach(function(animationName) {
print(animationName + "Brushes INfo 0" + JSON.stringify(DynamicBrushesInfo));
if (DynamicBrushesInfo[animationName].isEnabled) {
var prevUserData = Entities.getEntityProperties(entityID).userData;
prevUserData = prevUserData == "" ? new Object() : JSON.parse(prevUserData); //preserve other possible user data
if (prevUserData.animations == null) {
prevUserData.animations = {};
}
});
//print("Brushes INfo 1" + JSON.stringify(DynamicBrushesInfo));
prevUserData.animations[animationName] = dynamicBrushFactory(animationName, DynamicBrushesInfo[animationName].settings);
Entities.editEntity(entityID, {userData: JSON.stringify(prevUserData)});
//Entities.editEntity(entityID, {script: Script.resolvePath("content/brushes/dynamicBrushes/dynamicBrushScript.js")});
}
});
}
function addElementToUndoStack(item)
@ -1083,6 +1074,57 @@
button.clicked.disconnect(onButtonClicked);
tablet.removeButton(button);
}
function getFingerPosition(x, y) {
var pickRay = Camera.computePickRay(x, y);
return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, 5));
}
Controller.mouseMoveEvent.connect(function(event){
if (rightBrush && rightBrush.isDrawing()) {
rightBrush.drawLine(getFingerPosition(event.x, event.y), 0.03);
}
});
Controller.mousePressEvent.connect(function(event){
print(JSON.stringify(event));
if (event.isLeftButton) {
rightBrush.startLine(getFingerPosition(event.x, event.y), 0.03);
} else if (event.isMiddleButton) {
//delete first line in sight
//var pickRay = getFingerPosition(event.x, event.y);
entities = Entities.findEntities(MyAvatar.position, 10);
// Fine polyline entity with closest point within search radius.
for (i = 0, entitiesLength = entities.length; i < entitiesLength; i += 1) {
print("NEAR ENTITIES: " + JSON.stringify(Entities.getEntityProperties(entities[i])));
}
var pickRay = Camera.computePickRay(event.x, event.y);
var entityToDelete = Entities.findRayIntersection(pickRay, false, [Entities.findEntities(MyAvatar.position, 1000)], []);
print("Entity to DELETE: " + JSON.stringify(entityToDelete));
var line3d = Overlays.addOverlay("line3d", {
start: pickRay.origin,
end: Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, 100)),
color: { red: 255, green: 0, blue: 255},
lineWidth: 5
});
if (entityToDelete.intersects) {
print("Entity to DELETE Properties: " + JSON.stringify(Entities.getEntityProperties(entityToDelete.entityID)));
//Entities.deleteEntity(entityToDelete.entityID);
}
}
});
Controller.mouseReleaseEvent.connect(function(event){
isMouseDrawing = false;
if (rightBrush && rightBrush.isDrawing()) {
rightBrush.finishLine(getFingerPosition(event.x, event.y), 0.03);
}
});
setUp();
Script.scriptEnding.connect(tearDown);

View file

@ -1,9 +1,10 @@
<!--Note: change the parent postmessage second parameter due to possible security issues-->
<link rel="stylesheet" type="text/css" href="../../html/css/edit-style.css">
<script src="../../html/js/jquery-2.1.4.min.js"></script>
<style>
.brushButton {
width: 66px;
width: 66px;
background-color: #2e2e2e;
border:none;
margin: 1px 0px;
@ -56,11 +57,12 @@
</style>
<div class="behavior-group property checkbox">
<input onchange="setDynamicBrush(this)" animationType="DynamicHueBrush" type="checkbox" id="dynamicBrush"></input>
<label for="dynamicBrush">Use Dynamic Hue </label>
</div>
<div>
<!--<div>
<div style="float: left; margin-right: 20px">
<div class="behavior-group property checkbox">
<input onchange="setDynamicBrush(this)" animationType="DynamicRotationBrush" type="checkbox" id="yawRotationBrush"></input>
@ -89,7 +91,7 @@
<label for="zTranslationBrush">Use Translation z</label>
</div>
</div>
</div>
</div>-->
<div id="brushesCointainer">
@ -615,7 +617,6 @@
var selectedOverlay = document.createElement("div");
selectedOverlay.id = "selectedOverlay";
brushes[currentBrush].children[0].appendChild(selectedOverlay);
console.log(brushes[currentBrush].children[0]);
var changedBrushEvent = {
"type" : "changeBrush",
@ -668,12 +669,12 @@
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);
restoreSavedBrushes(JSON.parse(decodeURIComponent(window.parent.location.search).substring(1)));
function restoreSavedBrushes(brushData) {
//var brush = JSON.parse(event.data);
var dynamicBrushes = brushData.currentDynamicBrushes;
if (brushData.currentTexture) {
changePaintBrush(brushData.currentTexture.brushID);
}
if (dynamicBrushes) {
for (var i = 0; i < dynamicBrushes.length; i++) {

View file

@ -34,11 +34,11 @@
};
parent.postMessage(JSON.stringify(chooseHandEvent), "*");
}
//window.addEventListener("message", restoreCurrentDrawingHand, false);
restoreCurrentDrawingHand(JSON.parse(decodeURIComponent(window.parent.location.search).substring(1)));
window.addEventListener("message", restoreCurrentDrawingHand, false);
function restoreCurrentDrawingHand() {
var currentHand = JSON.parse(event.data);
if (currentHand) {
function restoreCurrentDrawingHand(handData) {
if (handData.currentDrawingHand) {
chooseHand(0);
} else {
chooseHand(1);

View file

@ -60,9 +60,6 @@
<div class="slider-wrapper">
<input type="range" id="lineWidthRange" value=0.25 min=0 max=1 step=0.01 onchange="changeLineWidthRange(this)"/>
<input type="number" id="lineWidthText" value=0.25 min=0 max=1 step=0.01 onchange="changeLineWidthNumber(this)"/>
<!--<span id="lineWidthText">0.25</span>
var inputField = document.createElement("input");
inputField.setAttribute("type", "number");-->
</div>
</div>
@ -203,9 +200,9 @@
}
}
window.addEventListener("message", restoreLastColor, false);
function restoreLastColor(event) {
var palleteData = JSON.parse(event.data);
restoreLastColor(JSON.parse(decodeURIComponent(window.parent.location.search).substring(1)));
function restoreLastColor(palleteData) {
//var palleteData = JSON.parse(event.data);
if ("currentColor" in palleteData) {
var newColor = palleteData.currentColor;
@ -229,4 +226,6 @@
changeLineWidthNumber({value: palleteData.currentStrokeWidth});
}
}
</script>

View file

@ -43,10 +43,10 @@
</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" 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="chooseHandTab.html" onLoad="notifyFrameLoaded(this)" id="chooseHandTab" seamless style="display: none"></iframe>
<iframe frameborder="0" lastState="window.location.search" src="colorsTab.html" id="colorTab" seamless></iframe>
<iframe frameborder="0" lastState="window.location.search" src="brushesTab.html" id="brushesTab" seamless style="display: none"></iframe>
<iframe frameborder="0" lastState="window.location.search" src="eraserTab.html" id="eraserTab" seamless style="display: none"></iframe>
<iframe frameborder="0" lastState="window.location.search" src="chooseHandTab.html" id="chooseHandTab" seamless style="display: none"></iframe>
</div>
</body>
</html>
@ -55,7 +55,6 @@
var currentTab = 0;
var settings;
var iframesLoaded = 0;
function selectTab(tabIndex) {
var tabs = document.getElementById("tabs").children;
var contentPanels = document.getElementById("content").children;
@ -77,60 +76,8 @@
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 != document.getElementById("content").children.length) {
return;
}
$("#settingsLoading").hide();
if (settings.currentTab != null) {
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.currentTriggerWidthEnabled) {
document.getElementById("colorTab").contentWindow.postMessage(JSON.stringify({currentTriggerWidthEnabled: settings.currentTriggerWidthEnabled}), "*");
}
if (settings.currentStrokeWidth) {
document.getElementById("colorTab").contentWindow.postMessage(JSON.stringify({currentStrokeWidth: settings.currentStrokeWidth}), "*");
}
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.currentDrawingHand) {
document.getElementById("chooseHandTab").contentWindow.postMessage(JSON.stringify(settings.currentDrawingHand), "*");
}
}
$(document).ready(receiveDataSetup);
selectTab(JSON.parse(decodeURIComponent(window.location.search).substring(1)).currentTab);
// Listen to message from child window
eventer(messageEvent,function(e) {
EventBridge.emitWebEvent(e.data);