Merge branch 'master' of https://github.com/highfidelity/hifi into entityScriptsAndEvents

This commit is contained in:
ZappoMan 2014-11-03 10:54:19 -08:00
commit 49a389618e
15 changed files with 1169 additions and 156 deletions

View file

@ -2787,13 +2787,13 @@ function setupModelMenus() {
print("delete exists... don't add ours");
}
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
afterItem: "Paste Models", isCheckable: true });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S",
afterItem: "Allow Select Large Models", isCheckable: true });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List", afterItem: "Models" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" });
@ -2809,6 +2809,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", "Delete");
}
Menu.removeMenuItem("Edit", "Model List...");
Menu.removeMenuItem("Edit", "Paste Models");
Menu.removeMenuItem("Edit", "Allow Select Large Models");
Menu.removeMenuItem("Edit", "Allow Select Small Models");
@ -2883,16 +2884,21 @@ function handeMenuEvent(menuItem) {
} else {
print(" Delete Entity.... not holding...");
}
} else if (menuItem == "Model List") {
} else if (menuItem == "Model List...") {
var models = new Array();
models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE);
for (var i = 0; i < models.length; i++) {
models[i].properties = Entities.getEntityProperties(models[i]);
models[i].toString = function() {
var modelname = decodeURIComponent(
this.properties.modelURL.indexOf("/") != -1 ?
this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) :
this.properties.modelURL);
var modelname;
if (this.properties.type == "Model") {
modelname = decodeURIComponent(
this.properties.modelURL.indexOf("/") != -1 ?
this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) :
this.properties.modelURL);
} else {
modelname = this.properties.id;
}
return "[" + this.properties.type + "] " + modelname;
};
}

View file

