mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-28 07:50:37 +02:00
merging with current upstrem
This commit is contained in:
commit
3d5bf9aa1a
48 changed files with 1250 additions and 519 deletions
|
@ -176,7 +176,7 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"label": "Enabled",
|
"label": "Enabled",
|
||||||
"help": "Assigns an asset-server in your domain to serve files to clients via the ATP protocol (over UDP)",
|
"help": "Assigns an asset-server in your domain to serve files to clients via the ATP protocol (over UDP)",
|
||||||
"default": false,
|
"default": true,
|
||||||
"advanced": true
|
"advanced": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -480,7 +480,7 @@ function MyController(hand, triggerAction) {
|
||||||
var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset);
|
var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset);
|
||||||
|
|
||||||
this.actionID = NULL_ACTION_ID;
|
this.actionID = NULL_ACTION_ID;
|
||||||
this.actionID = Entities.addAction("kinematic-hold", this.grabbedEntity, {
|
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
|
||||||
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||||
relativePosition: offsetPosition,
|
relativePosition: offsetPosition,
|
||||||
|
|
567
examples/edit.js
567
examples/edit.js
|
@ -39,7 +39,9 @@ var lightOverlayManager = new LightOverlayManager();
|
||||||
var cameraManager = new CameraManager();
|
var cameraManager = new CameraManager();
|
||||||
|
|
||||||
var grid = Grid();
|
var grid = Grid();
|
||||||
gridTool = GridTool({ horizontalGrid: grid });
|
gridTool = GridTool({
|
||||||
|
horizontalGrid: grid
|
||||||
|
});
|
||||||
gridTool.setVisible(false);
|
gridTool.setVisible(false);
|
||||||
|
|
||||||
var entityListTool = EntityListTool();
|
var entityListTool = EntityListTool();
|
||||||
|
@ -93,7 +95,7 @@ var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary p
|
||||||
|
|
||||||
var modelURLs = [
|
var modelURLs = [
|
||||||
"Insert the URL to your FBX"
|
"Insert the URL to your FBX"
|
||||||
];
|
];
|
||||||
|
|
||||||
var mode = 0;
|
var mode = 0;
|
||||||
var isActive = false;
|
var isActive = false;
|
||||||
|
@ -109,20 +111,30 @@ var importingSVOImageOverlay = Overlays.addOverlay("image", {
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
alpha: 1.0,
|
alpha: 1.0,
|
||||||
color: { red: 255, green: 255, blue: 255 },
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
},
|
||||||
x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH,
|
x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH,
|
||||||
y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT,
|
y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT,
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
var importingSVOTextOverlay = Overlays.addOverlay("text", {
|
var importingSVOTextOverlay = Overlays.addOverlay("text", {
|
||||||
font: { size: 14 },
|
font: {
|
||||||
|
size: 14
|
||||||
|
},
|
||||||
text: "Importing SVO...",
|
text: "Importing SVO...",
|
||||||
leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN,
|
leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN,
|
||||||
x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN,
|
x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN,
|
||||||
y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN,
|
y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN,
|
||||||
width: IMPORTING_SVO_OVERLAY_WIDTH,
|
width: IMPORTING_SVO_OVERLAY_WIDTH,
|
||||||
height: IMPORTING_SVO_OVERLAY_HEIGHT,
|
height: IMPORTING_SVO_OVERLAY_HEIGHT,
|
||||||
backgroundColor: { red: 80, green: 80, blue: 80 },
|
backgroundColor: {
|
||||||
|
red: 80,
|
||||||
|
green: 80,
|
||||||
|
blue: 80
|
||||||
|
},
|
||||||
backgroundAlpha: 0.7,
|
backgroundAlpha: 0.7,
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
@ -131,7 +143,7 @@ var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
|
||||||
var marketplaceWindow = new WebWindow('Marketplace', MARKETPLACE_URL, 900, 700, false);
|
var marketplaceWindow = new WebWindow('Marketplace', MARKETPLACE_URL, 900, 700, false);
|
||||||
marketplaceWindow.setVisible(false);
|
marketplaceWindow.setVisible(false);
|
||||||
|
|
||||||
var toolBar = (function () {
|
var toolBar = (function() {
|
||||||
var that = {},
|
var that = {},
|
||||||
toolBar,
|
toolBar,
|
||||||
activeButton,
|
activeButton,
|
||||||
|
@ -146,7 +158,7 @@ var toolBar = (function () {
|
||||||
browseMarketplaceButton;
|
browseMarketplaceButton;
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function (windowDimensions, toolbar) {
|
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) {
|
||||||
return {
|
return {
|
||||||
x: windowDimensions.x - 8 - toolbar.width,
|
x: windowDimensions.x - 8 - toolbar.width,
|
||||||
y: (windowDimensions.y - toolbar.height) / 2
|
y: (windowDimensions.y - toolbar.height) / 2
|
||||||
|
@ -163,7 +175,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
activeButton = toolBar.addTool({
|
activeButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "edit-status.svg",
|
imageURL: toolIconUrl + "edit-status.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: Tool.IMAGE_WIDTH,
|
||||||
|
width: Tool.IMAGE_WIDTH,
|
||||||
|
height: Tool.IMAGE_HEIGHT
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -172,7 +189,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newModelButton = toolBar.addTool({
|
newModelButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "upload.svg",
|
imageURL: toolIconUrl + "upload.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: Tool.IMAGE_WIDTH,
|
||||||
|
width: Tool.IMAGE_WIDTH,
|
||||||
|
height: Tool.IMAGE_HEIGHT
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -181,7 +203,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newCubeButton = toolBar.addTool({
|
newCubeButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "add-cube.svg",
|
imageURL: toolIconUrl + "add-cube.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: Tool.IMAGE_WIDTH,
|
||||||
|
width: Tool.IMAGE_WIDTH,
|
||||||
|
height: Tool.IMAGE_HEIGHT
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -190,7 +217,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newSphereButton = toolBar.addTool({
|
newSphereButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "add-sphere.svg",
|
imageURL: toolIconUrl + "add-sphere.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: Tool.IMAGE_WIDTH,
|
||||||
|
width: Tool.IMAGE_WIDTH,
|
||||||
|
height: Tool.IMAGE_HEIGHT
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -199,7 +231,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newLightButton = toolBar.addTool({
|
newLightButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "light.svg",
|
imageURL: toolIconUrl + "light.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: Tool.IMAGE_WIDTH,
|
||||||
|
width: Tool.IMAGE_WIDTH,
|
||||||
|
height: Tool.IMAGE_HEIGHT
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -208,7 +245,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newTextButton = toolBar.addTool({
|
newTextButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "add-text.svg",
|
imageURL: toolIconUrl + "add-text.svg",
|
||||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: Tool.IMAGE_WIDTH,
|
||||||
|
width: Tool.IMAGE_WIDTH,
|
||||||
|
height: Tool.IMAGE_HEIGHT
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -217,7 +259,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newWebButton = toolBar.addTool({
|
newWebButton = toolBar.addTool({
|
||||||
imageURL: "https://hifi-public.s3.amazonaws.com/images/www.svg",
|
imageURL: "https://hifi-public.s3.amazonaws.com/images/www.svg",
|
||||||
subImage: { x: 0, y: 0, width: 128, height: 128 },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 128,
|
||||||
|
height: 128
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -226,7 +273,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newZoneButton = toolBar.addTool({
|
newZoneButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "zonecube_text.svg",
|
imageURL: toolIconUrl + "zonecube_text.svg",
|
||||||
subImage: { x: 0, y: 128, width: 128, height: 128 },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: 128,
|
||||||
|
width: 128,
|
||||||
|
height: 128
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -235,7 +287,12 @@ var toolBar = (function () {
|
||||||
|
|
||||||
newPolyVoxButton = toolBar.addTool({
|
newPolyVoxButton = toolBar.addTool({
|
||||||
imageURL: toolIconUrl + "polyvox.svg",
|
imageURL: toolIconUrl + "polyvox.svg",
|
||||||
subImage: { x: 0, y: 0, width: 256, height: 256 },
|
subImage: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 256,
|
||||||
|
height: 256
|
||||||
|
},
|
||||||
width: toolWidth,
|
width: toolWidth,
|
||||||
height: toolHeight,
|
height: toolHeight,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
|
@ -293,6 +350,7 @@ var toolBar = (function () {
|
||||||
var RESIZE_INTERVAL = 50;
|
var RESIZE_INTERVAL = 50;
|
||||||
var RESIZE_TIMEOUT = 120000; // 2 minutes
|
var RESIZE_TIMEOUT = 120000; // 2 minutes
|
||||||
var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL;
|
var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL;
|
||||||
|
|
||||||
function addModel(url) {
|
function addModel(url) {
|
||||||
var entityID = createNewEntity({
|
var entityID = createNewEntity({
|
||||||
type: "Model",
|
type: "Model",
|
||||||
|
@ -329,12 +387,15 @@ var toolBar = (function () {
|
||||||
|
|
||||||
var newModelButtonDown = false;
|
var newModelButtonDown = false;
|
||||||
var browseMarketplaceButtonDown = false;
|
var browseMarketplaceButtonDown = false;
|
||||||
that.mousePressEvent = function (event) {
|
that.mousePressEvent = function(event) {
|
||||||
var clickedOverlay,
|
var clickedOverlay,
|
||||||
url,
|
url,
|
||||||
file;
|
file;
|
||||||
|
|
||||||
clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
|
|
||||||
if (activeButton === toolBar.clicked(clickedOverlay)) {
|
if (activeButton === toolBar.clicked(clickedOverlay)) {
|
||||||
that.setActive(!isActive);
|
that.setActive(!isActive);
|
||||||
|
@ -360,7 +421,11 @@ var toolBar = (function () {
|
||||||
createNewEntity({
|
createNewEntity({
|
||||||
type: "Box",
|
type: "Box",
|
||||||
dimensions: DEFAULT_DIMENSIONS,
|
dimensions: DEFAULT_DIMENSIONS,
|
||||||
color: { red: 255, green: 0, blue: 0 }
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -370,7 +435,11 @@ var toolBar = (function () {
|
||||||
createNewEntity({
|
createNewEntity({
|
||||||
type: "Sphere",
|
type: "Sphere",
|
||||||
dimensions: DEFAULT_DIMENSIONS,
|
dimensions: DEFAULT_DIMENSIONS,
|
||||||
color: { red: 255, green: 0, blue: 0 }
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -381,7 +450,11 @@ var toolBar = (function () {
|
||||||
type: "Light",
|
type: "Light",
|
||||||
dimensions: DEFAULT_LIGHT_DIMENSIONS,
|
dimensions: DEFAULT_LIGHT_DIMENSIONS,
|
||||||
isSpotlight: false,
|
isSpotlight: false,
|
||||||
color: { red: 150, green: 150, blue: 150 },
|
color: {
|
||||||
|
red: 150,
|
||||||
|
green: 150,
|
||||||
|
blue: 150
|
||||||
|
},
|
||||||
|
|
||||||
constantAttenuation: 1,
|
constantAttenuation: 1,
|
||||||
linearAttenuation: 0,
|
linearAttenuation: 0,
|
||||||
|
@ -396,9 +469,21 @@ var toolBar = (function () {
|
||||||
if (newTextButton === toolBar.clicked(clickedOverlay)) {
|
if (newTextButton === toolBar.clicked(clickedOverlay)) {
|
||||||
createNewEntity({
|
createNewEntity({
|
||||||
type: "Text",
|
type: "Text",
|
||||||
dimensions: { x: 0.65, y: 0.3, z: 0.01 },
|
dimensions: {
|
||||||
backgroundColor: { red: 64, green: 64, blue: 64 },
|
x: 0.65,
|
||||||
textColor: { red: 255, green: 255, blue: 255 },
|
y: 0.3,
|
||||||
|
z: 0.01
|
||||||
|
},
|
||||||
|
backgroundColor: {
|
||||||
|
red: 64,
|
||||||
|
green: 64,
|
||||||
|
blue: 64
|
||||||
|
},
|
||||||
|
textColor: {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
},
|
||||||
text: "some text",
|
text: "some text",
|
||||||
lineHeight: 0.06
|
lineHeight: 0.06
|
||||||
});
|
});
|
||||||
|
@ -409,7 +494,11 @@ var toolBar = (function () {
|
||||||
if (newWebButton === toolBar.clicked(clickedOverlay)) {
|
if (newWebButton === toolBar.clicked(clickedOverlay)) {
|
||||||
createNewEntity({
|
createNewEntity({
|
||||||
type: "Web",
|
type: "Web",
|
||||||
dimensions: { x: 1.6, y: 0.9, z: 0.01 },
|
dimensions: {
|
||||||
|
x: 1.6,
|
||||||
|
y: 0.9,
|
||||||
|
z: 0.01
|
||||||
|
},
|
||||||
sourceUrl: "https://highfidelity.com/",
|
sourceUrl: "https://highfidelity.com/",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -419,7 +508,11 @@ var toolBar = (function () {
|
||||||
if (newZoneButton === toolBar.clicked(clickedOverlay)) {
|
if (newZoneButton === toolBar.clicked(clickedOverlay)) {
|
||||||
createNewEntity({
|
createNewEntity({
|
||||||
type: "Zone",
|
type: "Zone",
|
||||||
dimensions: { x: 10, y: 10, z: 10 },
|
dimensions: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
z: 10
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -428,27 +521,83 @@ var toolBar = (function () {
|
||||||
if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) {
|
if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) {
|
||||||
var polyVoxId = createNewEntity({
|
var polyVoxId = createNewEntity({
|
||||||
type: "PolyVox",
|
type: "PolyVox",
|
||||||
dimensions: { x: 10, y: 10, z: 10 },
|
dimensions: {
|
||||||
voxelVolumeSize: {x:16, y:16, z:16},
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
z: 10
|
||||||
|
},
|
||||||
|
voxelVolumeSize: {
|
||||||
|
x: 16,
|
||||||
|
y: 16,
|
||||||
|
z: 16
|
||||||
|
},
|
||||||
voxelSurfaceStyle: 2
|
voxelSurfaceStyle: 2
|
||||||
});
|
});
|
||||||
for (var x = 1; x <= 14; x++) {
|
for (var x = 1; x <= 14; x++) {
|
||||||
Entities.setVoxel(polyVoxId, {x: x, y: 1, z: 1}, 255);
|
Entities.setVoxel(polyVoxId, {
|
||||||
Entities.setVoxel(polyVoxId, {x: x, y: 14, z: 1}, 255);
|
x: x,
|
||||||
Entities.setVoxel(polyVoxId, {x: x, y: 1, z: 14}, 255);
|
y: 1,
|
||||||
Entities.setVoxel(polyVoxId, {x: x, y: 14, z: 14}, 255);
|
z: 1
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: x,
|
||||||
|
y: 14,
|
||||||
|
z: 1
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: x,
|
||||||
|
y: 1,
|
||||||
|
z: 14
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: x,
|
||||||
|
y: 14,
|
||||||
|
z: 14
|
||||||
|
}, 255);
|
||||||
}
|
}
|
||||||
for (var y = 2; y <= 13; y++) {
|
for (var y = 2; y <= 13; y++) {
|
||||||
Entities.setVoxel(polyVoxId, {x: 1, y: y, z: 1}, 255);
|
Entities.setVoxel(polyVoxId, {
|
||||||
Entities.setVoxel(polyVoxId, {x: 14, y: y, z: 1}, 255);
|
x: 1,
|
||||||
Entities.setVoxel(polyVoxId, {x: 1, y: y, z: 14}, 255);
|
y: y,
|
||||||
Entities.setVoxel(polyVoxId, {x: 14, y: y, z: 14}, 255);
|
z: 1
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: 14,
|
||||||
|
y: y,
|
||||||
|
z: 1
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: 1,
|
||||||
|
y: y,
|
||||||
|
z: 14
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: 14,
|
||||||
|
y: y,
|
||||||
|
z: 14
|
||||||
|
}, 255);
|
||||||
}
|
}
|
||||||
for (var z = 2; z <= 13; z++) {
|
for (var z = 2; z <= 13; z++) {
|
||||||
Entities.setVoxel(polyVoxId, {x: 1, y: 1, z: z}, 255);
|
Entities.setVoxel(polyVoxId, {
|
||||||
Entities.setVoxel(polyVoxId, {x: 14, y: 1, z: z}, 255);
|
x: 1,
|
||||||
Entities.setVoxel(polyVoxId, {x: 1, y: 14, z: z}, 255);
|
y: 1,
|
||||||
Entities.setVoxel(polyVoxId, {x: 14, y: 14, z: z}, 255);
|
z: z
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: 14,
|
||||||
|
y: 1,
|
||||||
|
z: z
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: 1,
|
||||||
|
y: 14,
|
||||||
|
z: z
|
||||||
|
}, 255);
|
||||||
|
Entities.setVoxel(polyVoxId, {
|
||||||
|
x: 14,
|
||||||
|
y: 14,
|
||||||
|
z: z
|
||||||
|
}, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -461,7 +610,10 @@ var toolBar = (function () {
|
||||||
that.mouseReleaseEvent = function(event) {
|
that.mouseReleaseEvent = function(event) {
|
||||||
var handled = false;
|
var handled = false;
|
||||||
if (newModelButtonDown) {
|
if (newModelButtonDown) {
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
if (newModelButton === toolBar.clicked(clickedOverlay)) {
|
if (newModelButton === toolBar.clicked(clickedOverlay)) {
|
||||||
url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]);
|
url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]);
|
||||||
if (url !== null && url !== "") {
|
if (url !== null && url !== "") {
|
||||||
|
@ -470,7 +622,10 @@ var toolBar = (function () {
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
} else if (browseMarketplaceButtonDown) {
|
} else if (browseMarketplaceButtonDown) {
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
|
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
|
||||||
url = Window.s3Browse(".*(fbx|FBX|obj|OBJ)");
|
url = Window.s3Browse(".*(fbx|FBX|obj|OBJ)");
|
||||||
if (url !== null && url !== "") {
|
if (url !== null && url !== "") {
|
||||||
|
@ -497,7 +652,7 @@ var toolBar = (function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
that.cleanup = function () {
|
that.cleanup = function() {
|
||||||
toolBar.cleanup();
|
toolBar.cleanup();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -568,17 +723,26 @@ function findClickedEntity(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var foundEntity = result.entityID;
|
var foundEntity = result.entityID;
|
||||||
return { pickRay: pickRay, entityID: foundEntity };
|
return {
|
||||||
|
pickRay: pickRay,
|
||||||
|
entityID: foundEntity
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var mouseHasMovedSincePress = false;
|
var mouseHasMovedSincePress = false;
|
||||||
var mousePressStartTime = 0;
|
var mousePressStartTime = 0;
|
||||||
var mousePressStartPosition = { x: 0, y: 0 };
|
var mousePressStartPosition = {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
};
|
||||||
var mouseDown = false;
|
var mouseDown = false;
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
function mousePressEvent(event) {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
mousePressStartPosition = { x: event.x, y: event.y };
|
mousePressStartPosition = {
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
};
|
||||||
mousePressStartTime = Date.now();
|
mousePressStartTime = Date.now();
|
||||||
mouseHasMovedSincePress = false;
|
mouseHasMovedSincePress = false;
|
||||||
mouseCapturedByTool = false;
|
mouseCapturedByTool = false;
|
||||||
|
@ -605,9 +769,11 @@ var IDLE_MOUSE_TIMEOUT = 200;
|
||||||
var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0;
|
var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0;
|
||||||
|
|
||||||
var lastMouseMoveEvent = null;
|
var lastMouseMoveEvent = null;
|
||||||
|
|
||||||
function mouseMoveEventBuffered(event) {
|
function mouseMoveEventBuffered(event) {
|
||||||
lastMouseMoveEvent = event;
|
lastMouseMoveEvent = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseMove(event) {
|
function mouseMove(event) {
|
||||||
if (mouseDown && !mouseHasMovedSincePress) {
|
if (mouseDown && !mouseHasMovedSincePress) {
|
||||||
var timeSincePressMicro = Date.now() - mousePressStartTime;
|
var timeSincePressMicro = Date.now() - mousePressStartTime;
|
||||||
|
@ -647,7 +813,10 @@ function mouseMove(event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastMousePosition = { x: event.x, y: event.y };
|
lastMousePosition = {
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
};
|
||||||
|
|
||||||
idleMouseTimerId = Script.setTimeout(handleIdleMouse, IDLE_MOUSE_TIMEOUT);
|
idleMouseTimerId = Script.setTimeout(handleIdleMouse, IDLE_MOUSE_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
@ -660,9 +829,11 @@ function highlightEntityUnderCursor(position, accurateRay) {
|
||||||
var pickRay = Camera.computePickRay(position.x, position.y);
|
var pickRay = Camera.computePickRay(position.x, position.y);
|
||||||
var entityIntersection = Entities.findRayIntersection(pickRay, accurateRay);
|
var entityIntersection = Entities.findRayIntersection(pickRay, accurateRay);
|
||||||
if (entityIntersection.accurate) {
|
if (entityIntersection.accurate) {
|
||||||
if(highlightedEntityID && highlightedEntityID != entityIntersection.entityID) {
|
if (highlightedEntityID && highlightedEntityID != entityIntersection.entityID) {
|
||||||
selectionDisplay.unhighlightSelectable(highlightedEntityID);
|
selectionDisplay.unhighlightSelectable(highlightedEntityID);
|
||||||
highlightedEntityID = { id: -1 };
|
highlightedEntityID = {
|
||||||
|
id: -1
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0;
|
var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0;
|
||||||
|
@ -670,12 +841,13 @@ function highlightEntityUnderCursor(position, accurateRay) {
|
||||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(),
|
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(),
|
||||||
entityIntersection.properties.position)) * 180 / 3.14;
|
entityIntersection.properties.position)) * 180 / 3.14;
|
||||||
|
|
||||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
|
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||||
&& (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
|
||||||
|
|
||||||
if (entityIntersection.entityID && sizeOK) {
|
if (entityIntersection.entityID && sizeOK) {
|
||||||
if (wantEntityGlow) {
|
if (wantEntityGlow) {
|
||||||
Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 });
|
Entities.editEntity(entityIntersection.entityID, {
|
||||||
|
glowLevel: 0.25
|
||||||
|
});
|
||||||
}
|
}
|
||||||
highlightedEntityID = entityIntersection.entityID;
|
highlightedEntityID = entityIntersection.entityID;
|
||||||
selectionDisplay.highlightSelectable(entityIntersection.entityID);
|
selectionDisplay.highlightSelectable(entityIntersection.entityID);
|
||||||
|
@ -693,18 +865,23 @@ function mouseReleaseEvent(event) {
|
||||||
lastMouseMoveEvent = null;
|
lastMouseMoveEvent = null;
|
||||||
}
|
}
|
||||||
if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) {
|
if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (placingEntityID) {
|
if (placingEntityID) {
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
|
|
||||||
selectionManager.setSelections([placingEntityID]);
|
selectionManager.setSelections([placingEntityID]);
|
||||||
}
|
}
|
||||||
placingEntityID = null;
|
placingEntityID = null;
|
||||||
}
|
}
|
||||||
if (isActive && selectionManager.hasSelection()) {
|
if (isActive && selectionManager.hasSelection()) {
|
||||||
|
|
||||||
tooltip.show(false);
|
tooltip.show(false);
|
||||||
}
|
}
|
||||||
if (mouseCapturedByTool) {
|
if (mouseCapturedByTool) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,8 +934,7 @@ function mouseClickEvent(event) {
|
||||||
|
|
||||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14;
|
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14;
|
||||||
|
|
||||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
|
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||||
&& (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
|
||||||
|
|
||||||
if (0 < x && sizeOK) {
|
if (0 < x && sizeOK) {
|
||||||
entitySelected = true;
|
entitySelected = true;
|
||||||
|
@ -813,44 +989,125 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||||
// added it.
|
// added it.
|
||||||
var modelMenuAddedDelete = false;
|
var modelMenuAddedDelete = false;
|
||||||
var originalLightsArePickable = Entities.getLightsArePickable();
|
var originalLightsArePickable = Entities.getLightsArePickable();
|
||||||
|
|
||||||
function setupModelMenus() {
|
function setupModelMenus() {
|
||||||
print("setupModelMenus()");
|
print("setupModelMenus()");
|
||||||
// adj our menuitems
|
// adj our menuitems
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" });
|
Menu.addMenuItem({
|
||||||
|
menuName: "Edit",
|
||||||
|
menuItemName: "Models",
|
||||||
|
isSeparator: true,
|
||||||
|
beforeItem: "Physics"
|
||||||
|
});
|
||||||
if (!Menu.menuItemExists("Edit", "Delete")) {
|
if (!Menu.menuItemExists("Edit", "Delete")) {
|
||||||
print("no delete... adding ours");
|
print("no delete... adding ours");
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete",
|
Menu.addMenuItem({
|
||||||
shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" });
|
menuName: "Edit",
|
||||||
|
menuItemName: "Delete",
|
||||||
|
shortcutKeyEvent: {
|
||||||
|
text: "backspace"
|
||||||
|
},
|
||||||
|
afterItem: "Models"
|
||||||
|
});
|
||||||
modelMenuAddedDelete = true;
|
modelMenuAddedDelete = true;
|
||||||
} else {
|
} else {
|
||||||
print("delete exists... don't add ours");
|
print("delete exists... don't add ours");
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entity List...", shortcutKey: "CTRL+META+L", afterItem: "Models" });
|
Menu.addMenuItem({
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L",
|
menuName: "Edit",
|
||||||
afterItem: "Entity List...", isCheckable: true, isChecked: true });
|
menuItemName: "Entity List...",
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S",
|
shortcutKey: "CTRL+META+L",
|
||||||
afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true });
|
afterItem: "Models"
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L",
|
});
|
||||||
afterItem: "Allow Selecting of Small Models", isCheckable: true });
|
Menu.addMenuItem({
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", shortcutKey: "CTRL+SHIFT+META+A",
|
menuName: "Edit",
|
||||||
afterItem: "Allow Selecting of Lights" });
|
menuItemName: "Allow Selecting of Large Models",
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", shortcutKey: "CTRL+SHIFT+META+T",
|
shortcutKey: "CTRL+META+L",
|
||||||
afterItem: "Select All Entities In Box" });
|
afterItem: "Entity List...",
|
||||||
|
isCheckable: true,
|
||||||
|
isChecked: true
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "Edit",
|
||||||
|
menuItemName: "Allow Selecting of Small Models",
|
||||||
|
shortcutKey: "CTRL+META+S",
|
||||||
|
afterItem: "Allow Selecting of Large Models",
|
||||||
|
isCheckable: true,
|
||||||
|
isChecked: true
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "Edit",
|
||||||
|
menuItemName: "Allow Selecting of Lights",
|
||||||
|
shortcutKey: "CTRL+SHIFT+META+L",
|
||||||
|
afterItem: "Allow Selecting of Small Models",
|
||||||
|
isCheckable: true
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "Edit",
|
||||||
|
menuItemName: "Select All Entities In Box",
|
||||||
|
shortcutKey: "CTRL+SHIFT+META+A",
|
||||||
|
afterItem: "Allow Selecting of Lights"
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "Edit",
|
||||||
|
menuItemName: "Select All Entities Touching Box",
|
||||||
|
shortcutKey: "CTRL+SHIFT+META+T",
|
||||||
|
afterItem: "Select All Entities In Box"
|
||||||
|
});
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
Menu.addMenuItem({
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Entities", shortcutKey: "CTRL+META+E", afterItem: "Models" });
|
menuName: "File",
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Entities", shortcutKey: "CTRL+META+I", afterItem: "Export Entities" });
|
menuItemName: "Models",
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Entities from URL", shortcutKey: "CTRL+META+U", afterItem: "Import Entities" });
|
isSeparator: true,
|
||||||
|
beforeItem: "Settings"
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "File",
|
||||||
|
menuItemName: "Export Entities",
|
||||||
|
shortcutKey: "CTRL+META+E",
|
||||||
|
afterItem: "Models"
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "File",
|
||||||
|
menuItemName: "Import Entities",
|
||||||
|
shortcutKey: "CTRL+META+I",
|
||||||
|
afterItem: "Export Entities"
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "File",
|
||||||
|
menuItemName: "Import Entities from URL",
|
||||||
|
shortcutKey: "CTRL+META+U",
|
||||||
|
afterItem: "Import Entities"
|
||||||
|
});
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
|
Menu.addMenuItem({
|
||||||
isCheckable: true, isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true" });
|
menuName: "View",
|
||||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_AUTO_FOCUS_ON_SELECT,
|
menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
|
||||||
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
|
isCheckable: true,
|
||||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS,
|
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true"
|
||||||
isCheckable: true, isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true" });
|
});
|
||||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
|
Menu.addMenuItem({
|
||||||
isCheckable: true, isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true" });
|
menuName: "View",
|
||||||
|
menuItemName: MENU_EASE_ON_FOCUS,
|
||||||
|
afterItem: MENU_AUTO_FOCUS_ON_SELECT,
|
||||||
|
isCheckable: true,
|
||||||
|
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true"
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "View",
|
||||||
|
menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
|
||||||
|
afterItem: MENU_EASE_ON_FOCUS,
|
||||||
|
isCheckable: true,
|
||||||
|
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true"
|
||||||
|
});
|
||||||
|
Menu.addMenuItem({
|
||||||
|
menuName: "View",
|
||||||
|
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
|
||||||
|
afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
|
||||||
|
isCheckable: true,
|
||||||
|
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true"
|
||||||
|
});
|
||||||
|
|
||||||
Entities.setLightsArePickable(false);
|
Entities.setLightsArePickable(false);
|
||||||
}
|
}
|
||||||
|
@ -903,7 +1160,7 @@ var lastOrientation = null;
|
||||||
var lastPosition = null;
|
var lastPosition = null;
|
||||||
|
|
||||||
// Do some stuff regularly, like check for placement of various overlays
|
// Do some stuff regularly, like check for placement of various overlays
|
||||||
Script.update.connect(function (deltaTime) {
|
Script.update.connect(function(deltaTime) {
|
||||||
progressDialog.move();
|
progressDialog.move();
|
||||||
selectionDisplay.checkMove();
|
selectionDisplay.checkMove();
|
||||||
var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1);
|
var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1);
|
||||||
|
@ -920,9 +1177,7 @@ Script.update.connect(function (deltaTime) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function insideBox(center, dimensions, point) {
|
function insideBox(center, dimensions, point) {
|
||||||
return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0))
|
return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && (Math.abs(point.z - center.z) <= (dimensions.z / 2.0));
|
||||||
&& (Math.abs(point.y - center.y) <= (dimensions.y / 2.0))
|
|
||||||
&& (Math.abs(point.z - center.z) <= (dimensions.z / 2.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
||||||
|
@ -943,7 +1198,11 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
||||||
var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation),
|
var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation),
|
||||||
Vec3.subtract(position,
|
Vec3.subtract(position,
|
||||||
selectionManager.localPosition));
|
selectionManager.localPosition));
|
||||||
return insideBox({ x: 0, y: 0, z: 0 }, selectionManager.localDimensions, localPosition);
|
return insideBox({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
}, selectionManager.localDimensions, localPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var i = 0; i < entities.length; ++i) {
|
for (var i = 0; i < entities.length; ++i) {
|
||||||
|
@ -1041,12 +1300,8 @@ function getPositionToCreateEntity() {
|
||||||
|
|
||||||
var HALF_TREE_SCALE = 16384;
|
var HALF_TREE_SCALE = 16384;
|
||||||
|
|
||||||
var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE
|
var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE;
|
||||||
|| Math.abs(cameraPosition.y) > HALF_TREE_SCALE
|
var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE;
|
||||||
|| Math.abs(cameraPosition.z) > HALF_TREE_SCALE;
|
|
||||||
var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE
|
|
||||||
|| Math.abs(placementPosition.y) > HALF_TREE_SCALE
|
|
||||||
|| Math.abs(placementPosition.z) > HALF_TREE_SCALE;
|
|
||||||
|
|
||||||
if (cameraOutOfBounds && placementOutOfBounds) {
|
if (cameraOutOfBounds && placementOutOfBounds) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1065,14 +1320,22 @@ function importSVO(importURL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Overlays.editOverlay(importingSVOTextOverlay, { visible: true });
|
Overlays.editOverlay(importingSVOTextOverlay, {
|
||||||
Overlays.editOverlay(importingSVOImageOverlay, { visible: true });
|
visible: true
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(importingSVOImageOverlay, {
|
||||||
|
visible: true
|
||||||
|
});
|
||||||
|
|
||||||
var success = Clipboard.importEntities(importURL);
|
var success = Clipboard.importEntities(importURL);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
var VERY_LARGE = 10000;
|
var VERY_LARGE = 10000;
|
||||||
var position = { x: 0, y: 0, z: 0 };
|
var position = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) {
|
if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) {
|
||||||
position = getPositionToCreateEntity();
|
position = getPositionToCreateEntity();
|
||||||
}
|
}
|
||||||
|
@ -1091,8 +1354,12 @@ function importSVO(importURL) {
|
||||||
Window.alert("There was an error importing the entity file.");
|
Window.alert("There was an error importing the entity file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Overlays.editOverlay(importingSVOTextOverlay, { visible: false });
|
Overlays.editOverlay(importingSVOTextOverlay, {
|
||||||
Overlays.editOverlay(importingSVOImageOverlay, { visible: false });
|
visible: false
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(importingSVOImageOverlay, {
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Window.svoImportRequested.connect(importSVO);
|
Window.svoImportRequested.connect(importSVO);
|
||||||
|
|
||||||
|
@ -1104,7 +1371,7 @@ Controller.keyPressEvent.connect(function(event) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Controller.keyReleaseEvent.connect(function (event) {
|
Controller.keyReleaseEvent.connect(function(event) {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
cameraManager.keyReleaseEvent(event);
|
cameraManager.keyReleaseEvent(event);
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1398,11 @@ Controller.keyReleaseEvent.connect(function (event) {
|
||||||
} else if (event.text == 'g') {
|
} else if (event.text == 'g') {
|
||||||
if (isActive && selectionManager.hasSelection()) {
|
if (isActive && selectionManager.hasSelection()) {
|
||||||
var newPosition = selectionManager.worldPosition;
|
var newPosition = selectionManager.worldPosition;
|
||||||
newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 });
|
newPosition = Vec3.subtract(newPosition, {
|
||||||
|
x: 0,
|
||||||
|
y: selectionManager.worldDimensions.y * 0.5,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
grid.setPosition(newPosition);
|
grid.setPosition(newPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1140,8 +1411,7 @@ Controller.keyReleaseEvent.connect(function (event) {
|
||||||
// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently
|
// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently
|
||||||
// possible to create an entity with a specific id, earlier undo commands to the deleted entity
|
// possible to create an entity with a specific id, earlier undo commands to the deleted entity
|
||||||
// will fail if there isn't a way to find the new entity id.
|
// will fail if there isn't a way to find the new entity id.
|
||||||
DELETED_ENTITY_MAP = {
|
DELETED_ENTITY_MAP = {}
|
||||||
}
|
|
||||||
|
|
||||||
function applyEntityProperties(data) {
|
function applyEntityProperties(data) {
|
||||||
var properties = data.setProperties;
|
var properties = data.setProperties;
|
||||||
|
@ -1293,7 +1563,11 @@ PropertiesTool = function(opts) {
|
||||||
if (selectionManager.hasSelection()) {
|
if (selectionManager.hasSelection()) {
|
||||||
selectionManager.saveProperties();
|
selectionManager.saveProperties();
|
||||||
var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2);
|
var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2);
|
||||||
var diff = { x: 0, y: dY, z: 0 };
|
var diff = {
|
||||||
|
x: 0,
|
||||||
|
y: dY,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||||
var newPosition = Vec3.sum(properties.position, diff);
|
var newPosition = Vec3.sum(properties.position, diff);
|
||||||
|
@ -1311,7 +1585,11 @@ PropertiesTool = function(opts) {
|
||||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||||
var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2;
|
var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2;
|
||||||
var dY = grid.getOrigin().y - bottomY;
|
var dY = grid.getOrigin().y - bottomY;
|
||||||
var diff = { x: 0, y: dY, z: 0 };
|
var diff = {
|
||||||
|
x: 0,
|
||||||
|
y: dY,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
var newPosition = Vec3.sum(properties.position, diff);
|
var newPosition = Vec3.sum(properties.position, diff);
|
||||||
Entities.editEntity(selectionManager.selections[i], {
|
Entities.editEntity(selectionManager.selections[i], {
|
||||||
position: newPosition,
|
position: newPosition,
|
||||||
|
@ -1328,10 +1606,8 @@ PropertiesTool = function(opts) {
|
||||||
var naturalDimensions = properties.naturalDimensions;
|
var naturalDimensions = properties.naturalDimensions;
|
||||||
|
|
||||||
// If any of the natural dimensions are not 0, resize
|
// If any of the natural dimensions are not 0, resize
|
||||||
if (properties.type == "Model" && naturalDimensions.x == 0
|
if (properties.type == "Model" && naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) {
|
||||||
&& naturalDimensions.y == 0 && naturalDimensions.z == 0) {
|
Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded.");
|
||||||
Window.alert("Cannot reset entity to its natural dimensions: Model URL"
|
|
||||||
+ " is invalid or the model has not yet been loaded.");
|
|
||||||
} else {
|
} else {
|
||||||
Entities.editEntity(selectionManager.selections[i], {
|
Entities.editEntity(selectionManager.selections[i], {
|
||||||
dimensions: properties.naturalDimensions,
|
dimensions: properties.naturalDimensions,
|
||||||
|
@ -1370,12 +1646,16 @@ PropertiesTool = function(opts) {
|
||||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||||
if (properties.type == "Zone") {
|
if (properties.type == "Zone") {
|
||||||
var centerOfZone = properties.boundingBox.center;
|
var centerOfZone = properties.boundingBox.center;
|
||||||
var atmosphereCenter = { x: centerOfZone.x,
|
var atmosphereCenter = {
|
||||||
|
x: centerOfZone.x,
|
||||||
y: centerOfZone.y - properties.atmosphere.innerRadius,
|
y: centerOfZone.y - properties.atmosphere.innerRadius,
|
||||||
z: centerOfZone.z };
|
z: centerOfZone.z
|
||||||
|
};
|
||||||
|
|
||||||
Entities.editEntity(selectionManager.selections[i], {
|
Entities.editEntity(selectionManager.selections[i], {
|
||||||
atmosphere: { center: atmosphereCenter },
|
atmosphere: {
|
||||||
|
center: atmosphereCenter
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1399,11 +1679,23 @@ PopupMenu = function() {
|
||||||
var overlays = [];
|
var overlays = [];
|
||||||
var overlayInfo = {};
|
var overlayInfo = {};
|
||||||
|
|
||||||
var upColor = { red: 0, green: 0, blue: 0 };
|
var upColor = {
|
||||||
var downColor = { red: 192, green: 192, blue: 192 };
|
red: 0,
|
||||||
var overColor = { red: 128, green: 128, blue: 128 };
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
};
|
||||||
|
var downColor = {
|
||||||
|
red: 192,
|
||||||
|
green: 192,
|
||||||
|
blue: 192
|
||||||
|
};
|
||||||
|
var overColor = {
|
||||||
|
red: 128,
|
||||||
|
green: 128,
|
||||||
|
blue: 128
|
||||||
|
};
|
||||||
|
|
||||||
self.onSelectMenuItem = function() { };
|
self.onSelectMenuItem = function() {};
|
||||||
|
|
||||||
self.addMenuItem = function(name) {
|
self.addMenuItem = function(name) {
|
||||||
var id = Overlays.addOverlay("text", {
|
var id = Overlays.addOverlay("text", {
|
||||||
|
@ -1414,16 +1706,22 @@ PopupMenu = function() {
|
||||||
leftMargin: TEXT_MARGIN,
|
leftMargin: TEXT_MARGIN,
|
||||||
width: 210,
|
width: 210,
|
||||||
height: MENU_ITEM_HEIGHT,
|
height: MENU_ITEM_HEIGHT,
|
||||||
font: { size: 12 },
|
font: {
|
||||||
|
size: 12
|
||||||
|
},
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
overlays.push(id);
|
overlays.push(id);
|
||||||
overlayInfo[id] = { name: name };
|
overlayInfo[id] = {
|
||||||
|
name: name
|
||||||
|
};
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.updateMenuItemText = function(id, newText) {
|
self.updateMenuItemText = function(id, newText) {
|
||||||
Overlays.editOverlay(id, { text: newText });
|
Overlays.editOverlay(id, {
|
||||||
|
text: newText
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.setPosition = function(x, y) {
|
self.setPosition = function(x, y) {
|
||||||
|
@ -1436,17 +1734,22 @@ PopupMenu = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onSelected = function() { };
|
self.onSelected = function() {};
|
||||||
|
|
||||||
var pressingOverlay = null;
|
var pressingOverlay = null;
|
||||||
var hoveringOverlay = null;
|
var hoveringOverlay = null;
|
||||||
|
|
||||||
self.mousePressEvent = function(event) {
|
self.mousePressEvent = function(event) {
|
||||||
if (event.isLeftButton) {
|
if (event.isLeftButton) {
|
||||||
var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
var overlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
if (overlay in overlayInfo) {
|
if (overlay in overlayInfo) {
|
||||||
pressingOverlay = overlay;
|
pressingOverlay = overlay;
|
||||||
Overlays.editOverlay(pressingOverlay, { backgroundColor: downColor });
|
Overlays.editOverlay(pressingOverlay, {
|
||||||
|
backgroundColor: downColor
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
self.hide();
|
self.hide();
|
||||||
}
|
}
|
||||||
|
@ -1455,14 +1758,21 @@ PopupMenu = function() {
|
||||||
};
|
};
|
||||||
self.mouseMoveEvent = function(event) {
|
self.mouseMoveEvent = function(event) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
var overlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
if (!pressingOverlay) {
|
if (!pressingOverlay) {
|
||||||
if (hoveringOverlay != null && overlay != hoveringOverlay) {
|
if (hoveringOverlay != null && overlay != hoveringOverlay) {
|
||||||
Overlays.editOverlay(hoveringOverlay, { backgroundColor: upColor});
|
Overlays.editOverlay(hoveringOverlay, {
|
||||||
|
backgroundColor: upColor
|
||||||
|
});
|
||||||
hoveringOverlay = null;
|
hoveringOverlay = null;
|
||||||
}
|
}
|
||||||
if (overlay != hoveringOverlay && overlay in overlayInfo) {
|
if (overlay != hoveringOverlay && overlay in overlayInfo) {
|
||||||
Overlays.editOverlay(overlay, { backgroundColor: overColor });
|
Overlays.editOverlay(overlay, {
|
||||||
|
backgroundColor: overColor
|
||||||
|
});
|
||||||
hoveringOverlay = overlay;
|
hoveringOverlay = overlay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1470,12 +1780,17 @@ PopupMenu = function() {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
self.mouseReleaseEvent = function(event) {
|
self.mouseReleaseEvent = function(event) {
|
||||||
var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
var overlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
if (pressingOverlay != null) {
|
if (pressingOverlay != null) {
|
||||||
if (overlay == pressingOverlay) {
|
if (overlay == pressingOverlay) {
|
||||||
self.onSelectMenuItem(overlayInfo[overlay].name);
|
self.onSelectMenuItem(overlayInfo[overlay].name);
|
||||||
}
|
}
|
||||||
Overlays.editOverlay(pressingOverlay, { backgroundColor: upColor });
|
Overlays.editOverlay(pressingOverlay, {
|
||||||
|
backgroundColor: upColor
|
||||||
|
});
|
||||||
pressingOverlay = null;
|
pressingOverlay = null;
|
||||||
self.hide();
|
self.hide();
|
||||||
}
|
}
|
||||||
|
@ -1487,7 +1802,9 @@ PopupMenu = function() {
|
||||||
if (newVisible != visible) {
|
if (newVisible != visible) {
|
||||||
visible = newVisible;
|
visible = newVisible;
|
||||||
for (var key in overlayInfo) {
|
for (var key in overlayInfo) {
|
||||||
Overlays.editOverlay(key, { visible: newVisible });
|
Overlays.editOverlay(key, {
|
||||||
|
visible: newVisible
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,20 @@
|
||||||
// Assumes you only have the default keyboard connected
|
// Assumes you only have the default keyboard connected
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var hydra = Controller.Hardware.Hydra2;
|
||||||
|
if (hydra !== undefined) {
|
||||||
|
print("-----------------------------------");
|
||||||
|
var mapping = NewControllers.newMapping("Default");
|
||||||
|
var standard = Controller.Standard;
|
||||||
|
print("standard:" + standard);
|
||||||
|
mapping.from(hydra.LeftButton1).to(standard.A);
|
||||||
|
mapping.from(hydra.LeftButton2).to(standard.B);
|
||||||
|
mapping.from(hydra.LeftButton3).to(standard.X);
|
||||||
|
NewControllers.enableMapping("Default");
|
||||||
|
print("-----------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
Object.keys(Controller.Standard).forEach(function (input) {
|
Object.keys(Controller.Standard).forEach(function (input) {
|
||||||
print("Controller.Standard." + input + ":" + Controller.Standard[input]);
|
print("Controller.Standard." + input + ":" + Controller.Standard[input]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -118,8 +118,16 @@ CameraManager = function() {
|
||||||
that.targetYaw = 0;
|
that.targetYaw = 0;
|
||||||
that.targetPitch = 0;
|
that.targetPitch = 0;
|
||||||
|
|
||||||
that.focalPoint = { x: 0, y: 0, z: 0 };
|
that.focalPoint = {
|
||||||
that.targetFocalPoint = { x: 0, y: 0, z: 0 };
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
that.targetFocalPoint = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
|
||||||
easing = false;
|
easing = false;
|
||||||
easingTime = 0;
|
easingTime = 0;
|
||||||
|
@ -127,13 +135,18 @@ CameraManager = function() {
|
||||||
|
|
||||||
that.previousCameraMode = null;
|
that.previousCameraMode = null;
|
||||||
|
|
||||||
that.lastMousePosition = { x: 0, y: 0 };
|
that.lastMousePosition = {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
};
|
||||||
|
|
||||||
that.enable = function() {
|
that.enable = function() {
|
||||||
if (Camera.mode == "independent" || that.enabled) return;
|
if (Camera.mode == "independent" || that.enabled) return;
|
||||||
|
|
||||||
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
||||||
Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] });
|
Controller.captureKeyEvents({
|
||||||
|
text: CAPTURED_KEYS[i]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
that.enabled = true;
|
that.enabled = true;
|
||||||
|
@ -169,7 +182,9 @@ CameraManager = function() {
|
||||||
if (!that.enabled) return;
|
if (!that.enabled) return;
|
||||||
|
|
||||||
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
||||||
Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] });
|
Controller.releaseKeyEvents({
|
||||||
|
text: CAPTURED_KEYS[i]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
that.enabled = false;
|
that.enabled = false;
|
||||||
|
@ -335,19 +350,27 @@ CameraManager = function() {
|
||||||
|
|
||||||
var hasDragged = false;
|
var hasDragged = false;
|
||||||
that.mousePressEvent = function(event) {
|
that.mousePressEvent = function(event) {
|
||||||
|
|
||||||
if (cameraTool.mousePressEvent(event)) {
|
if (cameraTool.mousePressEvent(event)) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!that.enabled) return;
|
if (!that.enabled) return;
|
||||||
|
|
||||||
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
||||||
|
|
||||||
that.mode = MODE_ORBIT;
|
that.mode = MODE_ORBIT;
|
||||||
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
||||||
|
|
||||||
|
|
||||||
that.mode = MODE_PAN;
|
that.mode = MODE_PAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (that.mode != MODE_INACTIVE) {
|
if (that.mode !== MODE_INACTIVE) {
|
||||||
|
|
||||||
|
|
||||||
hasDragged = false;
|
hasDragged = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -357,10 +380,12 @@ CameraManager = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
that.mouseReleaseEvent = function(event) {
|
that.mouseReleaseEvent = function(event) {
|
||||||
|
|
||||||
if (!that.enabled) return;
|
if (!that.enabled) return;
|
||||||
|
|
||||||
Window.setCursorVisible(true);
|
|
||||||
that.mode = MODE_INACTIVE;
|
that.mode = MODE_INACTIVE;
|
||||||
|
Window.setCursorVisible(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
that.keyPressEvent = function(event) {
|
that.keyPressEvent = function(event) {
|
||||||
|
@ -396,15 +421,31 @@ CameraManager = function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var yRot = Quat.angleAxis(that.yaw, { x: 0, y: 1, z: 0 });
|
var yRot = Quat.angleAxis(that.yaw, {
|
||||||
var xRot = Quat.angleAxis(that.pitch, { x: 1, y: 0, z: 0 });
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
|
var xRot = Quat.angleAxis(that.pitch, {
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
var q = Quat.multiply(yRot, xRot);
|
var q = Quat.multiply(yRot, xRot);
|
||||||
|
|
||||||
var pos = Vec3.multiply(Quat.getFront(q), that.zoomDistance);
|
var pos = Vec3.multiply(Quat.getFront(q), that.zoomDistance);
|
||||||
Camera.setPosition(Vec3.sum(that.focalPoint, pos));
|
Camera.setPosition(Vec3.sum(that.focalPoint, pos));
|
||||||
|
|
||||||
yRot = Quat.angleAxis(that.yaw - 180, { x: 0, y: 1, z: 0 });
|
yRot = Quat.angleAxis(that.yaw - 180, {
|
||||||
xRot = Quat.angleAxis(-that.pitch, { x: 1, y: 0, z: 0 });
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
|
xRot = Quat.angleAxis(-that.pitch, {
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
q = Quat.multiply(yRot, xRot);
|
q = Quat.multiply(yRot, xRot);
|
||||||
|
|
||||||
if (easing) {
|
if (easing) {
|
||||||
|
@ -483,7 +524,7 @@ CameraManager = function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Controller.keyReleaseEvent.connect(function (event) {
|
Controller.keyReleaseEvent.connect(function(event) {
|
||||||
if (event.text == "ESC" && that.enabled) {
|
if (event.text == "ESC" && that.enabled) {
|
||||||
Camera.mode = lastAvatarCameraMode;
|
Camera.mode = lastAvatarCameraMode;
|
||||||
cameraManager.disable(true);
|
cameraManager.disable(true);
|
||||||
|
@ -503,9 +544,21 @@ CameraManager = function() {
|
||||||
CameraTool = function(cameraManager) {
|
CameraTool = function(cameraManager) {
|
||||||
var that = {};
|
var that = {};
|
||||||
|
|
||||||
var RED = { red: 191, green: 78, blue: 38 };
|
var RED = {
|
||||||
var GREEN = { red: 26, green: 193, blue: 105 };
|
red: 191,
|
||||||
var BLUE = { red: 0, green: 131, blue: 204 };
|
green: 78,
|
||||||
|
blue: 38
|
||||||
|
};
|
||||||
|
var GREEN = {
|
||||||
|
red: 26,
|
||||||
|
green: 193,
|
||||||
|
blue: 105
|
||||||
|
};
|
||||||
|
var BLUE = {
|
||||||
|
red: 0,
|
||||||
|
green: 131,
|
||||||
|
blue: 204
|
||||||
|
};
|
||||||
|
|
||||||
var BORDER_WIDTH = 1;
|
var BORDER_WIDTH = 1;
|
||||||
|
|
||||||
|
@ -536,7 +589,11 @@ CameraTool = function(cameraManager) {
|
||||||
height: UI_HEIGHT + BORDER_WIDTH * 2,
|
height: UI_HEIGHT + BORDER_WIDTH * 2,
|
||||||
alpha: 0,
|
alpha: 0,
|
||||||
text: "",
|
text: "",
|
||||||
backgroundColor: { red: 101, green: 101, blue: 101 },
|
backgroundColor: {
|
||||||
|
red: 101,
|
||||||
|
green: 101,
|
||||||
|
blue: 101
|
||||||
|
},
|
||||||
backgroundAlpha: 1.0,
|
backgroundAlpha: 1.0,
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
@ -548,7 +605,11 @@ CameraTool = function(cameraManager) {
|
||||||
height: UI_HEIGHT,
|
height: UI_HEIGHT,
|
||||||
alpha: 0,
|
alpha: 0,
|
||||||
text: "",
|
text: "",
|
||||||
backgroundColor: { red: 51, green: 51, blue: 51 },
|
backgroundColor: {
|
||||||
|
red: 51,
|
||||||
|
green: 51,
|
||||||
|
blue: 51
|
||||||
|
},
|
||||||
backgroundAlpha: 1.0,
|
backgroundAlpha: 1.0,
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
@ -556,7 +617,11 @@ CameraTool = function(cameraManager) {
|
||||||
var defaultCubeProps = {
|
var defaultCubeProps = {
|
||||||
size: ORIENTATION_OVERLAY_CUBE_SIZE,
|
size: ORIENTATION_OVERLAY_CUBE_SIZE,
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
color: { red: 255, green: 0, blue: 0 },
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
},
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
drawOnHUD: true,
|
drawOnHUD: true,
|
||||||
|
@ -564,10 +629,26 @@ CameraTool = function(cameraManager) {
|
||||||
var defaultLineProps = {
|
var defaultLineProps = {
|
||||||
lineWidth: 1.5,
|
lineWidth: 1.5,
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
position: { x: 0, y: 0, z: 0 },
|
position: {
|
||||||
start: { x: 0, y: 0, z: 0 },
|
x: 0,
|
||||||
end: { x: 0, y: 0, z: 0 },
|
y: 0,
|
||||||
color: { red: 255, green: 0, blue: 0 },
|
z: 0
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
},
|
||||||
visible: false,
|
visible: false,
|
||||||
drawOnHUD: true,
|
drawOnHUD: true,
|
||||||
};
|
};
|
||||||
|
@ -582,30 +663,66 @@ CameraTool = function(cameraManager) {
|
||||||
|
|
||||||
var OOHS = ORIENTATION_OVERLAY_HALF_SIZE;
|
var OOHS = ORIENTATION_OVERLAY_HALF_SIZE;
|
||||||
var cubeX = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, {
|
var cubeX = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, {
|
||||||
position: { x: -OOHS, y: OOHS, z: OOHS },
|
position: {
|
||||||
|
x: -OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
color: RED,
|
color: RED,
|
||||||
}));
|
}));
|
||||||
var cubeY = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, {
|
var cubeY = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, {
|
||||||
position: { x: OOHS, y: -OOHS, z: OOHS },
|
position: {
|
||||||
|
x: OOHS,
|
||||||
|
y: -OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
color: GREEN,
|
color: GREEN,
|
||||||
}));
|
}));
|
||||||
var cubeZ = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, {
|
var cubeZ = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, {
|
||||||
position: { x: OOHS, y: OOHS, z: -OOHS },
|
position: {
|
||||||
|
x: OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: -OOHS
|
||||||
|
},
|
||||||
color: BLUE,
|
color: BLUE,
|
||||||
}));
|
}));
|
||||||
orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, {
|
orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, {
|
||||||
start: { x: -OOHS, y: OOHS, z: OOHS },
|
start: {
|
||||||
end: { x: OOHS, y: OOHS, z: OOHS },
|
x: -OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
x: OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
color: RED,
|
color: RED,
|
||||||
}));
|
}));
|
||||||
orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, {
|
orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, {
|
||||||
start: { x: OOHS, y: -OOHS, z: OOHS },
|
start: {
|
||||||
end: { x: OOHS, y: OOHS, z: OOHS },
|
x: OOHS,
|
||||||
|
y: -OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
x: OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
color: GREEN,
|
color: GREEN,
|
||||||
}));
|
}));
|
||||||
orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, {
|
orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, {
|
||||||
start: { x: OOHS, y: OOHS, z: -OOHS },
|
start: {
|
||||||
end: { x: OOHS, y: OOHS, z: OOHS },
|
x: OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: -OOHS
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
x: OOHS,
|
||||||
|
y: OOHS,
|
||||||
|
z: OOHS
|
||||||
|
},
|
||||||
color: BLUE,
|
color: BLUE,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -645,7 +762,10 @@ CameraTool = function(cameraManager) {
|
||||||
}
|
}
|
||||||
|
|
||||||
that.mousePressEvent = function(event) {
|
that.mousePressEvent = function(event) {
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
|
|
||||||
if (clickedOverlay == cubeX) {
|
if (clickedOverlay == cubeX) {
|
||||||
targetPitch = 0;
|
targetPitch = 0;
|
||||||
|
@ -666,9 +786,15 @@ CameraTool = function(cameraManager) {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setVisible = function(visible) {
|
that.setVisible = function(visible) {
|
||||||
orientationOverlay.setProperties({ visible: visible });
|
orientationOverlay.setProperties({
|
||||||
Overlays.editOverlay(background, { visible: visible });
|
visible: visible
|
||||||
Overlays.editOverlay(backgroundBorder, { visible: visible });
|
});
|
||||||
|
Overlays.editOverlay(background, {
|
||||||
|
visible: visible
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(backgroundBorder, {
|
||||||
|
visible: visible
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setVisible(false);
|
that.setVisible(false);
|
||||||
|
|
|
@ -16,24 +16,38 @@
|
||||||
{
|
{
|
||||||
"jointName": "RightHand",
|
"jointName": "RightHand",
|
||||||
"positionVar": "rightHandPosition",
|
"positionVar": "rightHandPosition",
|
||||||
"rotationVar": "rightHandRotation"
|
"rotationVar": "rightHandRotation",
|
||||||
|
"typeVar": "rightHandType"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "LeftHand",
|
"jointName": "LeftHand",
|
||||||
"positionVar": "leftHandPosition",
|
"positionVar": "leftHandPosition",
|
||||||
"rotationVar": "leftHandRotation"
|
"rotationVar": "leftHandRotation",
|
||||||
|
"typeVar": "leftHandType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jointName": "RightFoot",
|
||||||
|
"positionVar": "rightFootPosition",
|
||||||
|
"rotationVar": "rightFootRotation",
|
||||||
|
"typeVar": "rightFootType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jointName": "LeftFoot",
|
||||||
|
"positionVar": "leftFootPosition",
|
||||||
|
"rotationVar": "leftFootRotation",
|
||||||
|
"typeVar": "leftFootType"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "Neck",
|
"jointName": "Neck",
|
||||||
"positionVar": "neckPosition",
|
"positionVar": "neckPosition",
|
||||||
"rotationVar": "neckRotation",
|
"rotationVar": "neckRotation",
|
||||||
"typeVar": "headAndNeckType"
|
"typeVar": "neckType"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "Head",
|
"jointName": "Head",
|
||||||
"positionVar": "headPosition",
|
"positionVar": "headPosition",
|
||||||
"rotationVar": "headRotation",
|
"rotationVar": "headRotation",
|
||||||
"typeVar": "headAndNeckType"
|
"typeVar": "headType"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -51,7 +65,7 @@
|
||||||
"id": "spineLean",
|
"id": "spineLean",
|
||||||
"type": "manipulator",
|
"type": "manipulator",
|
||||||
"data": {
|
"data": {
|
||||||
"alpha": 1.0,
|
"alpha": 0.0,
|
||||||
"joints": [
|
"joints": [
|
||||||
{ "var": "lean", "jointName": "Spine" }
|
{ "var": "lean", "jointName": "Spine" }
|
||||||
]
|
]
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
#include "Stars.h"
|
#include "Stars.h"
|
||||||
#include "ui/AddressBarDialog.h"
|
#include "ui/AddressBarDialog.h"
|
||||||
#include "ui/AvatarInputs.h"
|
#include "ui/AvatarInputs.h"
|
||||||
|
#include "ui/AssetUploadDialogFactory.h"
|
||||||
#include "ui/DataWebDialog.h"
|
#include "ui/DataWebDialog.h"
|
||||||
#include "ui/DialogsManager.h"
|
#include "ui/DialogsManager.h"
|
||||||
#include "ui/LoginDialog.h"
|
#include "ui/LoginDialog.h"
|
||||||
|
@ -159,6 +160,7 @@ static const QString SVO_JSON_EXTENSION = ".svo.json";
|
||||||
static const QString JS_EXTENSION = ".js";
|
static const QString JS_EXTENSION = ".js";
|
||||||
static const QString FST_EXTENSION = ".fst";
|
static const QString FST_EXTENSION = ".fst";
|
||||||
static const QString FBX_EXTENSION = ".fbx";
|
static const QString FBX_EXTENSION = ".fbx";
|
||||||
|
static const QString OBJ_EXTENSION = ".obj";
|
||||||
|
|
||||||
static const int MIRROR_VIEW_TOP_PADDING = 5;
|
static const int MIRROR_VIEW_TOP_PADDING = 5;
|
||||||
static const int MIRROR_VIEW_LEFT_PADDING = 10;
|
static const int MIRROR_VIEW_LEFT_PADDING = 10;
|
||||||
|
@ -179,9 +181,6 @@ static const unsigned int THROTTLED_SIM_FRAMERATE = 15;
|
||||||
static const int TARGET_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / TARGET_SIM_FRAMERATE;
|
static const int TARGET_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / TARGET_SIM_FRAMERATE;
|
||||||
static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
|
static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
|
||||||
|
|
||||||
const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml";
|
|
||||||
const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion";
|
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
#else
|
#else
|
||||||
|
@ -197,8 +196,7 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi
|
||||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||||
{ JS_EXTENSION, &Application::askToLoadScript },
|
{ JS_EXTENSION, &Application::askToLoadScript },
|
||||||
{ FST_EXTENSION, &Application::askToSetAvatarUrl },
|
{ FST_EXTENSION, &Application::askToSetAvatarUrl }
|
||||||
{ FBX_EXTENSION, &Application::askToUploadAsset }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -1892,16 +1890,6 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||||
computePickRay(mappedEvent.x(), mappedEvent.y()));
|
computePickRay(mappedEvent.x(), mappedEvent.y()));
|
||||||
sendEvent(this, &actionEvent);
|
sendEvent(this, &actionEvent);
|
||||||
|
|
||||||
} else if (event->button() == Qt::RightButton) {
|
|
||||||
// "right click" on controllers to toggle the overlay
|
|
||||||
if (deviceID > 0) {
|
|
||||||
_overlayConductor.setEnabled(!_overlayConductor.getEnabled());
|
|
||||||
}
|
|
||||||
} else if (event->button() == Qt::MiddleButton) {
|
|
||||||
// mouse middle click to toggle the overlay
|
|
||||||
if (deviceID == 0) {
|
|
||||||
_overlayConductor.setEnabled(!_overlayConductor.getEnabled());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2023,21 +2011,14 @@ void Application::dropEvent(QDropEvent *event) {
|
||||||
const QMimeData* mimeData = event->mimeData();
|
const QMimeData* mimeData = event->mimeData();
|
||||||
for (auto& url : mimeData->urls()) {
|
for (auto& url : mimeData->urls()) {
|
||||||
QString urlString = url.toString();
|
QString urlString = url.toString();
|
||||||
if (canAcceptURL(urlString) && acceptURL(urlString)) {
|
if (acceptURL(urlString, true)) {
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::dragEnterEvent(QDragEnterEvent* event) {
|
void Application::dragEnterEvent(QDragEnterEvent* event) {
|
||||||
const QMimeData* mimeData = event->mimeData();
|
|
||||||
for (auto& url : mimeData->urls()) {
|
|
||||||
auto urlString = url.toString();
|
|
||||||
if (canAcceptURL(urlString)) {
|
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::acceptSnapshot(const QString& urlString) {
|
bool Application::acceptSnapshot(const QString& urlString) {
|
||||||
|
@ -2770,6 +2751,8 @@ void Application::update(float deltaTime) {
|
||||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||||
updateDialogs(deltaTime); // update various stats dialogs if present
|
updateDialogs(deltaTime); // update various stats dialogs if present
|
||||||
|
|
||||||
|
_avatarUpdate->synchronousProcess();
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("physics");
|
PerformanceTimer perfTimer("physics");
|
||||||
myAvatar->relayDriveKeysToCharacterController();
|
myAvatar->relayDriveKeysToCharacterController();
|
||||||
|
@ -2831,8 +2814,6 @@ void Application::update(float deltaTime) {
|
||||||
_overlays.update(deltaTime);
|
_overlays.update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
_avatarUpdate->synchronousProcess();
|
|
||||||
|
|
||||||
// Update _viewFrustum with latest camera and view frustum data...
|
// Update _viewFrustum with latest camera and view frustum data...
|
||||||
// NOTE: we get this from the view frustum, to make it simpler, since the
|
// NOTE: we get this from the view frustum, to make it simpler, since the
|
||||||
// loadViewFrumstum() method will get the correct details from the camera
|
// loadViewFrumstum() method will get the correct details from the camera
|
||||||
|
@ -3973,13 +3954,14 @@ bool Application::canAcceptURL(const QString& urlString) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::acceptURL(const QString& urlString) {
|
bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
|
||||||
if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||||
// this is a hifi URL - have the AddressManager handle it
|
// this is a hifi URL - have the AddressManager handle it
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
||||||
Qt::AutoConnection, Q_ARG(const QString&, urlString));
|
Qt::AutoConnection, Q_ARG(const QString&, urlString));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
QUrl url(urlString);
|
QUrl url(urlString);
|
||||||
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
QHashIterator<QString, AcceptURLMethod> i(_acceptedExtensions);
|
||||||
QString lowerPath = url.path().toLower();
|
QString lowerPath = url.path().toLower();
|
||||||
|
@ -3987,12 +3969,11 @@ bool Application::acceptURL(const QString& urlString) {
|
||||||
i.next();
|
i.next();
|
||||||
if (lowerPath.endsWith(i.key())) {
|
if (lowerPath.endsWith(i.key())) {
|
||||||
AcceptURLMethod method = i.value();
|
AcceptURLMethod method = i.value();
|
||||||
(this->*method)(urlString);
|
return (this->*method)(urlString);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return defaultUpload && askToUploadAsset(urlString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setSessionUUID(const QUuid& sessionUUID) {
|
void Application::setSessionUUID(const QUuid& sessionUUID) {
|
||||||
|
@ -4076,8 +4057,36 @@ bool Application::askToUploadAsset(const QString& filename) {
|
||||||
|
|
||||||
QUrl url { filename };
|
QUrl url { filename };
|
||||||
if (auto upload = DependencyManager::get<AssetClient>()->createUpload(url.toLocalFile())) {
|
if (auto upload = DependencyManager::get<AssetClient>()->createUpload(url.toLocalFile())) {
|
||||||
|
|
||||||
|
QMessageBox messageBox;
|
||||||
|
messageBox.setWindowTitle("Asset upload");
|
||||||
|
messageBox.setText("You are about to upload the following file to the asset server:\n" +
|
||||||
|
url.toDisplayString());
|
||||||
|
messageBox.setInformativeText("Do you want to continue?");
|
||||||
|
messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||||
|
messageBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
|
||||||
|
// Option to drop model in world for models
|
||||||
|
if (filename.endsWith(FBX_EXTENSION) || filename.endsWith(OBJ_EXTENSION)) {
|
||||||
|
auto checkBox = new QCheckBox(&messageBox);
|
||||||
|
checkBox->setText("Add to scene");
|
||||||
|
messageBox.setCheckBox(checkBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messageBox.exec() != QMessageBox::Ok) {
|
||||||
|
upload->deleteLater();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// connect to the finished signal so we know when the AssetUpload is done
|
// connect to the finished signal so we know when the AssetUpload is done
|
||||||
QObject::connect(upload, &AssetUpload::finished, this, &Application::assetUploadFinished);
|
if (messageBox.checkBox() && (messageBox.checkBox()->checkState() == Qt::Checked)) {
|
||||||
|
// Custom behavior for models
|
||||||
|
QObject::connect(upload, &AssetUpload::finished, this, &Application::modelUploadFinished);
|
||||||
|
} else {
|
||||||
|
QObject::connect(upload, &AssetUpload::finished,
|
||||||
|
&AssetUploadDialogFactory::getInstance(),
|
||||||
|
&AssetUploadDialogFactory::handleUploadFinished);
|
||||||
|
}
|
||||||
|
|
||||||
// start the upload now
|
// start the upload now
|
||||||
upload->start();
|
upload->start();
|
||||||
|
@ -4089,47 +4098,26 @@ bool Application::askToUploadAsset(const QString& filename) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::assetUploadFinished(AssetUpload* upload, const QString& hash) {
|
void Application::modelUploadFinished(AssetUpload* upload, const QString& hash) {
|
||||||
if (upload->getError() != AssetUpload::NoError) {
|
|
||||||
// figure out the right error message for the message box
|
|
||||||
QString additionalError;
|
|
||||||
|
|
||||||
switch (upload->getError()) {
|
|
||||||
case AssetUpload::PermissionDenied:
|
|
||||||
additionalError = "You do not have permission to upload content to this asset-server.";
|
|
||||||
break;
|
|
||||||
case AssetUpload::TooLarge:
|
|
||||||
additionalError = "The uploaded content was too large and could not be stored in the asset-server.";
|
|
||||||
break;
|
|
||||||
case AssetUpload::FileOpenError:
|
|
||||||
additionalError = "The file could not be opened. Please check your permissions and try again.";
|
|
||||||
break;
|
|
||||||
case AssetUpload::NetworkError:
|
|
||||||
additionalError = "The file could not be opened. Please check your network connectivity.";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// not handled, do not show a message box
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// display a message box with the error
|
|
||||||
auto filename = QFileInfo(upload->getFilename()).fileName();
|
auto filename = QFileInfo(upload->getFilename()).fileName();
|
||||||
QString errorMessage = QString("Failed to upload %1.\n\n%2").arg(filename, additionalError);
|
|
||||||
QMessageBox::warning(_window, "Failed Upload", errorMessage);
|
if ((upload->getError() == AssetUpload::NoError) &&
|
||||||
}
|
(filename.endsWith(FBX_EXTENSION) || filename.endsWith(OBJ_EXTENSION))) {
|
||||||
|
|
||||||
auto entities = DependencyManager::get<EntityScriptingInterface>();
|
auto entities = DependencyManager::get<EntityScriptingInterface>();
|
||||||
auto myAvatar = getMyAvatar();
|
|
||||||
|
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
properties.setType(EntityTypes::Model);
|
properties.setType(EntityTypes::Model);
|
||||||
properties.setModelURL(QString("%1:%2.%3").arg(ATP_SCHEME).arg(hash).arg(upload->getExtension()));
|
properties.setModelURL(QString("%1:%2.%3").arg(URL_SCHEME_ATP).arg(hash).arg(upload->getExtension()));
|
||||||
properties.setPosition(myAvatar->getPosition() + myAvatar->getOrientation() * Vectors::FRONT * 2.0f);
|
properties.setPosition(_myCamera.getPosition() + _myCamera.getOrientation() * Vectors::FRONT * 2.0f);
|
||||||
properties.setName(QUrl(upload->getFilename()).fileName());
|
properties.setName(QUrl(upload->getFilename()).fileName());
|
||||||
|
|
||||||
entities->addEntity(properties);
|
entities->addEntity(properties);
|
||||||
|
|
||||||
upload->deleteLater();
|
upload->deleteLater();
|
||||||
|
} else {
|
||||||
|
AssetUploadDialogFactory::getInstance().handleUploadFinished(upload, hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
|
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
|
||||||
|
|
|
@ -211,7 +211,7 @@ public:
|
||||||
void setScriptsLocation(const QString& scriptsLocation);
|
void setScriptsLocation(const QString& scriptsLocation);
|
||||||
|
|
||||||
bool canAcceptURL(const QString& url);
|
bool canAcceptURL(const QString& url);
|
||||||
bool acceptURL(const QString& url);
|
bool acceptURL(const QString& url, bool defaultUpload = false);
|
||||||
|
|
||||||
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
|
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
|
||||||
int getMaxOctreePacketsPerSecond();
|
int getMaxOctreePacketsPerSecond();
|
||||||
|
@ -329,7 +329,7 @@ private slots:
|
||||||
bool askToSetAvatarUrl(const QString& url);
|
bool askToSetAvatarUrl(const QString& url);
|
||||||
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
||||||
bool askToUploadAsset(const QString& asset);
|
bool askToUploadAsset(const QString& asset);
|
||||||
void assetUploadFinished(AssetUpload* upload, const QString& hash);
|
void modelUploadFinished(AssetUpload* upload, const QString& hash);
|
||||||
|
|
||||||
void setSessionUUID(const QUuid& sessionUUID);
|
void setSessionUUID(const QUuid& sessionUUID);
|
||||||
void domainChanged(const QString& domainHostname);
|
void domainChanged(const QString& domainHostname);
|
||||||
|
|
|
@ -152,7 +152,7 @@ void MyAvatar::reset() {
|
||||||
setEnableRigAnimations(true);
|
setEnableRigAnimations(true);
|
||||||
|
|
||||||
// Reset dynamic state.
|
// Reset dynamic state.
|
||||||
_wasPushing = _isPushing = _isBraking = _billboardValid = _goToPending = _straighteningLean = false;
|
_wasPushing = _isPushing = _isBraking = _billboardValid = _straighteningLean = false;
|
||||||
_skeletonModel.reset();
|
_skeletonModel.reset();
|
||||||
getHead()->reset();
|
getHead()->reset();
|
||||||
_targetVelocity = glm::vec3(0.0f);
|
_targetVelocity = glm::vec3(0.0f);
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <HandData.h>
|
#include <HandData.h>
|
||||||
#include <HFBackEvent.h>
|
#include <HFBackEvent.h>
|
||||||
|
|
||||||
|
#include <controllers/NewControllerScriptingInterface.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "devices/MotionTracker.h"
|
#include "devices/MotionTracker.h"
|
||||||
#include "ControllerScriptingInterface.h"
|
#include "ControllerScriptingInterface.h"
|
||||||
|
@ -31,6 +33,11 @@ ControllerScriptingInterface::ControllerScriptingInterface() :
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ControllerScriptingInterface::~ControllerScriptingInterface() {
|
||||||
|
delete _newControllerScriptingInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int actionMetaTypeId = qRegisterMetaType<UserInputMapper::Action>();
|
static int actionMetaTypeId = qRegisterMetaType<UserInputMapper::Action>();
|
||||||
static int inputChannelMetaTypeId = qRegisterMetaType<UserInputMapper::InputChannel>();
|
static int inputChannelMetaTypeId = qRegisterMetaType<UserInputMapper::InputChannel>();
|
||||||
static int inputMetaTypeId = qRegisterMetaType<UserInputMapper::Input>();
|
static int inputMetaTypeId = qRegisterMetaType<UserInputMapper::Input>();
|
||||||
|
@ -121,6 +128,11 @@ void ControllerScriptingInterface::registerControllerTypes(ScriptEngine* engine)
|
||||||
qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue);
|
qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue);
|
||||||
|
|
||||||
wireUpControllers(engine);
|
wireUpControllers(engine);
|
||||||
|
|
||||||
|
// hack in the new controller scripting interface...
|
||||||
|
_newControllerScriptingInterface = new controller::NewControllerScriptingInterface();
|
||||||
|
engine->registerGlobalObject("NewControllers", _newControllerScriptingInterface);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
|
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
#include <AbstractControllerScriptingInterface.h>
|
#include <AbstractControllerScriptingInterface.h>
|
||||||
class PalmData;
|
class PalmData;
|
||||||
|
namespace controller {
|
||||||
|
class NewControllerScriptingInterface;
|
||||||
|
}
|
||||||
|
|
||||||
class InputController : public AbstractInputController {
|
class InputController : public AbstractInputController {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -55,6 +58,7 @@ class ControllerScriptingInterface : public AbstractControllerScriptingInterface
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ControllerScriptingInterface();
|
ControllerScriptingInterface();
|
||||||
|
~ControllerScriptingInterface();
|
||||||
|
|
||||||
virtual void registerControllerTypes(ScriptEngine* engine);
|
virtual void registerControllerTypes(ScriptEngine* engine);
|
||||||
|
|
||||||
|
@ -169,6 +173,7 @@ private:
|
||||||
|
|
||||||
void wireUpControllers(ScriptEngine* engine);
|
void wireUpControllers(ScriptEngine* engine);
|
||||||
|
|
||||||
|
controller::NewControllerScriptingInterface* _newControllerScriptingInterface = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip
|
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip
|
||||||
|
|
|
@ -11,11 +11,6 @@
|
||||||
|
|
||||||
#include "AssetUploadDialogFactory.h"
|
#include "AssetUploadDialogFactory.h"
|
||||||
|
|
||||||
#include <AssetClient.h>
|
|
||||||
#include <AssetUpload.h>
|
|
||||||
#include <AssetUtils.h>
|
|
||||||
#include <NodeList.h>
|
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtWidgets/QDialogButtonBox>
|
#include <QtWidgets/QDialogButtonBox>
|
||||||
#include <QtWidgets/QFileDialog>
|
#include <QtWidgets/QFileDialog>
|
||||||
|
@ -24,6 +19,12 @@
|
||||||
#include <QtWidgets/QLineEdit>
|
#include <QtWidgets/QLineEdit>
|
||||||
#include <QtWidgets/QVBoxLayout>
|
#include <QtWidgets/QVBoxLayout>
|
||||||
|
|
||||||
|
#include <AssetClient.h>
|
||||||
|
#include <AssetUpload.h>
|
||||||
|
#include <AssetUtils.h>
|
||||||
|
#include <NodeList.h>
|
||||||
|
#include <ResourceManager.h>
|
||||||
|
|
||||||
AssetUploadDialogFactory& AssetUploadDialogFactory::getInstance() {
|
AssetUploadDialogFactory& AssetUploadDialogFactory::getInstance() {
|
||||||
static AssetUploadDialogFactory staticInstance;
|
static AssetUploadDialogFactory staticInstance;
|
||||||
return staticInstance;
|
return staticInstance;
|
||||||
|
@ -85,7 +86,7 @@ void AssetUploadDialogFactory::handleUploadFinished(AssetUpload* upload, const Q
|
||||||
// setup the line edit to hold the copiable text
|
// setup the line edit to hold the copiable text
|
||||||
QLineEdit* lineEdit = new QLineEdit;
|
QLineEdit* lineEdit = new QLineEdit;
|
||||||
|
|
||||||
QString atpURL = QString("%1:%2.%3").arg(ATP_SCHEME).arg(hash).arg(upload->getExtension());
|
QString atpURL = QString("%1:%2.%3").arg(URL_SCHEME_ATP).arg(hash).arg(upload->getExtension());
|
||||||
|
|
||||||
// set the ATP URL as the text value so it's copiable
|
// set the ATP URL as the text value so it's copiable
|
||||||
lineEdit->insert(atpURL);
|
lineEdit->insert(atpURL);
|
||||||
|
|
|
@ -30,7 +30,6 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void showDialog();
|
void showDialog();
|
||||||
private slots:
|
|
||||||
void handleUploadFinished(AssetUpload* upload, const QString& hash);
|
void handleUploadFinished(AssetUpload* upload, const QString& hash);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -95,14 +95,20 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IKTarget target;
|
IKTarget target;
|
||||||
|
target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition));
|
||||||
|
if (target.getType() != IKTarget::Type::Unknown) {
|
||||||
AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
|
AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
|
||||||
target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans);
|
glm::quat rotation = animVars.lookup(targetVar.rotationVar, defaultPose.rot);
|
||||||
target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot);
|
glm::vec3 translation = animVars.lookup(targetVar.positionVar, defaultPose.trans);
|
||||||
target.setType(animVars.lookup(targetVar.typeVar, QString("")));
|
if (target.getType() == IKTarget::Type::HipsRelativeRotationAndPosition) {
|
||||||
target.index = targetVar.jointIndex;
|
translation += _hipsOffset;
|
||||||
|
}
|
||||||
|
target.setPose(rotation, translation);
|
||||||
|
target.setIndex(targetVar.jointIndex);
|
||||||
targets.push_back(target);
|
targets.push_back(target);
|
||||||
if (target.index > _maxTargetIndex) {
|
if (targetVar.jointIndex > _maxTargetIndex) {
|
||||||
_maxTargetIndex = target.index;
|
_maxTargetIndex = targetVar.jointIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,37 +147,44 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
do {
|
do {
|
||||||
int lowestMovedIndex = _relativePoses.size();
|
int lowestMovedIndex = _relativePoses.size();
|
||||||
for (auto& target: targets) {
|
for (auto& target: targets) {
|
||||||
if (target.type == IKTarget::Type::RotationOnly) {
|
IKTarget::Type targetType = target.getType();
|
||||||
|
if (targetType == IKTarget::Type::RotationOnly) {
|
||||||
// the final rotation will be enforced after the iterations
|
// the final rotation will be enforced after the iterations
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AnimPose targetPose = target.pose;
|
|
||||||
|
|
||||||
// cache tip absolute transform
|
// cache tip absolute transform
|
||||||
int tipIndex = target.index;
|
int tipIndex = target.getIndex();
|
||||||
|
int pivotIndex = _skeleton->getParentIndex(tipIndex);
|
||||||
|
if (pivotIndex == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int pivotsParentIndex = _skeleton->getParentIndex(pivotIndex);
|
||||||
|
if (pivotsParentIndex == -1) {
|
||||||
|
// TODO?: handle case where tip's parent is root?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 tipPosition = absolutePoses[tipIndex].trans;
|
glm::vec3 tipPosition = absolutePoses[tipIndex].trans;
|
||||||
glm::quat tipRotation = absolutePoses[tipIndex].rot;
|
glm::quat tipRotation = absolutePoses[tipIndex].rot;
|
||||||
|
|
||||||
// cache tip's parent's absolute rotation so we can recompute the tip's parent-relative
|
// cache tip's parent's absolute rotation so we can recompute the tip's parent-relative
|
||||||
// as we proceed walking down the joint chain
|
// as we proceed walking down the joint chain
|
||||||
int pivotIndex = _skeleton->getParentIndex(tipIndex);
|
glm::quat tipParentRotation = absolutePoses[pivotIndex].rot;
|
||||||
glm::quat tipParentRotation;
|
|
||||||
if (pivotIndex != -1) {
|
|
||||||
tipParentRotation = absolutePoses[pivotIndex].rot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// descend toward root, pivoting each joint to get tip closer to target
|
// descend toward root, pivoting each joint to get tip closer to target
|
||||||
int ancestorCount = 1;
|
while (pivotsParentIndex != -1) {
|
||||||
while (pivotIndex != -1) {
|
|
||||||
// compute the two lines that should be aligned
|
// compute the two lines that should be aligned
|
||||||
glm::vec3 jointPosition = absolutePoses[pivotIndex].trans;
|
glm::vec3 jointPosition = absolutePoses[pivotIndex].trans;
|
||||||
glm::vec3 leverArm = tipPosition - jointPosition;
|
glm::vec3 leverArm = tipPosition - jointPosition;
|
||||||
glm::vec3 targetLine = targetPose.trans - jointPosition;
|
|
||||||
|
|
||||||
|
glm::quat deltaRotation;
|
||||||
|
if (targetType == IKTarget::Type::RotationAndPosition ||
|
||||||
|
targetType == IKTarget::Type::HipsRelativeRotationAndPosition) {
|
||||||
// compute the swing that would get get tip closer
|
// compute the swing that would get get tip closer
|
||||||
|
glm::vec3 targetLine = target.getTranslation() - jointPosition;
|
||||||
glm::vec3 axis = glm::cross(leverArm, targetLine);
|
glm::vec3 axis = glm::cross(leverArm, targetLine);
|
||||||
float axisLength = glm::length(axis);
|
float axisLength = glm::length(axis);
|
||||||
glm::quat deltaRotation;
|
|
||||||
const float MIN_AXIS_LENGTH = 1.0e-4f;
|
const float MIN_AXIS_LENGTH = 1.0e-4f;
|
||||||
if (axisLength > MIN_AXIS_LENGTH) {
|
if (axisLength > MIN_AXIS_LENGTH) {
|
||||||
// compute deltaRotation for alignment (swings tip closer to target)
|
// compute deltaRotation for alignment (swings tip closer to target)
|
||||||
|
@ -182,46 +195,48 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
// still possible for the angle to be zero so we also check that to avoid unnecessary calculations.
|
// still possible for the angle to be zero so we also check that to avoid unnecessary calculations.
|
||||||
const float MIN_ADJUSTMENT_ANGLE = 1.0e-4f;
|
const float MIN_ADJUSTMENT_ANGLE = 1.0e-4f;
|
||||||
if (angle > MIN_ADJUSTMENT_ANGLE) {
|
if (angle > MIN_ADJUSTMENT_ANGLE) {
|
||||||
// reduce angle by a fraction (reduces IK swing contribution of this joint)
|
// reduce angle by a fraction (for stability)
|
||||||
angle /= (float)ancestorCount;
|
const float fraction = 0.5f;
|
||||||
|
angle *= fraction;
|
||||||
deltaRotation = glm::angleAxis(angle, axis);
|
deltaRotation = glm::angleAxis(angle, axis);
|
||||||
}
|
|
||||||
|
|
||||||
// The swing will re-orient the tip but there will tend to be be a non-zero delta between the tip's
|
// The swing will re-orient the tip but there will tend to be be a non-zero delta between the tip's
|
||||||
// new rotation and its target. We compute that delta here and rotate the tipJoint accordingly.
|
// new rotation and its target. This is the final parent-relative rotation that the tip joint have
|
||||||
glm::quat tipRelativeRotation = glm::inverse(deltaRotation * tipParentRotation) * targetPose.rot;
|
// make to achieve its target rotation.
|
||||||
|
glm::quat tipRelativeRotation = glm::inverse(deltaRotation * tipParentRotation) * target.getRotation();
|
||||||
|
|
||||||
// enforce tip's constraint
|
// enforce tip's constraint
|
||||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||||
if (constraint) {
|
if (constraint) {
|
||||||
bool constrained = constraint->apply(tipRelativeRotation);
|
bool constrained = constraint->apply(tipRelativeRotation);
|
||||||
if (constrained) {
|
if (constrained) {
|
||||||
// The tip's final parent-relative rotation violates its constraint
|
// The tip's final parent-relative rotation would violate its constraint
|
||||||
// so we try to twist this pivot to compensate.
|
// so we try to pre-twist this pivot to compensate.
|
||||||
glm::quat constrainedTipRotation = deltaRotation * tipParentRotation * tipRelativeRotation;
|
glm::quat constrainedTipRotation = deltaRotation * tipParentRotation * tipRelativeRotation;
|
||||||
glm::quat missingRotation = targetPose.rot * glm::inverse(constrainedTipRotation);
|
glm::quat missingRotation = target.getRotation() * glm::inverse(constrainedTipRotation);
|
||||||
glm::quat swingPart;
|
glm::quat swingPart;
|
||||||
glm::quat twistPart;
|
glm::quat twistPart;
|
||||||
glm::vec3 axis = glm::normalize(deltaRotation * leverArm);
|
glm::vec3 axis = glm::normalize(deltaRotation * leverArm);
|
||||||
swingTwistDecomposition(missingRotation, axis, swingPart, twistPart);
|
swingTwistDecomposition(missingRotation, axis, swingPart, twistPart);
|
||||||
deltaRotation = twistPart * deltaRotation;
|
float dotSign = copysignf(1.0f, twistPart.w);
|
||||||
}
|
deltaRotation = glm::normalize(glm::lerp(glm::quat(), dotSign * twistPart, fraction)) * deltaRotation;
|
||||||
// we update the tip rotation here to rotate it as close to its target orientation as possible
|
|
||||||
// before moving on to next pivot
|
|
||||||
tipRotation = tipParentRotation * tipRelativeRotation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++ancestorCount;
|
}
|
||||||
|
}
|
||||||
|
} else if (targetType == IKTarget::Type::HmdHead) {
|
||||||
|
// An HmdHead target slaves the orientation of the end-effector by distributing rotation
|
||||||
|
// deltas up the hierarchy. Its target position is enforced later by shifting the hips.
|
||||||
|
deltaRotation = target.getRotation() * glm::inverse(tipRotation);
|
||||||
|
float dotSign = copysignf(1.0f, deltaRotation.w);
|
||||||
|
const float ANGLE_DISTRIBUTION_FACTOR = 0.15f;
|
||||||
|
deltaRotation = glm::normalize(glm::lerp(glm::quat(), dotSign * deltaRotation, ANGLE_DISTRIBUTION_FACTOR));
|
||||||
|
}
|
||||||
|
|
||||||
int parentIndex = _skeleton->getParentIndex(pivotIndex);
|
|
||||||
if (parentIndex == -1) {
|
|
||||||
// TODO? apply constraints to root?
|
|
||||||
// TODO? harvest the root's transform as movement of entire skeleton?
|
|
||||||
} else {
|
|
||||||
// compute joint's new parent-relative rotation after swing
|
// compute joint's new parent-relative rotation after swing
|
||||||
// Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q
|
// Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q
|
||||||
glm::quat newRot = glm::normalize(glm::inverse(
|
glm::quat newRot = glm::normalize(glm::inverse(
|
||||||
absolutePoses[parentIndex].rot) *
|
absolutePoses[pivotsParentIndex].rot) *
|
||||||
deltaRotation *
|
deltaRotation *
|
||||||
absolutePoses[pivotIndex].rot);
|
absolutePoses[pivotIndex].rot);
|
||||||
|
|
||||||
|
@ -233,7 +248,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
// the constraint will modify the movement of the tip so we have to compute the modified
|
// the constraint will modify the movement of the tip so we have to compute the modified
|
||||||
// model-frame deltaRotation
|
// model-frame deltaRotation
|
||||||
// Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^
|
// Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^
|
||||||
deltaRotation = absolutePoses[parentIndex].rot *
|
deltaRotation = absolutePoses[pivotsParentIndex].rot *
|
||||||
newRot *
|
newRot *
|
||||||
glm::inverse(absolutePoses[pivotIndex].rot);
|
glm::inverse(absolutePoses[pivotIndex].rot);
|
||||||
}
|
}
|
||||||
|
@ -241,7 +256,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
|
|
||||||
// store the rotation change in the accumulator
|
// store the rotation change in the accumulator
|
||||||
_accumulators[pivotIndex].add(newRot);
|
_accumulators[pivotIndex].add(newRot);
|
||||||
}
|
|
||||||
// this joint has been changed so we check to see if it has the lowest index
|
// this joint has been changed so we check to see if it has the lowest index
|
||||||
if (pivotIndex < lowestMovedIndex) {
|
if (pivotIndex < lowestMovedIndex) {
|
||||||
lowestMovedIndex = pivotIndex;
|
lowestMovedIndex = pivotIndex;
|
||||||
|
@ -252,7 +267,8 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
tipRotation = glm::normalize(deltaRotation * tipRotation);
|
tipRotation = glm::normalize(deltaRotation * tipRotation);
|
||||||
tipParentRotation = glm::normalize(deltaRotation * tipParentRotation);
|
tipParentRotation = glm::normalize(deltaRotation * tipParentRotation);
|
||||||
|
|
||||||
pivotIndex = _skeleton->getParentIndex(pivotIndex);
|
pivotIndex = pivotsParentIndex;
|
||||||
|
pivotsParentIndex = _skeleton->getParentIndex(pivotIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++numLoops;
|
++numLoops;
|
||||||
|
@ -275,26 +291,15 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
}
|
}
|
||||||
} while (numLoops < MAX_IK_LOOPS);
|
} while (numLoops < MAX_IK_LOOPS);
|
||||||
|
|
||||||
/* KEEP: example code for measuring endeffector error of IK solution
|
|
||||||
for (uint32_t i = 0; i < targets.size(); ++i) {
|
|
||||||
auto& target = targets[i];
|
|
||||||
if (target.type == IKTarget::Type::RotationOnly) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
glm::vec3 tipPosition = absolutePoses[target.index].trans;
|
|
||||||
std::cout << i << " IK error = " << glm::distance(tipPosition, target.pose.trans) << std::endl;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// finally set the relative rotation of each tip to agree with absolute target rotation
|
// finally set the relative rotation of each tip to agree with absolute target rotation
|
||||||
for (auto& target: targets) {
|
for (auto& target: targets) {
|
||||||
int tipIndex = target.index;
|
int tipIndex = target.getIndex();
|
||||||
int parentIndex = _skeleton->getParentIndex(tipIndex);
|
int parentIndex = _skeleton->getParentIndex(tipIndex);
|
||||||
if (parentIndex != -1) {
|
if (parentIndex != -1) {
|
||||||
AnimPose targetPose = target.pose;
|
const glm::quat& targetRotation = target.getRotation();
|
||||||
// compute tip's new parent-relative rotation
|
// compute tip's new parent-relative rotation
|
||||||
// Q = Qp * q --> q' = Qp^ * Q
|
// Q = Qp * q --> q' = Qp^ * Q
|
||||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetPose.rot;
|
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetRotation;
|
||||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
RotationConstraint* constraint = getConstraint(tipIndex);
|
||||||
if (constraint) {
|
if (constraint) {
|
||||||
constraint->apply(newRelativeRotation);
|
constraint->apply(newRelativeRotation);
|
||||||
|
@ -303,7 +308,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
// to help this rotation target get met.
|
// to help this rotation target get met.
|
||||||
}
|
}
|
||||||
_relativePoses[tipIndex].rot = newRelativeRotation;
|
_relativePoses[tipIndex].rot = newRelativeRotation;
|
||||||
absolutePoses[tipIndex].rot = targetPose.rot;
|
absolutePoses[tipIndex].rot = targetRotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,7 +360,50 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
||||||
++constraintItr;
|
++constraintItr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// shift the hips according to the offset from the previous frame
|
||||||
|
float offsetLength = glm::length(_hipsOffset);
|
||||||
|
const float MIN_HIPS_OFFSET_LENGTH = 0.03f;
|
||||||
|
if (offsetLength > MIN_HIPS_OFFSET_LENGTH) {
|
||||||
|
// but only if offset is long enough
|
||||||
|
float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength);
|
||||||
|
_relativePoses[0].trans = underPoses[0].trans + scaleFactor * _hipsOffset;
|
||||||
|
}
|
||||||
|
|
||||||
solveWithCyclicCoordinateDescent(targets);
|
solveWithCyclicCoordinateDescent(targets);
|
||||||
|
|
||||||
|
// compute the new target hips offset (for next frame)
|
||||||
|
// by looking for discrepancies between where a targeted endEffector is
|
||||||
|
// and where it wants to be (after IK solutions are done)
|
||||||
|
glm::vec3 newHipsOffset = Vectors::ZERO;
|
||||||
|
for (auto& target: targets) {
|
||||||
|
int targetIndex = target.getIndex();
|
||||||
|
if (targetIndex == _headIndex && _headIndex != -1) {
|
||||||
|
// special handling for headTarget
|
||||||
|
if (target.getType() == IKTarget::Type::RotationOnly) {
|
||||||
|
// we want to shift the hips to bring the underpose closer
|
||||||
|
// to where the head happens to be (overpose)
|
||||||
|
glm::vec3 under = _skeleton->getAbsolutePose(_headIndex, underPoses).trans;
|
||||||
|
glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans;
|
||||||
|
const float HEAD_OFFSET_SLAVE_FACTOR = 0.65f;
|
||||||
|
newHipsOffset += HEAD_OFFSET_SLAVE_FACTOR * (actual - under);
|
||||||
|
} else if (target.getType() == IKTarget::Type::HmdHead) {
|
||||||
|
// we want to shift the hips to bring the head to its designated position
|
||||||
|
glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans;
|
||||||
|
_hipsOffset += target.getTranslation() - actual;
|
||||||
|
// and ignore all other targets
|
||||||
|
newHipsOffset = _hipsOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (target.getType() == IKTarget::Type::RotationAndPosition) {
|
||||||
|
glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans;
|
||||||
|
glm::vec3 targetPosition = target.getTranslation();
|
||||||
|
newHipsOffset += targetPosition - actualPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// smooth transitions by relaxing _hipsOffset toward the new value
|
||||||
|
const float HIPS_OFFSET_SLAVE_TIMESCALE = 0.15f;
|
||||||
|
_hipsOffset += (newHipsOffset - _hipsOffset) * (dt / HIPS_OFFSET_SLAVE_TIMESCALE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _relativePoses;
|
return _relativePoses;
|
||||||
|
@ -477,7 +525,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
stConstraint->setSwingLimits(minDots);
|
stConstraint->setSwingLimits(minDots);
|
||||||
|
|
||||||
constraint = static_cast<RotationConstraint*>(stConstraint);
|
constraint = static_cast<RotationConstraint*>(stConstraint);
|
||||||
} else if (0 == baseName.compare("UpLegXXX", Qt::CaseInsensitive)) {
|
} else if (0 == baseName.compare("UpLeg", Qt::CaseInsensitive)) {
|
||||||
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
||||||
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
||||||
stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f);
|
stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f);
|
||||||
|
@ -581,7 +629,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
} else if (0 == baseName.compare("Neck", Qt::CaseInsensitive)) {
|
} else if (0 == baseName.compare("Neck", Qt::CaseInsensitive)) {
|
||||||
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
||||||
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
||||||
const float MAX_NECK_TWIST = PI / 2.0f;
|
const float MAX_NECK_TWIST = PI / 4.0f;
|
||||||
stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST);
|
stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST);
|
||||||
|
|
||||||
std::vector<float> minDots;
|
std::vector<float> minDots;
|
||||||
|
@ -589,6 +637,18 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
minDots.push_back(cosf(MAX_NECK_SWING));
|
minDots.push_back(cosf(MAX_NECK_SWING));
|
||||||
stConstraint->setSwingLimits(minDots);
|
stConstraint->setSwingLimits(minDots);
|
||||||
|
|
||||||
|
constraint = static_cast<RotationConstraint*>(stConstraint);
|
||||||
|
} else if (0 == baseName.compare("Head", Qt::CaseInsensitive)) {
|
||||||
|
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
||||||
|
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
||||||
|
const float MAX_HEAD_TWIST = PI / 4.0f;
|
||||||
|
stConstraint->setTwistLimits(-MAX_HEAD_TWIST, MAX_HEAD_TWIST);
|
||||||
|
|
||||||
|
std::vector<float> minDots;
|
||||||
|
const float MAX_HEAD_SWING = PI / 4.0f;
|
||||||
|
minDots.push_back(cosf(MAX_HEAD_SWING));
|
||||||
|
stConstraint->setSwingLimits(minDots);
|
||||||
|
|
||||||
constraint = static_cast<RotationConstraint*>(stConstraint);
|
constraint = static_cast<RotationConstraint*>(stConstraint);
|
||||||
} else if (0 == baseName.compare("ForeArm", Qt::CaseInsensitive)) {
|
} else if (0 == baseName.compare("ForeArm", Qt::CaseInsensitive)) {
|
||||||
// The elbow joint rotates about the parent-frame's zAxis (-zAxis) for the Right (Left) arm.
|
// The elbow joint rotates about the parent-frame's zAxis (-zAxis) for the Right (Left) arm.
|
||||||
|
@ -621,7 +681,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
eConstraint->setAngleLimits(minAngle, maxAngle);
|
eConstraint->setAngleLimits(minAngle, maxAngle);
|
||||||
|
|
||||||
constraint = static_cast<RotationConstraint*>(eConstraint);
|
constraint = static_cast<RotationConstraint*>(eConstraint);
|
||||||
} else if (0 == baseName.compare("LegXXX", Qt::CaseInsensitive)) {
|
} else if (0 == baseName.compare("Leg", Qt::CaseInsensitive)) {
|
||||||
// The knee joint rotates about the parent-frame's -xAxis.
|
// The knee joint rotates about the parent-frame's -xAxis.
|
||||||
ElbowConstraint* eConstraint = new ElbowConstraint();
|
ElbowConstraint* eConstraint = new ElbowConstraint();
|
||||||
glm::quat referenceRotation = _defaultRelativePoses[i].rot;
|
glm::quat referenceRotation = _defaultRelativePoses[i].rot;
|
||||||
|
@ -652,7 +712,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
eConstraint->setAngleLimits(minAngle, maxAngle);
|
eConstraint->setAngleLimits(minAngle, maxAngle);
|
||||||
|
|
||||||
constraint = static_cast<RotationConstraint*>(eConstraint);
|
constraint = static_cast<RotationConstraint*>(eConstraint);
|
||||||
} else if (0 == baseName.compare("FootXXX", Qt::CaseInsensitive)) {
|
} else if (0 == baseName.compare("Foot", Qt::CaseInsensitive)) {
|
||||||
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
||||||
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
||||||
stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f);
|
stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f);
|
||||||
|
@ -697,7 +757,9 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
||||||
|
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
initConstraints();
|
initConstraints();
|
||||||
|
_headIndex = _skeleton->nameToJointIndex("Head");
|
||||||
} else {
|
} else {
|
||||||
clearConstraints();
|
clearConstraints();
|
||||||
|
_headIndex = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "AnimNode.h"
|
#include "AnimNode.h"
|
||||||
|
#include "IKTarget.h"
|
||||||
|
|
||||||
#include "RotationAccumulator.h"
|
#include "RotationAccumulator.h"
|
||||||
|
|
||||||
|
@ -37,18 +38,6 @@ public:
|
||||||
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override;
|
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct IKTarget {
|
|
||||||
enum class Type {
|
|
||||||
RotationAndPosition,
|
|
||||||
RotationOnly
|
|
||||||
};
|
|
||||||
AnimPose pose;
|
|
||||||
int index;
|
|
||||||
Type type = Type::RotationAndPosition;
|
|
||||||
|
|
||||||
void setType(const QString& typeVar) { type = ((typeVar == "RotationOnly") ? Type::RotationOnly : Type::RotationAndPosition); }
|
|
||||||
};
|
|
||||||
|
|
||||||
void computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses);
|
void computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses);
|
||||||
void solveWithCyclicCoordinateDescent(const std::vector<IKTarget>& targets);
|
void solveWithCyclicCoordinateDescent(const std::vector<IKTarget>& targets);
|
||||||
virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) override;
|
virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) override;
|
||||||
|
@ -60,6 +49,10 @@ protected:
|
||||||
void clearConstraints();
|
void clearConstraints();
|
||||||
void initConstraints();
|
void initConstraints();
|
||||||
|
|
||||||
|
// no copies
|
||||||
|
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
||||||
|
AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete;
|
||||||
|
|
||||||
struct IKTargetVar {
|
struct IKTargetVar {
|
||||||
IKTargetVar(const QString& jointNameIn,
|
IKTargetVar(const QString& jointNameIn,
|
||||||
const QString& positionVarIn,
|
const QString& positionVarIn,
|
||||||
|
@ -85,9 +78,9 @@ protected:
|
||||||
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
||||||
AnimPoseVec _relativePoses; // current relative poses
|
AnimPoseVec _relativePoses; // current relative poses
|
||||||
|
|
||||||
// no copies
|
// experimental data for moving hips during IK
|
||||||
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
int _headIndex = -1;
|
||||||
AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete;
|
glm::vec3 _hipsOffset = Vectors::ZERO;
|
||||||
|
|
||||||
// _maxTargetIndex is tracked to help optimize the recalculation of absolute poses
|
// _maxTargetIndex is tracked to help optimize the recalculation of absolute poses
|
||||||
// during the the cyclic coordinate descent algorithm
|
// during the the cyclic coordinate descent algorithm
|
||||||
|
|
34
libraries/animation/src/IKTarget.cpp
Normal file
34
libraries/animation/src/IKTarget.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//
|
||||||
|
// IKTarget.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "IKTarget.h"
|
||||||
|
|
||||||
|
void IKTarget::setPose(const glm::quat& rotation, const glm::vec3& translation) {
|
||||||
|
_pose.rot = rotation;
|
||||||
|
_pose.trans = translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKTarget::setType(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case (int)Type::RotationAndPosition:
|
||||||
|
_type = Type::RotationAndPosition;
|
||||||
|
break;
|
||||||
|
case (int)Type::RotationOnly:
|
||||||
|
_type = Type::RotationOnly;
|
||||||
|
break;
|
||||||
|
case (int)Type::HmdHead:
|
||||||
|
_type = Type::HmdHead;
|
||||||
|
break;
|
||||||
|
case (int)Type::HipsRelativeRotationAndPosition:
|
||||||
|
_type = Type::HipsRelativeRotationAndPosition;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_type = Type::Unknown;
|
||||||
|
}
|
||||||
|
}
|
43
libraries/animation/src/IKTarget.h
Normal file
43
libraries/animation/src/IKTarget.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// IKTarget.h
|
||||||
|
//
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_IKTarget_h
|
||||||
|
#define hifi_IKTarget_h
|
||||||
|
|
||||||
|
#include "AnimSkeleton.h"
|
||||||
|
|
||||||
|
class IKTarget {
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
RotationAndPosition,
|
||||||
|
RotationOnly,
|
||||||
|
HmdHead,
|
||||||
|
HipsRelativeRotationAndPosition,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
IKTarget() {}
|
||||||
|
|
||||||
|
const glm::vec3& getTranslation() const { return _pose.trans; }
|
||||||
|
const glm::quat& getRotation() const { return _pose.rot; }
|
||||||
|
int getIndex() const { return _index; }
|
||||||
|
Type getType() const { return _type; }
|
||||||
|
|
||||||
|
void setPose(const glm::quat& rotation, const glm::vec3& translation);
|
||||||
|
void setIndex(int index) { _index = index; }
|
||||||
|
void setType(int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AnimPose _pose;
|
||||||
|
int _index = -1;
|
||||||
|
Type _type = Type::RotationAndPosition;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_IKTarget_h
|
|
@ -14,13 +14,14 @@
|
||||||
#include <glm/gtx/vector_angle.hpp>
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "NumericalConstants.h"
|
#include <NumericalConstants.h>
|
||||||
|
#include <DebugDraw.h>
|
||||||
|
|
||||||
#include "AnimationHandle.h"
|
#include "AnimationHandle.h"
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
#include "AnimSkeleton.h"
|
#include "AnimSkeleton.h"
|
||||||
#include "DebugDraw.h"
|
#include "IKTarget.h"
|
||||||
|
|
||||||
#include "Rig.h"
|
|
||||||
|
|
||||||
void Rig::HeadParameters::dump() const {
|
void Rig::HeadParameters::dump() const {
|
||||||
qCDebug(animation, "HeadParameters =");
|
qCDebug(animation, "HeadParameters =");
|
||||||
|
@ -1057,9 +1058,11 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
||||||
|
|
||||||
_animVars.set("headPosition", headPos);
|
_animVars.set("headPosition", headPos);
|
||||||
_animVars.set("headRotation", headRot);
|
_animVars.set("headRotation", headRot);
|
||||||
_animVars.set("headAndNeckType", QString("RotationAndPosition"));
|
_animVars.set("headType", (int)IKTarget::Type::HmdHead);
|
||||||
_animVars.set("neckPosition", neckPos);
|
_animVars.set("neckPosition", neckPos);
|
||||||
_animVars.set("neckRotation", neckRot);
|
_animVars.set("neckRotation", neckRot);
|
||||||
|
//_animVars.set("neckType", (int)IKTarget::Type::RotationOnly);
|
||||||
|
_animVars.set("neckType", (int)IKTarget::Type::Unknown); // 'Unknown' disables the target
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -1070,9 +1073,11 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
||||||
|
|
||||||
_animVars.unset("headPosition");
|
_animVars.unset("headPosition");
|
||||||
_animVars.set("headRotation", realLocalHeadOrientation);
|
_animVars.set("headRotation", realLocalHeadOrientation);
|
||||||
_animVars.set("headAndNeckType", QString("RotationOnly"));
|
_animVars.set("headAndNeckType", (int)IKTarget::Type::RotationOnly);
|
||||||
|
_animVars.set("headType", (int)IKTarget::Type::RotationOnly);
|
||||||
_animVars.unset("neckPosition");
|
_animVars.unset("neckPosition");
|
||||||
_animVars.unset("neckRotation");
|
_animVars.unset("neckRotation");
|
||||||
|
_animVars.set("neckType", (int)IKTarget::Type::RotationOnly);
|
||||||
}
|
}
|
||||||
} else if (!_enableAnimGraph) {
|
} else if (!_enableAnimGraph) {
|
||||||
|
|
||||||
|
@ -1130,16 +1135,20 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
||||||
if (params.isLeftEnabled) {
|
if (params.isLeftEnabled) {
|
||||||
_animVars.set("leftHandPosition", rootBindPose.trans + rootBindPose.rot * yFlipHACK * params.leftPosition);
|
_animVars.set("leftHandPosition", rootBindPose.trans + rootBindPose.rot * yFlipHACK * params.leftPosition);
|
||||||
_animVars.set("leftHandRotation", rootBindPose.rot * yFlipHACK * params.leftOrientation);
|
_animVars.set("leftHandRotation", rootBindPose.rot * yFlipHACK * params.leftOrientation);
|
||||||
|
_animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
} else {
|
} else {
|
||||||
_animVars.unset("leftHandPosition");
|
_animVars.unset("leftHandPosition");
|
||||||
_animVars.unset("leftHandRotation");
|
_animVars.unset("leftHandRotation");
|
||||||
|
_animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||||
}
|
}
|
||||||
if (params.isRightEnabled) {
|
if (params.isRightEnabled) {
|
||||||
_animVars.set("rightHandPosition", rootBindPose.trans + rootBindPose.rot * yFlipHACK * params.rightPosition);
|
_animVars.set("rightHandPosition", rootBindPose.trans + rootBindPose.rot * yFlipHACK * params.rightPosition);
|
||||||
_animVars.set("rightHandRotation", rootBindPose.rot * yFlipHACK * params.rightOrientation);
|
_animVars.set("rightHandRotation", rootBindPose.rot * yFlipHACK * params.rightOrientation);
|
||||||
|
_animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
} else {
|
} else {
|
||||||
_animVars.unset("rightHandPosition");
|
_animVars.unset("rightHandPosition");
|
||||||
_animVars.unset("rightHandRotation");
|
_animVars.unset("rightHandRotation");
|
||||||
|
_animVars.set("rightHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set leftHand grab vars
|
// set leftHand grab vars
|
||||||
|
|
|
@ -7,5 +7,10 @@
|
||||||
//
|
//
|
||||||
#include "Mapping.h"
|
#include "Mapping.h"
|
||||||
|
|
||||||
|
namespace controller {
|
||||||
|
Mapping::Mapping(const QString& name ) : _name(name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,10 @@ namespace controller {
|
||||||
using Map = std::map<Endpoint::Pointer, Route::List>;
|
using Map = std::map<Endpoint::Pointer, Route::List>;
|
||||||
using Pointer = std::shared_ptr<Mapping>;
|
using Pointer = std::shared_ptr<Mapping>;
|
||||||
|
|
||||||
|
Mapping(const QString& name);
|
||||||
|
|
||||||
Map _channelMappings;
|
Map _channelMappings;
|
||||||
|
|
||||||
QString _name;
|
QString _name;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -59,6 +59,25 @@ namespace controller {
|
||||||
QJSValue _callable;
|
QJSValue _callable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScriptEndpoint : public Endpoint {
|
||||||
|
public:
|
||||||
|
ScriptEndpoint(const QScriptValue& callable)
|
||||||
|
: Endpoint(UserInputMapper::Input(-1)), _callable(callable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float value() {
|
||||||
|
float result = (float)_callable.call().toNumber();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(float newValue, float oldValue, const Pointer& source) {
|
||||||
|
_callable.call(QScriptValue(), QScriptValueList({ QScriptValue(newValue) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QScriptValue _callable;
|
||||||
|
};
|
||||||
|
|
||||||
class CompositeEndpoint : public Endpoint, Endpoint::Pair {
|
class CompositeEndpoint : public Endpoint, Endpoint::Pair {
|
||||||
public:
|
public:
|
||||||
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second)
|
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second)
|
||||||
|
@ -158,7 +177,7 @@ namespace controller {
|
||||||
qCWarning(controllers) << "Refusing to recreate mapping named " << mappingName;
|
qCWarning(controllers) << "Refusing to recreate mapping named " << mappingName;
|
||||||
}
|
}
|
||||||
qDebug() << "Creating new Mapping " << mappingName;
|
qDebug() << "Creating new Mapping " << mappingName;
|
||||||
Mapping::Pointer mapping = std::make_shared<Mapping>();
|
auto mapping = std::make_shared<Mapping>(mappingName);
|
||||||
_mappingsByName[mappingName] = mapping;
|
_mappingsByName[mappingName] = mapping;
|
||||||
return new MappingBuilderProxy(*this, mapping);
|
return new MappingBuilderProxy(*this, mapping);
|
||||||
}
|
}
|
||||||
|
@ -297,6 +316,11 @@ namespace controller {
|
||||||
return endpointFor(UserInputMapper::Input(endpoint.toInt32()));
|
return endpointFor(UserInputMapper::Input(endpoint.toInt32()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (endpoint.isFunction()) {
|
||||||
|
auto result = std::make_shared<ScriptEndpoint>(endpoint);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
qWarning() << "Unsupported input type " << endpoint.toString();
|
qWarning() << "Unsupported input type " << endpoint.toString();
|
||||||
return Endpoint::Pointer();
|
return Endpoint::Pointer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace controller {
|
||||||
Q_INVOKABLE float getValue(const int& source);
|
Q_INVOKABLE float getValue(const int& source);
|
||||||
|
|
||||||
Q_INVOKABLE void update();
|
Q_INVOKABLE void update();
|
||||||
Q_INVOKABLE QObject* newMapping(const QString& mappingName);
|
Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString());
|
||||||
Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true);
|
Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true);
|
||||||
Q_INVOKABLE void disableMapping(const QString& mappingName) {
|
Q_INVOKABLE void disableMapping(const QString& mappingName) {
|
||||||
enableMapping(mappingName, false);
|
enableMapping(mappingName, false);
|
||||||
|
|
|
@ -44,7 +44,6 @@ QObject* MappingBuilderProxy::join(const QJSValue& source1, const QJSValue& sour
|
||||||
return from(_parent.compositeEndpointFor(source1Endpoint, source2Endpoint));
|
return from(_parent.compositeEndpointFor(source1Endpoint, source2Endpoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const QString JSON_NAME = QStringLiteral("name");
|
const QString JSON_NAME = QStringLiteral("name");
|
||||||
const QString JSON_CHANNELS = QStringLiteral("channels");
|
const QString JSON_CHANNELS = QStringLiteral("channels");
|
||||||
const QString JSON_CHANNEL_FROM = QStringLiteral("from");
|
const QString JSON_CHANNEL_FROM = QStringLiteral("from");
|
||||||
|
@ -84,4 +83,9 @@ QObject* MappingBuilderProxy::from(const QJsonValue& json) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject* MappingBuilderProxy::enable(bool enable) {
|
||||||
|
_parent.enableMapping(_mapping->_name, enable);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,18 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE QObject* from(const QJSValue& source);
|
Q_INVOKABLE QObject* from(const QJSValue& source);
|
||||||
Q_INVOKABLE QObject* from(const QScriptValue& source);
|
Q_INVOKABLE QObject* from(const QScriptValue& source);
|
||||||
|
|
||||||
Q_INVOKABLE QObject* join(const QJSValue& source1, const QJSValue& source2);
|
Q_INVOKABLE QObject* join(const QJSValue& source1, const QJSValue& source2);
|
||||||
|
|
||||||
|
Q_INVOKABLE QObject* enable(bool enable = true);
|
||||||
|
Q_INVOKABLE QObject* disable() { return enable(false); }
|
||||||
|
|
||||||
|
|
||||||
// JSON route creation point
|
// JSON route creation point
|
||||||
Q_INVOKABLE QObject* from(const QJsonValue& json);
|
Q_INVOKABLE QObject* from(const QJsonValue& json);
|
||||||
|
|
||||||
|
|
||||||
void parse(const QJsonObject& json);
|
void parse(const QJsonObject& json);
|
||||||
// void serialize(QJsonObject& json);
|
// void serialize(QJsonObject& json);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QObject* from(const Endpoint::Pointer& source);
|
QObject* from(const Endpoint::Pointer& source);
|
||||||
|
|
|
@ -27,7 +27,4 @@ void NullDisplayPlugin::preRender() {}
|
||||||
void NullDisplayPlugin::preDisplay() {}
|
void NullDisplayPlugin::preDisplay() {}
|
||||||
void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize) {}
|
void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize) {}
|
||||||
void NullDisplayPlugin::finishFrame() {}
|
void NullDisplayPlugin::finishFrame() {}
|
||||||
|
|
||||||
void NullDisplayPlugin::activate() {}
|
|
||||||
void NullDisplayPlugin::deactivate() {}
|
|
||||||
void NullDisplayPlugin::stop() {}
|
void NullDisplayPlugin::stop() {}
|
||||||
|
|
|
@ -15,8 +15,6 @@ public:
|
||||||
virtual ~NullDisplayPlugin() final {}
|
virtual ~NullDisplayPlugin() final {}
|
||||||
virtual const QString & getName() const override;
|
virtual const QString & getName() const override;
|
||||||
|
|
||||||
void activate() override;
|
|
||||||
void deactivate() override;
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
|
|
|
@ -57,12 +57,12 @@ void OpenGLDisplayPlugin::customizeContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::activate() {
|
void OpenGLDisplayPlugin::activate() {
|
||||||
_active = true;
|
DisplayPlugin::activate();
|
||||||
_timer.start(1);
|
_timer.start(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::stop() {
|
void OpenGLDisplayPlugin::stop() {
|
||||||
_active = false;
|
DisplayPlugin::activate();
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@ protected:
|
||||||
mutable QTimer _timer;
|
mutable QTimer _timer;
|
||||||
ProgramPtr _program;
|
ProgramPtr _program;
|
||||||
ShapeWrapperPtr _plane;
|
ShapeWrapperPtr _plane;
|
||||||
bool _active{ false };
|
|
||||||
bool _vsyncSupported{ false };
|
bool _vsyncSupported{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ InputPluginList getInputPlugins() {
|
||||||
InputPlugin* PLUGIN_POOL[] = {
|
InputPlugin* PLUGIN_POOL[] = {
|
||||||
new KeyboardMouseDevice(),
|
new KeyboardMouseDevice(),
|
||||||
new SDL2Manager(),
|
new SDL2Manager(),
|
||||||
//new SixenseManager(),
|
new SixenseManager(),
|
||||||
//new ViveControllerManager(),
|
//new ViveControllerManager(),
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
//
|
//
|
||||||
#include "KeyboardMouseDevice.h"
|
#include "KeyboardMouseDevice.h"
|
||||||
|
|
||||||
#include <QtGUI/QKeyEvent>
|
#include <QtGui/QKeyEvent>
|
||||||
#include <QtGUI/QMouseEvent>
|
#include <QtGui/QMouseEvent>
|
||||||
#include <QtGUI/QTouchEvent>
|
#include <QtGui/QTouchEvent>
|
||||||
|
|
||||||
|
|
||||||
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
#define hifi_KeyboardMouseDevice_h
|
#define hifi_KeyboardMouseDevice_h
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#include <QtCore/QPoint>
|
||||||
|
|
||||||
#include "InputDevice.h"
|
#include "InputDevice.h"
|
||||||
#include "InputPlugin.h"
|
#include "InputPlugin.h"
|
||||||
|
|
||||||
|
@ -65,9 +68,6 @@ public:
|
||||||
virtual bool isJointController() const override { return false; }
|
virtual bool isJointController() const override { return false; }
|
||||||
const QString& getName() const override { return NAME; }
|
const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual void activate() override {};
|
|
||||||
virtual void deactivate() override {};
|
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ public:
|
||||||
|
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
virtual void deinit() override;
|
virtual void deinit() override;
|
||||||
virtual void activate() override {};
|
|
||||||
virtual void deactivate() override {};
|
|
||||||
|
|
||||||
virtual void pluginFocusOutEvent() override;
|
virtual void pluginFocusOutEvent() override;
|
||||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||||
|
|
|
@ -85,6 +85,7 @@ bool SixenseManager::isSupported() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::activate() {
|
void SixenseManager::activate() {
|
||||||
|
InputPlugin::activate();
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||||
_avatarPosition = DEFAULT_AVATAR_POSITION;
|
_avatarPosition = DEFAULT_AVATAR_POSITION;
|
||||||
|
@ -125,6 +126,7 @@ void SixenseManager::activate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::deactivate() {
|
void SixenseManager::deactivate() {
|
||||||
|
InputPlugin::deactivate();
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
CONTAINER->removeMenuItem(MENU_NAME, TOGGLE_SMOOTH);
|
CONTAINER->removeMenuItem(MENU_NAME, TOGGLE_SMOOTH);
|
||||||
CONTAINER->removeMenu(MENU_PATH);
|
CONTAINER->removeMenu(MENU_PATH);
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
const float CONTROLLER_THRESHOLD = 0.3f;
|
const float CONTROLLER_THRESHOLD = 0.3f;
|
||||||
|
|
||||||
const float MAX_AXIS = 32768.0f;
|
|
||||||
|
|
||||||
StandardController::~StandardController() {
|
StandardController::~StandardController() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,7 @@ bool ViveControllerManager::isSupported() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViveControllerManager::activate() {
|
void ViveControllerManager::activate() {
|
||||||
|
InputPlugin::activate();
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
CONTAINER->addMenu(MENU_PATH);
|
CONTAINER->addMenu(MENU_PATH);
|
||||||
CONTAINER->addMenuItem(MENU_PATH, RENDER_CONTROLLERS,
|
CONTAINER->addMenuItem(MENU_PATH, RENDER_CONTROLLERS,
|
||||||
|
@ -143,6 +144,8 @@ void ViveControllerManager::activate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViveControllerManager::deactivate() {
|
void ViveControllerManager::deactivate() {
|
||||||
|
InputPlugin::deactivate();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
CONTAINER->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
|
CONTAINER->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
|
||||||
CONTAINER->removeMenu(MENU_PATH);
|
CONTAINER->removeMenu(MENU_PATH);
|
||||||
|
|
|
@ -14,10 +14,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtNetwork/QAbstractNetworkCache>
|
|
||||||
|
|
||||||
#include "AssetClient.h"
|
#include "AssetClient.h"
|
||||||
#include "NetworkAccessManager.h"
|
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
#include "ResourceCache.h"
|
#include "ResourceCache.h"
|
||||||
|
@ -41,14 +39,14 @@ void AssetRequest::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to load from cache
|
// Try to load from cache
|
||||||
if (loadFromCache()) {
|
_data = loadFromCache(getUrl());
|
||||||
|
if (!_data.isNull()) {
|
||||||
_info.hash = _hash;
|
_info.hash = _hash;
|
||||||
_info.size = _data.size();
|
_info.size = _data.size();
|
||||||
_error = NoError;
|
_error = NoError;
|
||||||
|
|
||||||
_state = Finished;
|
_state = Finished;
|
||||||
emit finished(this);
|
emit finished(this);
|
||||||
qCDebug(asset_client) << getUrl().toDisplayString() << "loaded from disk cache.";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +110,7 @@ void AssetRequest::start() {
|
||||||
_totalReceived += data.size();
|
_totalReceived += data.size();
|
||||||
emit progress(_totalReceived, _info.size);
|
emit progress(_totalReceived, _info.size);
|
||||||
|
|
||||||
if (saveToCache(data)) {
|
saveToCache(getUrl(), data);
|
||||||
qCDebug(asset_client) << getUrl().toDisplayString() << "saved to disk cache";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// hash doesn't match - we have an error
|
// hash doesn't match - we have an error
|
||||||
_error = HashVerificationFailed;
|
_error = HashVerificationFailed;
|
||||||
|
@ -133,49 +129,6 @@ void AssetRequest::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl AssetRequest::getUrl() const {
|
QUrl AssetRequest::getUrl() const {
|
||||||
if (!_extension.isEmpty()) {
|
return ::getUrl(_hash, _extension);
|
||||||
return QUrl(QString("%1:%2.%3").arg(URL_SCHEME_ATP, _hash, _extension));
|
|
||||||
} else {
|
|
||||||
return QUrl(QString("%1:%2").arg(URL_SCHEME_ATP, _hash));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetRequest::loadFromCache() {
|
|
||||||
if (auto cache = NetworkAccessManager::getInstance().cache()) {
|
|
||||||
auto url = getUrl();
|
|
||||||
if (auto ioDevice = cache->data(url)) {
|
|
||||||
_data = ioDevice->readAll();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
qCDebug(asset_client) << url.toDisplayString() << "not in disk cache";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qCWarning(asset_client) << "No disk cache to load assets from.";
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssetRequest::saveToCache(const QByteArray& file) const {
|
|
||||||
if (auto cache = NetworkAccessManager::getInstance().cache()) {
|
|
||||||
auto url = getUrl();
|
|
||||||
|
|
||||||
if (!cache->metaData(url).isValid()) {
|
|
||||||
QNetworkCacheMetaData metaData;
|
|
||||||
metaData.setUrl(url);
|
|
||||||
metaData.setSaveToDisk(true);
|
|
||||||
metaData.setLastModified(QDateTime::currentDateTime());
|
|
||||||
metaData.setExpirationDate(QDateTime()); // Never expires
|
|
||||||
|
|
||||||
if (auto ioDevice = cache->prepare(metaData)) {
|
|
||||||
ioDevice->write(file);
|
|
||||||
cache->insert(ioDevice);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
qCWarning(asset_client) << "Could not save" << url.toDisplayString() << "to disk cache.";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qCWarning(asset_client) << "No disk cache to save assets to.";
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,6 @@ signals:
|
||||||
void progress(qint64 totalReceived, qint64 total);
|
void progress(qint64 totalReceived, qint64 total);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool loadFromCache();
|
|
||||||
bool saveToCache(const QByteArray& file) const;
|
|
||||||
|
|
||||||
State _state = NotStarted;
|
State _state = NotStarted;
|
||||||
Error _error = NoError;
|
Error _error = NoError;
|
||||||
AssetInfo _info;
|
AssetInfo _info;
|
||||||
|
|
|
@ -25,7 +25,7 @@ AssetUpload::AssetUpload(QObject* object, const QString& filename) :
|
||||||
|
|
||||||
void AssetUpload::start() {
|
void AssetUpload::start() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "start", Qt::AutoConnection);
|
QMetaObject::invokeMethod(this, "start");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +37,15 @@ void AssetUpload::start() {
|
||||||
// file opened, read the data and grab the extension
|
// file opened, read the data and grab the extension
|
||||||
_extension = QFileInfo(_filename).suffix();
|
_extension = QFileInfo(_filename).suffix();
|
||||||
|
|
||||||
auto data = file.readAll();
|
_data = file.readAll();
|
||||||
|
|
||||||
// ask the AssetClient to upload the asset and emit the proper signals from the passed callback
|
// ask the AssetClient to upload the asset and emit the proper signals from the passed callback
|
||||||
auto assetClient = DependencyManager::get<AssetClient>();
|
auto assetClient = DependencyManager::get<AssetClient>();
|
||||||
|
|
||||||
qCDebug(asset_client) << "Attempting to upload" << _filename << "to asset-server.";
|
qCDebug(asset_client) << "Attempting to upload" << _filename << "to asset-server.";
|
||||||
|
|
||||||
assetClient->uploadAsset(data, _extension, [this](bool responseReceived, AssetServerError error, const QString& hash){
|
assetClient->uploadAsset(_data, _extension, [this](bool responseReceived, AssetServerError error,
|
||||||
|
const QString& hash){
|
||||||
if (!responseReceived) {
|
if (!responseReceived) {
|
||||||
_error = NetworkError;
|
_error = NetworkError;
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,6 +64,11 @@ void AssetUpload::start() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_error == NoError && hash == hashData(_data).toHex()) {
|
||||||
|
saveToCache(getUrl(hash, _extension), _data);
|
||||||
|
}
|
||||||
|
|
||||||
emit finished(this, hash);
|
emit finished(this, hash);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -50,6 +50,7 @@ signals:
|
||||||
private:
|
private:
|
||||||
QString _filename;
|
QString _filename;
|
||||||
QString _extension;
|
QString _extension;
|
||||||
|
QByteArray _data;
|
||||||
Error _error;
|
Error _error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
69
libraries/networking/src/AssetUtils.cpp
Normal file
69
libraries/networking/src/AssetUtils.cpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
//
|
||||||
|
// AssetUtils.h
|
||||||
|
// libraries/networking/src
|
||||||
|
//
|
||||||
|
// Created by Clément Brisset on 10/12/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AssetUtils.h"
|
||||||
|
|
||||||
|
#include <QtCore/QCryptographicHash>
|
||||||
|
#include <QtNetwork/QAbstractNetworkCache>
|
||||||
|
|
||||||
|
#include "NetworkAccessManager.h"
|
||||||
|
#include "NetworkLogging.h"
|
||||||
|
|
||||||
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
|
QUrl getUrl(const QString& hash, const QString& extension) {
|
||||||
|
if (!extension.isEmpty()) {
|
||||||
|
return QUrl(QString("%1:%2.%3").arg(URL_SCHEME_ATP, hash, extension));
|
||||||
|
} else {
|
||||||
|
return QUrl(QString("%1:%2").arg(URL_SCHEME_ATP, hash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray hashData(const QByteArray& data) {
|
||||||
|
return QCryptographicHash::hash(data, QCryptographicHash::Sha256);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray loadFromCache(const QUrl& url) {
|
||||||
|
if (auto cache = NetworkAccessManager::getInstance().cache()) {
|
||||||
|
if (auto ioDevice = cache->data(url)) {
|
||||||
|
qCDebug(asset_client) << url.toDisplayString() << "loaded from disk cache.";
|
||||||
|
return ioDevice->readAll();
|
||||||
|
} else {
|
||||||
|
qCDebug(asset_client) << url.toDisplayString() << "not in disk cache";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCWarning(asset_client) << "No disk cache to load assets from.";
|
||||||
|
}
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saveToCache(const QUrl& url, const QByteArray& file) {
|
||||||
|
if (auto cache = NetworkAccessManager::getInstance().cache()) {
|
||||||
|
if (!cache->metaData(url).isValid()) {
|
||||||
|
QNetworkCacheMetaData metaData;
|
||||||
|
metaData.setUrl(url);
|
||||||
|
metaData.setSaveToDisk(true);
|
||||||
|
metaData.setLastModified(QDateTime::currentDateTime());
|
||||||
|
metaData.setExpirationDate(QDateTime()); // Never expires
|
||||||
|
|
||||||
|
if (auto ioDevice = cache->prepare(metaData)) {
|
||||||
|
ioDevice->write(file);
|
||||||
|
cache->insert(ioDevice);
|
||||||
|
qCDebug(asset_client) << url.toDisplayString() << "saved to disk cache";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
qCWarning(asset_client) << "Could not save" << url.toDisplayString() << "to disk cache.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCWarning(asset_client) << "No disk cache to save assets to.";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -12,10 +12,11 @@
|
||||||
#ifndef hifi_AssetUtils_h
|
#ifndef hifi_AssetUtils_h
|
||||||
#define hifi_AssetUtils_h
|
#define hifi_AssetUtils_h
|
||||||
|
|
||||||
#include <QtCore/QCryptographicHash>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <QtCore/QByteArray>
|
||||||
|
#include <QtCore/QUrl>
|
||||||
|
|
||||||
using MessageID = uint32_t;
|
using MessageID = uint32_t;
|
||||||
using DataOffset = int64_t;
|
using DataOffset = int64_t;
|
||||||
|
|
||||||
|
@ -31,8 +32,11 @@ enum AssetServerError : uint8_t {
|
||||||
PermissionDenied
|
PermissionDenied
|
||||||
};
|
};
|
||||||
|
|
||||||
const QString ATP_SCHEME = "atp";
|
QUrl getUrl(const QString& hash, const QString& extension = QString());
|
||||||
|
|
||||||
inline QByteArray hashData(const QByteArray& data) { return QCryptographicHash::hash(data, QCryptographicHash::Sha256); }
|
QByteArray hashData(const QByteArray& data);
|
||||||
|
|
||||||
|
QByteArray loadFromCache(const QUrl& url);
|
||||||
|
bool saveToCache(const QUrl& url, const QByteArray& file);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -319,10 +319,10 @@ void Resource::attemptRequest() {
|
||||||
|
|
||||||
void Resource::finishedLoading(bool success) {
|
void Resource::finishedLoading(bool success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
qDebug() << "Finished loading:" << _url;
|
qDebug().noquote() << "Finished loading:" << _url.toDisplayString();
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Failed to load:" << _url;
|
qDebug().noquote() << "Failed to load:" << _url.toDisplayString();
|
||||||
_failedToLoad = true;
|
_failedToLoad = true;
|
||||||
}
|
}
|
||||||
_loadPriorities.clear();
|
_loadPriorities.clear();
|
||||||
|
@ -339,13 +339,13 @@ void Resource::makeRequest() {
|
||||||
_request = ResourceManager::createResourceRequest(this, _activeUrl);
|
_request = ResourceManager::createResourceRequest(this, _activeUrl);
|
||||||
|
|
||||||
if (!_request) {
|
if (!_request) {
|
||||||
qDebug() << "Failed to get request for " << _url;
|
qDebug().noquote() << "Failed to get request for" << _url.toDisplayString();
|
||||||
ResourceCache::requestCompleted(this);
|
ResourceCache::requestCompleted(this);
|
||||||
finishedLoading(false);
|
finishedLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Starting request for: " << _url;
|
qDebug().noquote() << "Starting request for:" << _url.toDisplayString();
|
||||||
|
|
||||||
connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress);
|
connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress);
|
||||||
connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
|
connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
|
||||||
|
@ -368,7 +368,8 @@ void Resource::handleReplyFinished() {
|
||||||
auto result = _request->getResult();
|
auto result = _request->getResult();
|
||||||
if (result == ResourceRequest::Success) {
|
if (result == ResourceRequest::Success) {
|
||||||
_data = _request->getData();
|
_data = _request->getData();
|
||||||
qDebug() << "Request finished for " << _url << ", " << _activeUrl;
|
auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString());
|
||||||
|
qDebug().noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo);
|
||||||
|
|
||||||
finishedLoading(true);
|
finishedLoading(true);
|
||||||
emit loaded(_data);
|
emit loaded(_data);
|
||||||
|
|
|
@ -33,9 +33,18 @@ public:
|
||||||
virtual void deinit();
|
virtual void deinit();
|
||||||
|
|
||||||
/// Called when a plugin is being activated for use. May be called multiple times.
|
/// Called when a plugin is being activated for use. May be called multiple times.
|
||||||
virtual void activate() = 0;
|
virtual void activate() {
|
||||||
|
_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Called when a plugin is no longer being used. May be called multiple times.
|
/// Called when a plugin is no longer being used. May be called multiple times.
|
||||||
virtual void deactivate() = 0;
|
virtual void deactivate() {
|
||||||
|
_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isActive() {
|
||||||
|
return _active;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the application during it's idle phase. If the plugin needs to do
|
* Called by the application during it's idle phase. If the plugin needs to do
|
||||||
|
@ -48,6 +57,7 @@ public:
|
||||||
virtual void loadSettings() {}
|
virtual void loadSettings() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool _active{ false };
|
||||||
static PluginContainer* CONTAINER;
|
static PluginContainer* CONTAINER;
|
||||||
static QString UNKNOWN_PLUGIN_ID;
|
static QString UNKNOWN_PLUGIN_ID;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
set(TARGET_NAME controllers-test)
|
set(TARGET_NAME controllers-test)
|
||||||
|
|
||||||
# This is not a testcase -- just set it up as a regular hifi project
|
# This is not a testcase -- just set it up as a regular hifi project
|
||||||
setup_hifi_project(Script)
|
setup_hifi_project(Script Qml)
|
||||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
||||||
|
|
||||||
# link in the shared libraries
|
# link in the shared libraries
|
||||||
|
|
|
@ -8,10 +8,21 @@ import "./controls"
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
||||||
property var xbox: NewControllers.Hardware.X360Controller1
|
|
||||||
property var actions: NewControllers.Actions
|
property var actions: NewControllers.Actions
|
||||||
property var standard: NewControllers.Standard
|
property var standard: NewControllers.Standard
|
||||||
property string mappingName: "TestMapping"
|
property var testMapping: null
|
||||||
|
property var xbox: null
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var patt = /^X360Controller/;
|
||||||
|
for (var prop in NewControllers.Hardware) {
|
||||||
|
if(patt.test(prop)) {
|
||||||
|
root.xbox = NewControllers.Hardware[prop]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
|
||||||
|
@ -49,13 +60,15 @@ Column {
|
||||||
mapping.from(xbox.LT).to(standard.LT);
|
mapping.from(xbox.LT).to(standard.LT);
|
||||||
mapping.from(xbox.RT).to(standard.RT);
|
mapping.from(xbox.RT).to(standard.RT);
|
||||||
NewControllers.enableMapping("Default");
|
NewControllers.enableMapping("Default");
|
||||||
|
enabled = false;
|
||||||
|
text = "Built"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Build Mapping"
|
text: "Build Mapping"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var mapping = NewControllers.newMapping(root.mappingName);
|
var mapping = NewControllers.newMapping();
|
||||||
// Inverting a value
|
// Inverting a value
|
||||||
mapping.from(xbox.RY).invert().to(standard.RY);
|
mapping.from(xbox.RY).invert().to(standard.RY);
|
||||||
// Assigning a value from a function
|
// Assigning a value from a function
|
||||||
|
@ -63,17 +76,22 @@ Column {
|
||||||
// Constrainting a value to -1, 0, or 1, with a deadzone
|
// Constrainting a value to -1, 0, or 1, with a deadzone
|
||||||
mapping.from(xbox.LY).deadZone(0.5).constrainToInteger().to(standard.LY);
|
mapping.from(xbox.LY).deadZone(0.5).constrainToInteger().to(standard.LY);
|
||||||
mapping.join(standard.LB, standard.RB).pulse(0.5).to(actions.Yaw);
|
mapping.join(standard.LB, standard.RB).pulse(0.5).to(actions.Yaw);
|
||||||
|
mapping.from(actions.Yaw).clamp(0, 1).invert().to(actions.YAW_RIGHT);
|
||||||
|
mapping.from(actions.Yaw).clamp(-1, 0).to(actions.YAW_LEFT);
|
||||||
|
testMapping = mapping;
|
||||||
|
enabled = false
|
||||||
|
text = "Built"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Enable Mapping"
|
text: "Enable Mapping"
|
||||||
onClicked: NewControllers.enableMapping(root.mappingName)
|
onClicked: root.testMapping.enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Disable Mapping"
|
text: "Disable Mapping"
|
||||||
onClicked: NewControllers.disableMapping(root.mappingName)
|
onClicked: root.testMapping.disable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +103,7 @@ Column {
|
||||||
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
spacing: 8
|
||||||
ScrollingGraph {
|
ScrollingGraph {
|
||||||
controlId: NewControllers.Actions.Yaw
|
controlId: NewControllers.Actions.Yaw
|
||||||
label: "Yaw"
|
label: "Yaw"
|
||||||
|
@ -92,6 +111,22 @@ Column {
|
||||||
max: 3.0
|
max: 3.0
|
||||||
size: 128
|
size: 128
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrollingGraph {
|
||||||
|
controlId: NewControllers.Actions.YAW_LEFT
|
||||||
|
label: "Yaw Left"
|
||||||
|
min: -3.0
|
||||||
|
max: 3.0
|
||||||
|
size: 128
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollingGraph {
|
||||||
|
controlId: NewControllers.Actions.YAW_RIGHT
|
||||||
|
label: "Yaw Right"
|
||||||
|
min: -3.0
|
||||||
|
max: 3.0
|
||||||
|
size: 128
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,9 @@ public:
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
|
for (auto path : qApp->libraryPaths()) {
|
||||||
|
qDebug() << path;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto path : qApp->libraryPaths()) {
|
for (auto path : qApp->libraryPaths()) {
|
||||||
qDebug() << path;
|
qDebug() << path;
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MasterReset = function() {
|
MasterReset = function() {
|
||||||
var resetKey = "resetMe";
|
var resetKey = "resetMe";
|
||||||
var GRABBABLE_DATA_KEY = "grabbableKey";
|
var GRABBABLE_DATA_KEY = "grabbableKey";
|
||||||
|
@ -407,11 +406,6 @@
|
||||||
type: 'Box',
|
type: 'Box',
|
||||||
position: startPosition,
|
position: startPosition,
|
||||||
dimensions: TARGET_DIMENSIONS,
|
dimensions: TARGET_DIMENSIONS,
|
||||||
color: {
|
|
||||||
red: 0,
|
|
||||||
green: 255,
|
|
||||||
blue: 0
|
|
||||||
},
|
|
||||||
rotation: rotation,
|
rotation: rotation,
|
||||||
visible: false,
|
visible: false,
|
||||||
collisionsWillMove: false,
|
collisionsWillMove: false,
|
||||||
|
@ -658,6 +652,7 @@
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -685,6 +680,7 @@
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -734,7 +730,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var sconceLight3 = Entities.addEntity({
|
var sconceLight3 = Entities.addEntity({
|
||||||
type: "Light",
|
type: "Light",
|
||||||
position: {
|
position: {
|
||||||
|
@ -755,6 +750,7 @@
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -783,6 +779,7 @@
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -810,6 +807,7 @@
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -888,7 +886,7 @@
|
||||||
y: 1.13,
|
y: 1.13,
|
||||||
z: 0.2
|
z: 0.2
|
||||||
},
|
},
|
||||||
rotation: rotation2,
|
rotation: rotation,
|
||||||
collisionsWillMove: true,
|
collisionsWillMove: true,
|
||||||
gravity: {
|
gravity: {
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -1256,7 +1254,7 @@
|
||||||
y: 0.05,
|
y: 0.05,
|
||||||
z: 0.25
|
z: 0.25
|
||||||
}
|
}
|
||||||
},];
|
}, ];
|
||||||
|
|
||||||
var modelURL, entity;
|
var modelURL, entity;
|
||||||
for (i = 0; i < blockTypes.length; i++) {
|
for (i = 0; i < blockTypes.length; i++) {
|
||||||
|
@ -1305,7 +1303,6 @@
|
||||||
Script.scriptEnding.connect(cleanup);
|
Script.scriptEnding.connect(cleanup);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// entity scripts always need to return a newly constructed object of our type
|
// entity scripts always need to return a newly constructed object of our type
|
||||||
return new ResetSwitch();
|
return new ResetSwitch();
|
||||||
});
|
});
|
|
@ -625,6 +625,7 @@ MasterReset = function() {
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -652,6 +653,7 @@ MasterReset = function() {
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -701,7 +703,6 @@ MasterReset = function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var sconceLight3 = Entities.addEntity({
|
var sconceLight3 = Entities.addEntity({
|
||||||
type: "Light",
|
type: "Light",
|
||||||
position: {
|
position: {
|
||||||
|
@ -722,6 +723,7 @@ MasterReset = function() {
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -750,6 +752,7 @@ MasterReset = function() {
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -777,6 +780,7 @@ MasterReset = function() {
|
||||||
green: 146,
|
green: 146,
|
||||||
blue: 24
|
blue: 24
|
||||||
},
|
},
|
||||||
|
isSpotlight: false,
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
|
@ -1223,7 +1227,7 @@ MasterReset = function() {
|
||||||
y: 0.05,
|
y: 0.05,
|
||||||
z: 0.25
|
z: 0.25
|
||||||
}
|
}
|
||||||
},];
|
}, ];
|
||||||
|
|
||||||
var modelURL, entity;
|
var modelURL, entity;
|
||||||
for (i = 0; i < blockTypes.length; i++) {
|
for (i = 0; i < blockTypes.length; i++) {
|
||||||
|
|
Loading…
Reference in a new issue