@ -0,0 +1,986 @@
//
// follow-through-and-overlapping-action.js
//
// Simple demonstration showing the visual effect of adding the Disney
// follow through and overlapping action animation technique to avatar movement.
//
// Designed and created by David Wooldridge and Ozan Serim, August 2014
//
// Version 1.001
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// location of overlay images
var pathToOverlays = "https://s3.amazonaws.com/hifi-public/ArmSwingScript/ArmSwingOverlays/";
// animation
var LEFT = 1;
var RIGHT = 2;
var DIRECTION = 0;
// min max
var weightMin = 1;
var weightMax = 20;
var jointEffectMax = 5;
// animation effect variables
var handEffect = 3.4; // 0 to jointEffectMax
var forearmEffect = 2.5; // 0 to jointEffectMax
var limbWeight = 8; // will only use nearest integer, as defines an array length
var effectStrength = 1; // 0 to 1 - overall effect strength
// Overshoot: false uses upper arm as driver for forearm and hand
// true uses upper arm for forearm and lower arm as driver for hand.
var overShoot = false;
// animate self (tap the 'r' key)
var animateSelf = false;
var selfAnimateFrequency = 7.5;
// overlay values
var handleValue = 0;
var controlPosX = Window.innerWidth / 2 - 500;
var controlPosY = 0;
var minSliderX = controlPosX + 18;
var sliderRangeX = 190;
var minHandleX = controlPosX - 50;
var handleRangeX = 350 / 2;
var handlePosition = 0;
// background overlay
var controllerBackground = Overlays.addOverlay("image", {
bounds: {x: controlPosX, y: controlPosY, width: 250, height: 380},
imageURL: pathToOverlays + "flourish-augmentation-control-overlay.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1
});
var controllerRadioSelectedBackground = Overlays.addOverlay("image", {
bounds: {x: controlPosX, y: controlPosY, width: 250, height: 380},
imageURL: pathToOverlays + "flourish-augmentation-control-radio-selected-overlay.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1,
visible: false
});
// handle overlay
var applyMotionHandle = Overlays.addOverlay("image", {
bounds: {x: minHandleX+handleRangeX-39, y: controlPosY+232,
width: 79, height: 100},
imageURL: pathToOverlays + "flourish-augmentation-handle-overlay.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1
});
// slider overlays
var handEffectSlider = Overlays.addOverlay("image", {
bounds: {x: minSliderX + (handEffect / jointEffectMax * sliderRangeX),
y: controlPosY + 46, width: 25, height: 25},
imageURL: pathToOverlays + "ddao-slider-handle.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1
});
var forearmEffectSlider = Overlays.addOverlay("image", {
bounds: {x: minSliderX + (forearmEffect / jointEffectMax * sliderRangeX), y: controlPosY + 86,
width: 25, height: 25},
imageURL: pathToOverlays + "ddao-slider-handle.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1
});
var limbWeightSlider = Overlays.addOverlay("image", {
bounds: {x: minSliderX + (limbWeight / weightMax * sliderRangeX), y: controlPosY+126,
width: 25, height: 25},
imageURL: pathToOverlays + "ddao-slider-handle.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1
});
var effectStrengthSlider = Overlays.addOverlay("image", {
bounds: {x: minSliderX + (effectStrength * sliderRangeX), y: controlPosY+206,
width: 25, height: 25},
imageURL: pathToOverlays + "ddao-slider-handle.png",
color: {red: 255, green: 255, blue: 255},
alpha: 1
});
// main loop - using averaging filters to add limb element follow-through
var upperArmPDampingFilter = [];
upperArmPDampingFilter.length = parseInt(limbWeight); // sets amount of damping for upper arm pitch
var forearmPDampingFilter = [];
forearmPDampingFilter.length = parseInt(limbWeight) + 2; // sets amount of damping for lower arm pitch
var cumulativeTime = 0;
Script.update.connect(function(deltaTime) {
// used for self animating (press r to invoke)
cumulativeTime += deltaTime;
// blend three keyframes using handle position to determine progress between keyframes
var animationProgress = handleValue;
if(animateSelf) {
animationProgress = Math.sin(cumulativeTime * selfAnimateFrequency);
animationProgress++;
animationProgress /= 2;
}
var keyframeOneWeight = 0;
var keyframeTwoWeight = 0;
var keyframeThreeWeight = 0;
if(movingHandle || animateSelf) {
keyframeOneWeight = 0;
keyframeTwoWeight = animationProgress;
keyframeThreeWeight = 1 - animationProgress;
}
else if(!movingHandle) {
// idle
keyframeOneWeight = 1;
keyframeTwoWeight = 0;
keyframeThreeWeight = 0;
}
var shoulderPitch =
keyframeOneWeight * keyFrameOne.joints[8].pitchOffset +
keyframeTwoWeight * keyFrameTwo.joints[8].pitchOffset +
keyframeThreeWeight * keyFrameThree.joints[8].pitchOffset;
var upperArmPitch =
keyframeOneWeight * keyFrameOne.joints[9].pitchOffset +
keyframeTwoWeight * keyFrameTwo.joints[9].pitchOffset +
keyframeThreeWeight * keyFrameThree.joints[9].pitchOffset;
// get the change in upper arm pitch and use to add weight effect to forearm (always) and hand (only for overShoot)
var deltaUpperArmPitch = effectStrength *
(upperArmPDampingFilter[upperArmPDampingFilter.length - 1] -
upperArmPDampingFilter[0]);
var forearmPitch =
keyframeOneWeight * keyFrameOne.joints[10].pitchOffset +
keyframeTwoWeight * keyFrameTwo.joints[10].pitchOffset +
keyframeThreeWeight * keyFrameThree.joints[10].pitchOffset -
(deltaUpperArmPitch/(jointEffectMax - forearmEffect));
// there are two methods for calculating the hand follow through
var handPitch = 0;
if(overShoot) {
// get the change in forearm pitch and use to add weight effect to hand
var deltaForearmPitch = effectStrength *
(forearmPDampingFilter[forearmPDampingFilter.length - 1] -
forearmPDampingFilter[0]);
handPitch =
keyframeOneWeight * keyFrameOne.joints[11].pitchOffset +
keyframeTwoWeight * keyFrameTwo.joints[11].pitchOffset +
keyframeThreeWeight * keyFrameThree.joints[11].pitchOffset +
(deltaForearmPitch /(jointEffectMax - handEffect)); // hand driven by forearm
} else {
handPitch =
keyframeOneWeight * keyFrameOne.joints[11].pitchOffset +
keyframeTwoWeight * keyFrameTwo.joints[11].pitchOffset +
keyframeThreeWeight * keyFrameThree.joints[11].pitchOffset -
(deltaUpperArmPitch /(jointEffectMax - handEffect)); // hand driven by upper arm
}
var shoulderYaw =
keyframeOneWeight * keyFrameOne.joints[8].yawOffset +
keyframeTwoWeight * keyFrameTwo.joints[8].yawOffset +
keyframeThreeWeight * keyFrameThree.joints[8].yawOffset;
var upperArmYaw =
keyframeOneWeight * keyFrameOne.joints[9].yawOffset +
keyframeTwoWeight * keyFrameTwo.joints[9].yawOffset +
keyframeThreeWeight * keyFrameThree.joints[9].yawOffset;
var lowerArmYaw =
keyframeOneWeight * keyFrameOne.joints[10].yawOffset +
keyframeTwoWeight * keyFrameTwo.joints[10].yawOffset +
keyframeThreeWeight * keyFrameThree.joints[10].yawOffset;
var handYaw =
keyframeOneWeight * keyFrameOne.joints[11].yawOffset +
keyframeTwoWeight * keyFrameTwo.joints[11].yawOffset +
keyframeThreeWeight * keyFrameThree.joints[11].yawOffset;
var shoulderRoll =
keyframeOneWeight * keyFrameOne.joints[8].rollOffset +
keyframeTwoWeight * keyFrameTwo.joints[8].rollOffset +
keyframeThreeWeight * keyFrameThree.joints[8].rollOffset;
var upperArmRoll =
keyframeOneWeight * keyFrameOne.joints[9].rollOffset +
keyframeTwoWeight * keyFrameTwo.joints[9].rollOffset +
keyframeThreeWeight * keyFrameThree.joints[9].rollOffset;
var lowerArmRoll =
keyframeOneWeight * keyFrameOne.joints[10].rollOffset +
keyframeTwoWeight * keyFrameTwo.joints[10].rollOffset +
keyframeThreeWeight * keyFrameThree.joints[10].rollOffset;
var handRoll =
keyframeOneWeight * keyFrameOne.joints[11].rollOffset +
keyframeTwoWeight * keyFrameTwo.joints[11].rollOffset +
keyframeThreeWeight * keyFrameThree.joints[11].rollOffset;
// filter upper arm pitch
upperArmPDampingFilter.push(upperArmPitch);
upperArmPDampingFilter.shift();
var upperArmPitchFiltered = 0;
for(ea in upperArmPDampingFilter) upperArmPitchFiltered += upperArmPDampingFilter[ea];
upperArmPitchFiltered /= upperArmPDampingFilter.length;
upperArmPitch = (effectStrength * upperArmPitchFiltered) + ((1 - effectStrength) * upperArmPitch);
// filter forearm pitch only if using for hand follow-though
if(overShoot) {
forearmPDampingFilter.push(forearmPitch);
forearmPDampingFilter.shift();
var forearmPitchFiltered = 0;
for(ea in forearmPDampingFilter) forearmPitchFiltered += forearmPDampingFilter[ea];
forearmPitchFiltered /= forearmPDampingFilter.length;
forearmPitch = (effectStrength*forearmPitchFiltered) + ((1-effectStrength) * forearmPitch);
}
// apply the new rotation data to the joints
MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(shoulderPitch, shoulderYaw, shoulderRoll));
MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees(upperArmPitch, -upperArmYaw, upperArmRoll));
MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees(forearmPitch, lowerArmYaw, lowerArmRoll));
MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollDegrees(handPitch, handYaw, handRoll));
});
// mouse handling
var movingHandEffectSlider = false;
var movingForearmEffectSlider = false;
var movingLimbWeightSlider = false;
var movingDampingSlider = false;
var movingEffectStrengthSlider = false;
var movingHandle = false;
function mousePressEvent(event) {
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
if(clickedOverlay === applyMotionHandle) movingHandle = true;
else if(clickedOverlay === handEffectSlider) movingHandEffectSlider = true;
else if(clickedOverlay === forearmEffectSlider) movingForearmEffectSlider = true;
else if(clickedOverlay === limbWeightSlider) movingLimbWeightSlider = true;
else if(clickedOverlay === effectStrengthSlider) movingEffectStrengthSlider = true;
else if(clickedOverlay === controllerRadioSelectedBackground &&
event.x > 477 && event.x < 497 && event.y > 338 && event.y < 360) {
overShoot = false;
Overlays.editOverlay(controllerBackground, {visible: true});
Overlays.editOverlay(controllerRadioSelectedBackground, {visible: false});
}
else if(clickedOverlay === controllerBackground &&
event.x > 477 && event.x < 497 && event.y > 338 && event.y < 360){
overShoot = true;
Overlays.editOverlay(controllerBackground, {visible: false});
Overlays.editOverlay(controllerRadioSelectedBackground, {visible: true});
}
}
function mouseMoveEvent(event) {
if(movingHandle) {
var thumbClickOffsetX = event.x - minHandleX;
var thumbPositionNormalised = (thumbClickOffsetX - handleRangeX) / handleRangeX;
if(thumbPositionNormalised <= -1) thumbPositionNormalised = -1;
else if(thumbPositionNormalised > 1) thumbPositionNormalised = 1;
if(thumbPositionNormalised < 0) DIRECTION = LEFT;
else DIRECTION = RIGHT;
handleValue = (thumbPositionNormalised + 1) / 2;
var handleX = (thumbPositionNormalised * handleRangeX) + handleRangeX - 39;
Overlays.editOverlay(applyMotionHandle, {x: handleX + minHandleX});
return;
}
else if(movingHandEffectSlider) {
var thumbClickOffsetX = event.x - minSliderX;
var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX;
if(thumbPositionNormalised < 0) thumbPositionNormalised = 0;
if(thumbPositionNormalised > 1) thumbPositionNormalised = 1;
handEffect = (thumbPositionNormalised - 0.08) * jointEffectMax;
var sliderX = thumbPositionNormalised * sliderRangeX ;
Overlays.editOverlay(handEffectSlider, {x: sliderX + minSliderX});
}
else if(movingForearmEffectSlider) {
var thumbClickOffsetX = event.x - minSliderX;
var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX;
if(thumbPositionNormalised < 0) thumbPositionNormalised = 0;
if(thumbPositionNormalised > 1) thumbPositionNormalised = 1;
forearmEffect = (thumbPositionNormalised - 0.1) * jointEffectMax;
var sliderX = thumbPositionNormalised * sliderRangeX ;
Overlays.editOverlay(forearmEffectSlider, {x: sliderX + minSliderX});
}
else if(movingLimbWeightSlider) {
var thumbClickOffsetX = event.x - minSliderX;
var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX;
if(thumbPositionNormalised<0) thumbPositionNormalised = 0;
if(thumbPositionNormalised>1) thumbPositionNormalised = 1;
limbWeight = thumbPositionNormalised * weightMax;
if(limbWeight < weightMin) limbWeight = weightMin;
upperArmPDampingFilter.length = parseInt(limbWeight);
var sliderX = thumbPositionNormalised * sliderRangeX ;
Overlays.editOverlay(limbWeightSlider, {x: sliderX + minSliderX});
}
else if(movingEffectStrengthSlider) {
var thumbClickOffsetX = event.x - minSliderX;
var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX;
if(thumbPositionNormalised < 0) thumbPositionNormalised = 0;
if(thumbPositionNormalised > 1) thumbPositionNormalised = 1;
effectStrength = thumbPositionNormalised;
var sliderX = thumbPositionNormalised * sliderRangeX ;
Overlays.editOverlay(effectStrengthSlider, {x: sliderX + minSliderX});
return;
}
}
function mouseReleaseEvent(event) {
if(movingHandle) {
movingHandle = false;
handleValue = 0;
Overlays.editOverlay(applyMotionHandle, {x: minHandleX+handleRangeX - 39});
}
else if(movingHandEffectSlider) movingHandEffectSlider = false;
else if(movingForearmEffectSlider) movingForearmEffectSlider = false;
else if(movingLimbWeightSlider) movingLimbWeightSlider = false;
else if(movingEffectStrengthSlider) movingEffectStrengthSlider = false;
else if(movingDampingSlider) movingDampingSlider = false;
}
// set up mouse and keyboard callbacks
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.keyPressEvent.connect(keyPressEvent);
// keyboard command
function keyPressEvent(event) {
if (event.text == "q") {
print('hand effect = ' + handEffect + '\n');
print('forearmEffect = ' + forearmEffect + '\n');
print('limbWeight = ' + limbWeight + '\n');
print('effectStrength = ' + effectStrength + '\n');
}
else if (event.text == "r") {
animateSelf = !animateSelf;
}
else if (event.text == "[") {
selfAnimateFrequency += 0.5;
print('selfAnimateFrequency = '+selfAnimateFrequency);
}
else if (event.text == "]") {
selfAnimateFrequency -= 0.5;
print('selfAnimateFrequency = '+selfAnimateFrequency);
}
}
// zero out all joints
function resetJoints() {
var avatarJointNames = MyAvatar.getJointNames();
for (var i = 0; i < avatarJointNames.length; i++)
MyAvatar.clearJointData(avatarJointNames[i]);
}
// Script ending
Script.scriptEnding.connect(function() {
// delete the overlays
Overlays.deleteOverlay(controllerBackground);
Overlays.deleteOverlay(controllerRadioSelectedBackground);
Overlays.deleteOverlay(handEffectSlider);
Overlays.deleteOverlay(forearmEffectSlider);
Overlays.deleteOverlay(limbWeightSlider);
Overlays.deleteOverlay(effectStrengthSlider);
Overlays.deleteOverlay(applyMotionHandle);
// leave the avi in zeroed out stance
resetJoints();
});
// animation data. animation keyframes produced using walk.js
MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees(80,0,0));
var keyFrameOne =
{
"name":"FemaleStandingOne",
"settings":{
"baseFrequency":70,
"flyingHipsPitch":60,
"takeFlightVelocity":40,
"maxBankingAngle":40
},
"adjusters":{
"legsSeparation":{
"strength":-0.03679245283018867,
"separationAngle":50
},
"stride":{
"strength":0,
"upperLegsPitch":30,
"lowerLegsPitch":15,
"upperLegsPitchOffset":0.2,
"lowerLegsPitchOffset":1.5
}
},
"joints":[
{
"name":"hips",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0,
"thrust":0,
"bob":0,
"sway":0,
"thrustPhase":180,
"bobPhase":0,
"swayPhase":-90,
"thrustOffset":0,
"bobOffset":0,
"swayOffset":0
},
{
"name":"upperLegs",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"lowerLegs",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"feet",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"toes",
"pitch":2.0377358490566038,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":4.415094339622641,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine",
"pitch":1.660377358490566,
"yaw":0,
"roll":0,
"pitchPhase":-180,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine1",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine2",
"pitch":2.1132075471698113,
"yaw":0,
"roll":0,
"pitchPhase":-0.6792452830188722,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"shoulders",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0.6792452830188678,
"yawOffset":-5.20754716981132,
"rollOffset":-2.9433962264150937
},
{
"name":"upperArms",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":77.77358490566039,
"yawOffset":9.169811320754715,
"rollOffset":0
},
{
"name":"lowerArms",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"hands",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":1.6981132075471694,
"yawOffset":-1.0188679245283017,
"rollOffset":1.0188679245283017
},
{
"name":"head",
"pitch":0,
"yaw":1.7358490566037734,
"roll":1.5094339622641508,
"pitchPhase":-90.33962264150944,
"yawPhase":94.41509433962267,
"rollPhase":0,
"pitchOffset":1.6981132075471694,
"yawOffset":0,
"rollOffset":0
}
]
};
var keyFrameTwo =
{
"name":"FemaleStandingOne",
"settings":{
"baseFrequency":70,
"flyingHipsPitch":60,
"takeFlightVelocity":40,
"maxBankingAngle":40
},
"adjusters":{
"legsSeparation":{
"strength":-0.03679245283018867,
"separationAngle":50
},
"stride":{
"strength":0,
"upperLegsPitch":30,
"lowerLegsPitch":15,
"upperLegsPitchOffset":0.2,
"lowerLegsPitchOffset":1.5
}
},
"joints":[
{
"name":"hips",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0,
"thrust":0,
"bob":0,
"sway":0,
"thrustPhase":180,
"bobPhase":0,
"swayPhase":-90,
"thrustOffset":0,
"bobOffset":0,
"swayOffset":0
},
{
"name":"upperLegs",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"lowerLegs",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"feet",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"toes",
"pitch":2.0377358490566038,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":4.415094339622641,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine",
"pitch":1.660377358490566,
"yaw":0,
"roll":0,
"pitchPhase":-180,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine1",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine2",
"pitch":2.1132075471698113,
"yaw":0,
"roll":0,
"pitchPhase":-0.6792452830188722,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"shoulders",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0.6792452830188678,
"yawOffset":-5.20754716981132,
"rollOffset":-2.9433962264150937
},
{
"name":"upperArms",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":49.584905660377345,
"yawOffset":9.169811320754715,
"rollOffset":0
},
{
"name":"lowerArms",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"hands",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":-13,
"yawOffset":-1.0188679245283017,
"rollOffset":1.0188679245283017
},
{
"name":"head",
"pitch":0,
"yaw":1.7358490566037734,
"roll":1.5094339622641508,
"pitchPhase":-90.33962264150944,
"yawPhase":94.41509433962267,
"rollPhase":0,
"pitchOffset":1.6981132075471694,
"yawOffset":0,
"rollOffset":0
}
]
};
var keyFrameThree =
{
"name":"FemaleStandingOne",
"settings":{
"baseFrequency":70,
"flyingHipsPitch":60,
"takeFlightVelocity":40,
"maxBankingAngle":40
},
"adjusters":{
"legsSeparation":{
"strength":-0.03679245283018867,
"separationAngle":50
},
"stride":{
"strength":0,
"upperLegsPitch":30,
"lowerLegsPitch":15,
"upperLegsPitchOffset":0.2,
"lowerLegsPitchOffset":1.5
}
},
"joints":[
{
"name":"hips",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0,
"thrust":0,
"bob":0,
"sway":0,
"thrustPhase":180,
"bobPhase":0,
"swayPhase":-90,
"thrustOffset":0,
"bobOffset":0,
"swayOffset":0
},
{
"name":"upperLegs",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"lowerLegs",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"feet",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"toes",
"pitch":2.0377358490566038,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":4.415094339622641,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine",
"pitch":1.660377358490566,
"yaw":0,
"roll":0,
"pitchPhase":-180,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine1",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"spine2",
"pitch":2.1132075471698113,
"yaw":0,
"roll":0,
"pitchPhase":-0.6792452830188722,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"shoulders",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":-21.0566037735849,
"yawOffset":-5.20754716981132,
"rollOffset":-2.9433962264150937
},
{
"name":"upperArms",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":-33.28301886792452,
"yawOffset":9.169811320754715,
"rollOffset":0
},
{
"name":"lowerArms",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":0,
"yawOffset":0,
"rollOffset":0
},
{
"name":"hands",
"pitch":0,
"yaw":0,
"roll":0,
"pitchPhase":0,
"yawPhase":0,
"rollPhase":0,
"pitchOffset":-13,
"yawOffset":-1.0188679245283017,
"rollOffset":1.0188679245283017
},
{
"name":"head",
"pitch":0,
"yaw":1.7358490566037734,
"roll":1.5094339622641508,
"pitchPhase":-90.33962264150944,
"yawPhase":94.41509433962267,
"rollPhase":0,
"pitchOffset":1.6981132075471694,
"yawOffset":0,
"rollOffset":0
}
]
};

View file

@ -17,13 +17,17 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var PI = 3.14 // No need for something more precise
var PI = Math.PI;
var RAD_TO_DEG = 180.0 / PI;
var AZIMUTH_RATE = 90.0;
var ALTITUDE_RATE = 200.0;
var RADIUS_RATE = 1.0 / 100.0;
var PAN_RATE = 50.0;
var Y_AXIS = { x: 0, y: 1, z: 0 };
var X_AXIS = { x: 1, y: 0, z: 0 };
var alt = false;
var shift = false;
var control = false;
@ -53,6 +57,18 @@ var avatarPosition;
var avatarOrientation;
function orientationOf(vector) {
var direction,
yaw,
pitch;
direction = Vec3.normalize(vector);
yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS);
pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS);
return Quat.multiply(yaw, pitch);
}
function handleRadialMode(dx, dy) {
azimuth += dx / AZIMUTH_RATE;
radius += radius * dy * RADIUS_RATE;
@ -65,6 +81,7 @@ function handleRadialMode(dx, dy) {
z: (Math.cos(altitude) * Math.sin(azimuth)) * radius };
position = Vec3.sum(center, vector);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
}
function handleOrbitMode(dx, dy) {
@ -82,6 +99,7 @@ function handleOrbitMode(dx, dy) {
z:(Math.cos(altitude) * Math.sin(azimuth)) * radius };
position = Vec3.sum(center, vector);
Camera.setPosition(position);
Camera.setOrientation(orientationOf(vector));
}
@ -96,7 +114,7 @@ function handlePanMode(dx, dy) {
position = Vec3.sum(position, dv);
Camera.setPosition(position);
Camera.keepLookingAt(center);
Camera.setOrientation(orientationOf(vector));
}
function saveCameraState() {
@ -107,7 +125,6 @@ function saveCameraState() {
}
function restoreCameraState() {
Camera.stopLooking();
Camera.setMode(oldMode);
}
@ -245,7 +262,6 @@ function mousePressEvent(event) {
azimuth = Math.atan2(vector.z, vector.x);
altitude = Math.asin(vector.y / Vec3.length(vector));
Camera.keepLookingAt(center);
print(string);
isActive = true;
}

View file

@ -86,7 +86,7 @@ CameraManager = function() {
that.updateCamera();
cameraTool.setVisible(true);
cameraTool.setVisible(false);
}
that.disable = function(ignoreCamera) {
@ -100,7 +100,7 @@ CameraManager = function() {
cameraTool.setVisible(false);
}
that.focus = function(entityProperties) {
that.focus = function() {
var dim = SelectionManager.worldDimensions;
var size = Math.max(dim.x, Math.max(dim.y, dim.z));

View file

@ -209,12 +209,6 @@ SelectionDisplay = (function () {
var lastCameraOrientation = Camera.getOrientation();
var lastPlaneIntersection;
var currentSelection = { id: -1, isKnownID: false };
var entitySelected = false;
var selectedEntityProperties;
var selectedEntityPropertiesOriginalPosition;
var selectedEntityPropertiesOriginalDimensions;
var handleHoverColor = { red: 224, green: 67, blue: 36 };
var handleHoverAlpha = 1.0;
@ -656,20 +650,12 @@ SelectionDisplay = (function () {
};
that.select = function(entityID, event) {
var properties = Entities.getEntityProperties(entityID);
// if (currentSelection.isKnownID == true) {
// that.unselect(currentSelection);
// }
currentSelection = entityID;
entitySelected = true;
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
// lastCameraPosition = Camera.getPosition();
lastCameraPosition = Camera.getPosition();
lastCameraOrientation = Camera.getOrientation();
if (event !== false) {
selectedEntityProperties = properties;
selectedEntityPropertiesOriginalPosition = properties.position;
selectedEntityPropertiesOriginalDimensions = properties.dimensions;
pickRay = Camera.computePickRay(event.x, event.y);
lastPlaneIntersection = rayPlaneIntersection(pickRay, properties.position, Quat.getFront(lastCameraOrientation));
@ -678,8 +664,6 @@ SelectionDisplay = (function () {
print("select() with EVENT...... ");
print(" event.y:" + event.y);
Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection);
Vec3.print(" originalPosition:", selectedEntityPropertiesOriginalPosition);
Vec3.print(" originalDimensions:", selectedEntityPropertiesOriginalDimensions);
Vec3.print(" current position:", properties.position);
}
@ -939,11 +923,6 @@ SelectionDisplay = (function () {
};
that.unselectAll = function () {
if (currentSelection.isKnownID == true) {
that.unselect(currentSelection);
}
currentSelection = { id: -1, isKnownID: false };
entitySelected = false;
};
that.updateHandles = function() {
@ -952,7 +931,9 @@ SelectionDisplay = (function () {
return;
}
that.updateRotationHandles();
that.highlightSelectable();
var rotation, dimensions, position;
@ -1113,12 +1094,6 @@ SelectionDisplay = (function () {
};
that.unselect = function (entityID) {
that.setOverlaysVisible(false);
Entities.editEntity(entityID, { localRenderAlpha: 1.0 });
currentSelection = { id: -1, isKnownID: false };
entitySelected = false;
};
var initialXZPick = null;
@ -1207,15 +1182,16 @@ SelectionDisplay = (function () {
}
}
tooltip.updateText(selectedEntityProperties);
that.select(currentSelection, false); // TODO: this should be more than highlighted
SelectionManager._update();
}
};
var lastXYPick = null
addGrabberTool(grabberMoveUp, {
mode: "TRANSLATE_UP_DOWN",
onBegin: function(event) {
lastXYPick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, Quat.getFront(lastCameraOrientation));
SelectionManager.saveProperties();
// Duplicate entities if alt is pressed. This will make a
@ -1243,7 +1219,7 @@ SelectionDisplay = (function () {
// translate mode left/right based on view toward entity
var newIntersection = rayPlaneIntersection(pickRay,
selectedEntityPropertiesOriginalPosition,
SelectionManager.worldPosition,
Quat.getFront(lastCameraOrientation));
var vector = Vec3.subtract(newIntersection, lastPlaneIntersection);
@ -1253,8 +1229,6 @@ SelectionDisplay = (function () {
vector.x = 0;
vector.z = 0;
// newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, vector);
var wantDebug = false;
if (wantDebug) {
print("translateUpDown... ");
@ -1262,8 +1236,6 @@ SelectionDisplay = (function () {
Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection);
Vec3.print(" newIntersection:", newIntersection);
Vec3.print(" vector:", vector);
Vec3.print(" originalPosition:", selectedEntityPropertiesOriginalPosition);
Vec3.print(" recentPosition:", selectedEntityProperties.position);
Vec3.print(" newPosition:", newPosition);
}
for (var i = 0; i < SelectionManager.selections.length; i++) {
@ -1273,8 +1245,6 @@ SelectionDisplay = (function () {
Entities.editEntity(SelectionManager.selections[i], properties);
}
tooltip.updateText(selectedEntityProperties);
that.select(currentSelection, false); // TODO: this should be more than highlighted
SelectionManager._update();
},
});
@ -1306,7 +1276,7 @@ SelectionDisplay = (function () {
var rotation = null;
var onBegin = function(event) {
var properties = Entities.getEntityProperties(currentSelection);
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
initialProperties = properties;
rotation = spaceMode == SPACE_LOCAL ? properties.rotation : Quat.fromPitchYawRollDegrees(0, 0, 0);
@ -1445,11 +1415,11 @@ SelectionDisplay = (function () {
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(p, changeInDimensions));
var newPosition = Vec3.sum(initialPosition, changeInPosition);
selectedEntityProperties.position = newPosition;
selectedEntityProperties.dimensions = newDimensions;
for (var i = 0; i < SelectionManager.selections.length; i++) {
Entities.editEntity(SelectionManager.selections[i], selectedEntityProperties);
Entities.editEntity(SelectionManager.selections[i], {
position: newPosition,
dimensions: newDimensions,
});
}
var wantDebug = false;
@ -1460,18 +1430,14 @@ SelectionDisplay = (function () {
Vec3.print(" vector:", vector);
Vec3.print(" oldPOS:", oldPOS);
Vec3.print(" newPOS:", newPOS);
Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions);
Vec3.print(" changeInDimensions:", changeInDimensions);
Vec3.print(" newDimensions:", newDimensions);
Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition);
Vec3.print(" changeInPosition:", changeInPosition);
Vec3.print(" newPosition:", newPosition);
}
tooltip.updateText(selectedEntityProperties);
SelectionManager._update();
that.select(currentSelection, false); // TODO: this should be more than highlighted
};
@ -1590,7 +1556,6 @@ SelectionDisplay = (function () {
}
if (result.intersects) {
var properties = Entities.getEntityProperties(currentSelection);
var center = yawCenter;
var zero = yawZero;
var centerToZero = Vec3.subtract(center, zero);
@ -1664,8 +1629,8 @@ SelectionDisplay = (function () {
// Size the overlays to the current selection size
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
var innerRadius = diagonal;
var outerRadius = diagonal * 1.15;
innerRadius = diagonal;
outerRadius = diagonal * 1.15;
var innerAlpha = 0.2;
var outerAlpha = 0.2;
Overlays.editOverlay(rotateOverlayInner,
@ -1721,7 +1686,7 @@ SelectionDisplay = (function () {
}
if (result.intersects) {
var properties = Entities.getEntityProperties(currentSelection);
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
var center = pitchCenter;
var zero = pitchZero;
var centerToZero = Vec3.subtract(center, zero);
@ -1794,8 +1759,8 @@ SelectionDisplay = (function () {
// Size the overlays to the current selection size
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
var innerRadius = diagonal;
var outerRadius = diagonal * 1.15;
innerRadius = diagonal;
outerRadius = diagonal * 1.15;
var innerAlpha = 0.2;
var outerAlpha = 0.2;
Overlays.editOverlay(rotateOverlayInner,
@ -1851,7 +1816,7 @@ SelectionDisplay = (function () {
}
if (result.intersects) {
var properties = Entities.getEntityProperties(currentSelection);
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
var center = rollCenter;
var zero = rollZero;
var centerToZero = Vec3.subtract(center, zero);
@ -1915,9 +1880,9 @@ SelectionDisplay = (function () {
});
that.checkMove = function() {
if (currentSelection.isKnownID &&
if (SelectionManager.hasSelection() &&
(!Vec3.equal(Camera.getPosition(), lastCameraPosition) || !Quat.equal(Camera.getOrientation(), lastCameraOrientation))){
that.select(currentSelection, false, false);
that.select(selectionManager.selections[0], false, false);
}
};
@ -2033,7 +1998,7 @@ SelectionDisplay = (function () {
var overlayOrientation;
var overlayCenter;
var properties = Entities.getEntityProperties(currentSelection);
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
var angles = Quat.safeEulerAngles(properties.rotation);
var pitch = angles.x;
var yaw = angles.y;
@ -2169,12 +2134,11 @@ SelectionDisplay = (function () {
if (somethingClicked) {
pickRay = Camera.computePickRay(event.x, event.y);
lastPlaneIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition,
lastPlaneIntersection = rayPlaneIntersection(pickRay, selectionManager.worldPosition,
Quat.getFront(lastCameraOrientation));
if (wantDebug) {
print("mousePressEvent()...... " + overlayNames[result.overlayID]);
Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection);
Vec3.print(" originalPosition:", selectedEntityPropertiesOriginalPosition);
}
}
@ -2289,8 +2253,8 @@ SelectionDisplay = (function () {
};
that.updateHandleSizes = function() {
if (selectedEntityProperties) {
var diff = Vec3.subtract(selectedEntityProperties.position, Camera.getPosition());
if (selectionManager.hasSelection()) {
var diff = Vec3.subtract(selectionManager.worldPosition, Camera.getPosition());
var grabberSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO;
for (var i = 0; i < stretchHandles.length; i++) {
Overlays.editOverlay(stretchHandles[i], {
@ -2336,15 +2300,10 @@ SelectionDisplay = (function () {
mode = "UNKNOWN";
// if something is selected, then reset the "original" properties for any potential next click+move operation
if (entitySelected) {
if (SelectionManager.hasSelection()) {
if (showHandles) {
that.select(currentSelection, event);
that.select(SelectionManager.selections[0], event);
}
selectedEntityProperties = Entities.getEntityProperties(currentSelection);
selectedEntityPropertiesOriginalPosition = properties.position;
selectedEntityPropertiesOriginalDimensions = properties.dimensions;
}
};

View file

@ -174,7 +174,7 @@ function maybeCleanupLobby() {
function toggleEnvironmentRendering(shouldRender) {
Menu.setIsOptionChecked("Voxels", shouldRender);
Menu.setIsOptionChecked("Models", shouldRender);
Menu.setIsOptionChecked("Entities", shouldRender);
Menu.setIsOptionChecked("Metavoxels", shouldRender);
Menu.setIsOptionChecked("Avatars", shouldRender);
}

View file

@ -256,7 +256,7 @@ var toolBar = (function () {
if (activeButton === toolBar.clicked(clickedOverlay)) {
isActive = !isActive;
if (!isActive) {
selectionDisplay.unselectAll();
selectionManager.clearSelections();
cameraManager.disable();
} else {
cameraManager.enable();
@ -386,9 +386,7 @@ function isLocked(properties) {
}
var entitySelected = false;
var selectedEntityID;
var selectedEntityProperties;
var mouseLastPosition;
var orientation;
var intersection;
@ -408,13 +406,12 @@ function mousePressEvent(event) {
mouseLastPosition = { x: event.x, y: event.y };
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
var entitySelected = false;
if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)
|| cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) {
// Event handled; do nothing.
return;
} else {
entitySelected = false;
selectionDisplay.unselectAll();
// If we aren't active and didn't click on an overlay: quit
if (!isActive) {
@ -426,6 +423,7 @@ function mousePressEvent(event) {
var foundIntersection = Entities.findRayIntersection(pickRay);
if(!foundIntersection.accurate) {
selectionManager.clearSelections();
return;
}
var foundEntity = foundIntersection.entityID;
@ -434,6 +432,7 @@ function mousePressEvent(event) {
var identify = Entities.identifyEntity(foundEntity);
if (!identify.isKnownID) {
print("Unknown ID " + identify.id + " (update loop " + foundEntity.id + ")");
selectionManager.clearSelections();
return;
}
foundEntity = identify;
@ -474,7 +473,6 @@ function mousePressEvent(event) {
if (0 < x && sizeOK) {
entitySelected = true;
selectedEntityID = foundEntity;
selectedEntityProperties = properties;
orientation = MyAvatar.orientation;
intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
@ -483,29 +481,11 @@ function mousePressEvent(event) {
}
selectionManager.addEntity(foundEntity);
print("Model selected selectedEntityID:" + selectedEntityID.id);
print("Model selected: " + foundEntity.id);
}
}
}
if (entitySelected) {
selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions;
selectedEntityProperties.oldPosition = {
x: selectedEntityProperties.position.x,
y: selectedEntityProperties.position.y,
z: selectedEntityProperties.position.z,
};
selectedEntityProperties.oldRotation = {
x: selectedEntityProperties.rotation.x,
y: selectedEntityProperties.rotation.y,
z: selectedEntityProperties.rotation.z,
w: selectedEntityProperties.rotation.w,
};
selectedEntityProperties.glowLevel = 0.0;
print("Clicked on " + selectedEntityID.id + " " + entitySelected);
tooltip.updateText(selectedEntityProperties);
tooltip.show(true);
selectionDisplay.select(selectedEntityID, event);
}
}
@ -554,7 +534,7 @@ function mouseReleaseEvent(event) {
if (!isActive) {
return;
}
if (entitySelected) {
if (selectionManager.hasSelection()) {
tooltip.show(false);
}
cameraManager.mouseReleaseEvent(event);
@ -584,6 +564,7 @@ function setupModelMenus() {
print("delete exists... don't add ours");
}
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
afterItem: "Paste Models", isCheckable: true });
@ -606,6 +587,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", "Delete");
}
Menu.removeMenuItem("Edit", "Model List...");
Menu.removeMenuItem("Edit", "Paste Models");
Menu.removeMenuItem("Edit", "Allow Select Large Models");
Menu.removeMenuItem("Edit", "Allow Select Small Models");
@ -642,7 +624,7 @@ function handeMenuEvent(menuItem) {
allowLargeModels = Menu.isOptionChecked("Allow Select Large Models");
} else if (menuItem == "Delete") {
if (SelectionManager.hasSelection()) {
print(" Delete Entity.... selectedEntityID="+ selectedEntityID);
print(" Delete Entities");
SelectionManager.saveProperties();
var savedProperties = [];
for (var i = 0; i < selectionManager.selections.length; i++) {
@ -657,11 +639,41 @@ function handeMenuEvent(menuItem) {
}
SelectionManager.clearSelections();
pushCommandForSelections([], savedProperties);
selectionDisplay.unselect(selectedEntityID);
entitySelected = false;
} else {
print(" Delete Entity.... not holding...");
}
} else if (menuItem == "Model List...") {
var models = new Array();
models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE);
for (var i = 0; i < models.length; i++) {
models[i].properties = Entities.getEntityProperties(models[i]);
models[i].toString = function() {
var modelname;
if (this.properties.type == "Model") {
modelname = decodeURIComponent(
this.properties.modelURL.indexOf("/") != -1 ?
this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) :
this.properties.modelURL);
} else {
modelname = this.properties.id;
}
return "[" + this.properties.type + "] " + modelname;
};
}
var form = [{label: "Model: ", options: models}];
form.push({label: "Action: ", options: ["Properties", "Delete", "Teleport"]});
form.push({ button: "Cancel" });
if (Window.form("Model List", form)) {
var selectedModel = form[0].value;
if (form[1].value == "Properties") {
editModelID = selectedModel;
showPropertiesForm(editModelID);
} else if (form[1].value == "Delete") {
Entities.deleteEntity(selectedModel);
} else if (form[1].value == "Teleport") {
MyAvatar.position = selectedModel.properties.position;
}
}
} else if (menuItem == "Edit Properties...") {
// good place to put the properties dialog
@ -706,11 +718,7 @@ Controller.keyReleaseEvent.connect(function (event) {
} else if (event.text == "TAB") {
selectionDisplay.toggleSpaceMode();
} else if (event.text == "f") {
if (entitySelected) {
// Get latest properties
var properties = Entities.getEntityProperties(selectedEntityID);
cameraManager.focus(properties);
}
cameraManager.focus();
} else if (event.text == '[') {
if (isActive) {
cameraManager.enable();

View file

@ -2349,7 +2349,7 @@ void Application::update(float deltaTime) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
queryOctree(NodeType::EntityServer, PacketTypeEntityQuery, _entityServerJurisdictions);
}
_lastQueriedViewFrustum = _viewFrustum;
@ -2996,7 +2996,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
}
// render models...
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
PerformanceTimer perfTimer("entities");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... entities...");

View file

@ -41,7 +41,7 @@ void FileLogger::addMessage(QString message) {
QFile file(_fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream out(&file);
out << message;
out << message << "\n";
}
}

View file

@ -366,7 +366,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Avatars, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Models, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Entities, 0, true);
QMenu* shadowMenu = renderOptionsMenu->addMenu("Shadows");
QActionGroup* shadowGroup = new QActionGroup(shadowMenu);
@ -433,14 +433,16 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
QMenu* modelDebugMenu = developerMenu->addMenu("Models");
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
QMenu* modelCullingMenu = modelDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontReduceMaterialSwitches, 0, false);
QMenu* entitiesDebugMenu = developerMenu->addMenu("Entities");
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisableLightEntities, 0, false);
QMenu* entityCullingMenu = entitiesDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontReduceMaterialSwitches, 0, false);
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels");
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);

View file

@ -384,6 +384,7 @@ namespace MenuOption {
const QString DecreaseVoxelSize = "Decrease Voxel Size";
const QString DisableActivityLogger = "Disable Activity Logger";
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
const QString DisableLightEntities = "Disable Light Entities";
const QString DisableNackPackets = "Disable NACK Packets";
const QString DisplayFrustum = "Display Frustum";
const QString DisplayHands = "Show Hand Info";
@ -400,6 +401,7 @@ namespace MenuOption {
const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableGlowEffect = "Enable Glow Effect (Warning: Poor Oculus Performance)";
const QString EnableVRMode = "Enable VR Mode";
const QString Entities = "Entities";
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
const QString ExpandOtherAvatarTiming = "Expand /otherAvatar";
@ -430,8 +432,6 @@ namespace MenuOption {
const QString MetavoxelEditor = "Metavoxel Editor...";
const QString Metavoxels = "Metavoxels";
const QString Mirror = "Mirror";
const QString ModelOptions = "Model Options";
const QString Models = "Models";
const QString MoveWithLean = "Move with Lean";
const QString MuteAudio = "Mute Microphone";
const QString MuteEnvironment = "Mute Environment";

View file

@ -61,15 +61,18 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
float exponent = getExponent();
float cutoff = glm::radians(getCutoff());
if (_isSpotlight) {
Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation,
direction, exponent, cutoff);
} else {
Application::getInstance()->getDeferredLightingEffect()->addPointLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
}
bool disableLights = Menu::getInstance()->isOptionChecked(MenuOption::DisableLightEntities);
if (!disableLights) {
if (_isSpotlight) {
Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation,
direction, exponent, cutoff);
} else {
Application::getInstance()->getDeferredLightingEffect()->addPointLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
}
}
bool wantDebug = false;
if (wantDebug) {
glColor4f(diffuseR, diffuseG, diffuseB, 1.0f);

View file

@ -38,12 +38,9 @@ RenderableModelEntityItem::~RenderableModelEntityItem() {
bool RenderableModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) {
QString oldModelURL = getModelURL();
QString oldTextures = getTextures();
bool somethingChanged = ModelEntityItem::setProperties(properties, forceCopy);
if (somethingChanged) {
if ((oldModelURL != getModelURL()) || (oldTextures != getTextures())) {
_needsModelReload = true;
}
if (somethingChanged && oldModelURL != getModelURL()) {
_needsModelReload = true;
}
return somethingChanged;
}
@ -60,6 +57,47 @@ int RenderableModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned c
return bytesRead;
}
void RenderableModelEntityItem::remapTextures() {
if (!_model) {
return; // nothing to do if we don't have a model
}
if (_currentTextures == _textures) {
return; // nothing to do if our recently mapped textures match our desired textures
}
qDebug() << "void RenderableModelEntityItem::remapTextures()....";
// since we're changing here, we need to run through our current texture map
// and any textures in the recently mapped texture, that is not in our desired
// textures, we need to "unset"
QJsonDocument currentTexturesAsJson = QJsonDocument::fromJson(_currentTextures.toUtf8());
QJsonObject currentTexturesAsJsonObject = currentTexturesAsJson.object();
QVariantMap currentTextureMap = currentTexturesAsJsonObject.toVariantMap();
QJsonDocument texturesAsJson = QJsonDocument::fromJson(_textures.toUtf8());
QJsonObject texturesAsJsonObject = texturesAsJson.object();
QVariantMap textureMap = texturesAsJsonObject.toVariantMap();
foreach(const QString& key, currentTextureMap.keys()) {
// if the desired texture map (what we're setting the textures to) doesn't
// contain this texture, then remove it by setting the URL to null
if (!textureMap.contains(key)) {
QUrl noURL;
qDebug() << "Removing texture named" << key << "by replacing it with no URL";
_model->setTextureWithNameToURL(key, noURL);
}
}
// here's where we remap any textures if needed...
foreach(const QString& key, textureMap.keys()) {
QUrl newTextureURL = textureMap[key].toUrl();
qDebug() << "Updating texture named" << key << "to texture at URL" << newTextureURL;
_model->setTextureWithNameToURL(key, newTextureURL);
}
_currentTextures = _textures;
}
void RenderableModelEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RMEIrender");
@ -72,6 +110,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE;
if (drawAsModel) {
remapTextures();
glPushMatrix();
{
float alpha = getLocalRenderAlpha();
@ -159,6 +198,10 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
}
assert(_myRenderer == renderer); // you should only ever render on one renderer
if (QThread::currentThread() != _myRenderer->thread()) {
return _model;
}
_needsModelReload = false; // this is the reload
// if we have a URL, then we will want to end up returning a model...
@ -183,18 +226,6 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
}
}
// here's where we remap any textures if needed...
if (!_textures.isEmpty() && _model) {
QJsonDocument texturesAsJson = QJsonDocument::fromJson(_textures.toUtf8());
QJsonObject texturesAsJsonObject = texturesAsJson.object();
QVariantMap textureMap = texturesAsJsonObject.toVariantMap();
foreach(const QString& key, textureMap.keys()) {
QUrl newTextureURL = textureMap[key].toUrl();
qDebug() << "Updating texture named" << key << "to texture at URL" << newTextureURL;
_model->setTextureWithNameToURL(key, newTextureURL);
}
}
return result;
}

View file

@ -51,12 +51,14 @@ public:
virtual void render(RenderArgs* args);
Model* getModel(EntityTreeRenderer* renderer);
private:
void remapTextures();
bool needsSimulation() const;
Model* _model;
bool _needsInitialSimulation;
bool _needsModelReload;
EntityTreeRenderer* _myRenderer;
QString _currentTextures;
};
#endif // hifi_RenderableModelEntityItem_h

View file

@ -86,13 +86,13 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
switch(voxelPacketType) {
case PacketTypeEntityErase: {
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
app->_entities.processEraseMessage(mutablePacket, sendingNode);
}
} break;
case PacketTypeEntityData: {
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
app->_entities.processDatagram(mutablePacket, sendingNode);
}
} break;