mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 13:23:36 +02:00
moving libraries style JS files to libraries
This commit is contained in:
parent
d0026cd529
commit
bfde23349f
15 changed files with 1781 additions and 18 deletions
|
@ -18,7 +18,7 @@ var controlVoxelSize = 0.25;
|
|||
var controlVoxelPosition = { x: 2000 , y: 0, z: 0 };
|
||||
|
||||
// Script. DO NOT MODIFY BEYOND THIS LINE.
|
||||
Script.include("toolBars.js");
|
||||
Script.include("libraries/toolBars.js");
|
||||
|
||||
var DO_NOTHING = 0;
|
||||
var PLAY = 1;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("toolBars.js");
|
||||
Script.include("libraries/toolBars.js");
|
||||
|
||||
var recordingFile = "recording.rec";
|
||||
|
||||
|
|
|
@ -22,10 +22,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("toolBars.js");
|
||||
Script.include("entitySelectionTool.js");
|
||||
var selectionDisplay = SelectionDisplay;
|
||||
|
||||
Script.include("libraries/toolBars.js");
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var toolIconUrl = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/";
|
||||
var toolHeight = 50;
|
||||
|
@ -2022,7 +2019,6 @@ function controller(wichSide) {
|
|||
|
||||
if (this.glowedIntersectingModel.isKnownID) {
|
||||
Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.0 });
|
||||
selectionDisplay.hideSelection(this.glowedIntersectingModel);
|
||||
this.glowedIntersectingModel.isKnownID = false;
|
||||
}
|
||||
if (!this.grabbing) {
|
||||
|
@ -2042,7 +2038,6 @@ function controller(wichSide) {
|
|||
if (wantEntityGlow) {
|
||||
Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 });
|
||||
}
|
||||
selectionDisplay.showSelection(this.glowedIntersectingModel, intersection.properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2113,7 +2108,6 @@ function controller(wichSide) {
|
|||
});
|
||||
this.oldModelRotation = newRotation;
|
||||
this.oldModelPosition = newPosition;
|
||||
selectionDisplay.showSelection(this.entityID, Entities.getEntityProperties(this.entityID));
|
||||
|
||||
var indicesToRemove = [];
|
||||
for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) {
|
||||
|
@ -2342,7 +2336,6 @@ function moveEntities() {
|
|||
|
||||
|
||||
});
|
||||
selectionDisplay.showSelection(leftController.entityID, Entities.getEntityProperties(leftController.entityID));
|
||||
leftController.oldModelPosition = newPosition;
|
||||
leftController.oldModelRotation = rotation;
|
||||
leftController.oldModelHalfDiagonal *= ratio;
|
||||
|
@ -2572,7 +2565,6 @@ function mousePressEvent(event) {
|
|||
print("Clicked on " + selectedEntityID.id + " " + entitySelected);
|
||||
tooltip.updateText(selectedEntityProperties);
|
||||
tooltip.show(true);
|
||||
selectionDisplay.showSelection(selectedEntityID, selectedEntityProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2591,7 +2583,6 @@ function mouseMoveEvent(event) {
|
|||
if (entityIntersection.accurate) {
|
||||
if(glowedEntityID.isKnownID && glowedEntityID.id != entityIntersection.entityID.id) {
|
||||
Entities.editEntity(glowedEntityID, { glowLevel: 0.0 });
|
||||
selectionDisplay.hideSelection(glowedEntityID);
|
||||
glowedEntityID.id = -1;
|
||||
glowedEntityID.isKnownID = false;
|
||||
}
|
||||
|
@ -2609,7 +2600,6 @@ function mouseMoveEvent(event) {
|
|||
Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 });
|
||||
}
|
||||
glowedEntityID = entityIntersection.entityID;
|
||||
selectionDisplay.showSelection(entityIntersection.entityID, entityIntersection.properties);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2732,7 +2722,6 @@ function mouseMoveEvent(event) {
|
|||
|
||||
Entities.editEntity(selectedEntityID, selectedEntityProperties);
|
||||
tooltip.updateText(selectedEntityProperties);
|
||||
selectionDisplay.showSelection(selectedEntityID, selectedEntityProperties);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2807,7 +2796,6 @@ function scriptEnding() {
|
|||
cleanupModelMenus();
|
||||
tooltip.cleanup();
|
||||
modelImporter.cleanup();
|
||||
selectionDisplay.cleanup();
|
||||
if (exportMenu) {
|
||||
exportMenu.close();
|
||||
}
|
||||
|
@ -3037,7 +3025,6 @@ Controller.keyPressEvent.connect(function (event) {
|
|||
Entities.editEntity(selectedEntityID, selectedEntityProperties);
|
||||
tooltip.updateText(selectedEntityProperties);
|
||||
somethingChanged = true;
|
||||
selectionDisplay.showSelection(selectedEntityID, selectedEntityProperties);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3155,7 +3142,6 @@ Window.nonBlockingFormClosed.connect(function() {
|
|||
properties.color.blue = array[index++].value;
|
||||
}
|
||||
Entities.editEntity(editModelID, properties);
|
||||
selectionDisplay.showSelection(editModelID, propeties);
|
||||
}
|
||||
modelSelected = false;
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
Script.include("toolBars.js");
|
||||
Script.include("libraries/toolBars.js");
|
||||
|
||||
const LEFT_PALM = 0;
|
||||
const LEFT_TIP = 1;
|
||||
|
|
214
examples/libraries/ExportMenu.js
Normal file
214
examples/libraries/ExportMenu.js
Normal file
|
@ -0,0 +1,214 @@
|
|||
var ExportMenu = function (opts) {
|
||||
var self = this;
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var pos = { x: windowDimensions.x / 2, y: windowDimensions.y - 100 };
|
||||
|
||||
this._onClose = opts.onClose || function () { };
|
||||
this._position = { x: 0.0, y: 0.0, z: 0.0 };
|
||||
this._scale = 1.0;
|
||||
|
||||
var minScale = 1;
|
||||
var maxScale = 32768;
|
||||
var titleWidth = 120;
|
||||
var locationWidth = 100;
|
||||
var scaleWidth = 144;
|
||||
var exportWidth = 100;
|
||||
var cancelWidth = 100;
|
||||
var margin = 4;
|
||||
var height = 30;
|
||||
var outerHeight = height + (2 * margin);
|
||||
var buttonColor = { red: 128, green: 128, blue: 128 };
|
||||
|
||||
var SCALE_MINUS = scaleWidth * 40.0 / 100.0;
|
||||
var SCALE_PLUS = scaleWidth * 63.0 / 100.0;
|
||||
|
||||
var fullWidth = locationWidth + scaleWidth + exportWidth + cancelWidth + (2 * margin);
|
||||
var offset = fullWidth / 2;
|
||||
pos.x -= offset;
|
||||
|
||||
var background = Overlays.addOverlay("text", {
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
opacity: 1,
|
||||
width: fullWidth,
|
||||
height: outerHeight,
|
||||
backgroundColor: { red: 200, green: 200, blue: 200 },
|
||||
text: "",
|
||||
});
|
||||
|
||||
var titleText = Overlays.addOverlay("text", {
|
||||
x: pos.x,
|
||||
y: pos.y - height,
|
||||
font: { size: 14 },
|
||||
width: titleWidth,
|
||||
height: height,
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
text: "Export Models"
|
||||
});
|
||||
|
||||
var locationButton = Overlays.addOverlay("text", {
|
||||
x: pos.x + margin,
|
||||
y: pos.y + margin,
|
||||
width: locationWidth,
|
||||
height: height,
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
text: "0, 0, 0",
|
||||
});
|
||||
var scaleOverlay = Overlays.addOverlay("image", {
|
||||
x: pos.x + margin + locationWidth,
|
||||
y: pos.y + margin,
|
||||
width: scaleWidth,
|
||||
height: height,
|
||||
subImage: { x: 0, y: 3, width: 144, height: height },
|
||||
imageURL: toolIconUrl + "voxel-size-selector.svg",
|
||||
alpha: 0.9,
|
||||
});
|
||||
var scaleViewWidth = 40;
|
||||
var scaleView = Overlays.addOverlay("text", {
|
||||
x: pos.x + margin + locationWidth + SCALE_MINUS,
|
||||
y: pos.y + margin,
|
||||
width: scaleViewWidth,
|
||||
height: height,
|
||||
alpha: 0.0,
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
text: "1"
|
||||
});
|
||||
var exportButton = Overlays.addOverlay("text", {
|
||||
x: pos.x + margin + locationWidth + scaleWidth,
|
||||
y: pos.y + margin,
|
||||
width: exportWidth,
|
||||
height: height,
|
||||
color: { red: 0, green: 255, blue: 255 },
|
||||
text: "Export"
|
||||
});
|
||||
var cancelButton = Overlays.addOverlay("text", {
|
||||
x: pos.x + margin + locationWidth + scaleWidth + exportWidth,
|
||||
y: pos.y + margin,
|
||||
width: cancelWidth,
|
||||
height: height,
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
text: "Cancel"
|
||||
});
|
||||
|
||||
var voxelPreview = Overlays.addOverlay("cube", {
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
size: this._scale,
|
||||
color: { red: 255, green: 255, blue: 0 },
|
||||
alpha: 1,
|
||||
solid: false,
|
||||
visible: true,
|
||||
lineWidth: 4
|
||||
});
|
||||
|
||||
this.parsePosition = function (str) {
|
||||
var parts = str.split(',');
|
||||
if (parts.length == 3) {
|
||||
var x = parseFloat(parts[0]);
|
||||
var y = parseFloat(parts[1]);
|
||||
var z = parseFloat(parts[2]);
|
||||
if (isFinite(x) && isFinite(y) && isFinite(z)) {
|
||||
return { x: x, y: y, z: z };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.showPositionPrompt = function () {
|
||||
var positionStr = self._position.x + ", " + self._position.y + ", " + self._position.z;
|
||||
while (1) {
|
||||
positionStr = Window.prompt("Position to export form:", positionStr);
|
||||
if (positionStr == null) {
|
||||
break;
|
||||
}
|
||||
var position = self.parsePosition(positionStr);
|
||||
if (position != null) {
|
||||
self.setPosition(position.x, position.y, position.z);
|
||||
break;
|
||||
}
|
||||
Window.alert("The position you entered was invalid.");
|
||||
}
|
||||
};
|
||||
|
||||
this.setScale = function (scale) {
|
||||
self._scale = Math.min(maxScale, Math.max(minScale, scale));
|
||||
Overlays.editOverlay(scaleView, { text: self._scale });
|
||||
Overlays.editOverlay(voxelPreview, { size: self._scale });
|
||||
}
|
||||
|
||||
this.decreaseScale = function () {
|
||||
self.setScale(self._scale /= 2);
|
||||
}
|
||||
|
||||
this.increaseScale = function () {
|
||||
self.setScale(self._scale *= 2);
|
||||
}
|
||||
|
||||
this.exportEntities = function() {
|
||||
var x = self._position.x;
|
||||
var y = self._position.y;
|
||||
var z = self._position.z;
|
||||
var s = self._scale;
|
||||
var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo";
|
||||
filename = Window.save("Select where to save", filename, "*.svo")
|
||||
if (filename) {
|
||||
var success = Clipboard.exportEntities(filename, x, y, z, s);
|
||||
if (!success) {
|
||||
Window.alert("Export failed: no models found in selected area.");
|
||||
}
|
||||
}
|
||||
self.close();
|
||||
};
|
||||
|
||||
this.getPosition = function () {
|
||||
return self._position;
|
||||
};
|
||||
|
||||
this.setPosition = function (x, y, z) {
|
||||
self._position = { x: x, y: y, z: z };
|
||||
var positionStr = x + ", " + y + ", " + z;
|
||||
Overlays.editOverlay(locationButton, { text: positionStr });
|
||||
Overlays.editOverlay(voxelPreview, { position: self._position });
|
||||
|
||||
};
|
||||
|
||||
this.mouseReleaseEvent = function (event) {
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
||||
|
||||
if (clickedOverlay == locationButton) {
|
||||
self.showPositionPrompt();
|
||||
} else if (clickedOverlay == exportButton) {
|
||||
self.exportEntities();
|
||||
} else if (clickedOverlay == cancelButton) {
|
||||
self.close();
|
||||
} else if (clickedOverlay == scaleOverlay) {
|
||||
var x = event.x - pos.x - margin - locationWidth;
|
||||
print(x);
|
||||
if (x < SCALE_MINUS) {
|
||||
self.decreaseScale();
|
||||
} else if (x > SCALE_PLUS) {
|
||||
self.increaseScale();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.close = function () {
|
||||
this.cleanup();
|
||||
this._onClose();
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
Overlays.deleteOverlay(background);
|
||||
Overlays.deleteOverlay(titleText);
|
||||
Overlays.deleteOverlay(locationButton);
|
||||
Overlays.deleteOverlay(exportButton);
|
||||
Overlays.deleteOverlay(cancelButton);
|
||||
Overlays.deleteOverlay(voxelPreview);
|
||||
Overlays.deleteOverlay(scaleOverlay);
|
||||
Overlays.deleteOverlay(scaleView);
|
||||
};
|
||||
|
||||
print("CONNECTING!");
|
||||
Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent);
|
||||
};
|
189
examples/libraries/ModelImporter.js
Normal file
189
examples/libraries/ModelImporter.js
Normal file
|
@ -0,0 +1,189 @@
|
|||
ModelImporter = function (opts) {
|
||||
var self = this;
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
|
||||
var height = 30;
|
||||
var margin = 4;
|
||||
var outerHeight = height + (2 * margin);
|
||||
var titleWidth = 120;
|
||||
var cancelWidth = 100;
|
||||
var fullWidth = titleWidth + cancelWidth + (2 * margin);
|
||||
|
||||
var localModels = Overlays.addOverlay("localmodels", {
|
||||
position: { x: 1, y: 1, z: 1 },
|
||||
scale: 1,
|
||||
visible: false
|
||||
});
|
||||
var importScale = 1;
|
||||
var importBoundaries = Overlays.addOverlay("cube", {
|
||||
position: { x: 0, y: 0, z: 0 },
|
||||
size: 1,
|
||||
color: { red: 128, blue: 128, green: 128 },
|
||||
lineWidth: 4,
|
||||
solid: false,
|
||||
visible: false
|
||||
});
|
||||
|
||||
var pos = { x: windowDimensions.x / 2 - (fullWidth / 2), y: windowDimensions.y - 100 };
|
||||
|
||||
var background = Overlays.addOverlay("text", {
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
opacity: 1,
|
||||
width: fullWidth,
|
||||
height: outerHeight,
|
||||
backgroundColor: { red: 200, green: 200, blue: 200 },
|
||||
visible: false,
|
||||
text: "",
|
||||
});
|
||||
|
||||
var titleText = Overlays.addOverlay("text", {
|
||||
x: pos.x + margin,
|
||||
y: pos.y + margin,
|
||||
font: { size: 14 },
|
||||
width: titleWidth,
|
||||
height: height,
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
visible: false,
|
||||
text: "Import Models"
|
||||
});
|
||||
var cancelButton = Overlays.addOverlay("text", {
|
||||
x: pos.x + margin + titleWidth,
|
||||
y: pos.y + margin,
|
||||
width: cancelWidth,
|
||||
height: height,
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
visible: false,
|
||||
text: "Close"
|
||||
});
|
||||
this._importing = false;
|
||||
|
||||
this.setImportVisible = function (visible) {
|
||||
Overlays.editOverlay(importBoundaries, { visible: visible });
|
||||
Overlays.editOverlay(localModels, { visible: visible });
|
||||
Overlays.editOverlay(cancelButton, { visible: visible });
|
||||
Overlays.editOverlay(titleText, { visible: visible });
|
||||
Overlays.editOverlay(background, { visible: visible });
|
||||
};
|
||||
|
||||
var importPosition = { x: 0, y: 0, z: 0 };
|
||||
this.moveImport = function (position) {
|
||||
importPosition = position;
|
||||
Overlays.editOverlay(localModels, {
|
||||
position: { x: importPosition.x, y: importPosition.y, z: importPosition.z }
|
||||
});
|
||||
Overlays.editOverlay(importBoundaries, {
|
||||
position: { x: importPosition.x, y: importPosition.y, z: importPosition.z }
|
||||
});
|
||||
}
|
||||
|
||||
this.mouseMoveEvent = function (event) {
|
||||
if (self._importing) {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
|
||||
var distance = 2;// * self._scale;
|
||||
|
||||
if (false) {//intersection.intersects) {
|
||||
var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection));
|
||||
if (intersectionDistance < distance) {
|
||||
distance = intersectionDistance * 0.99;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var targetPosition = {
|
||||
x: pickRay.origin.x + (pickRay.direction.x * distance),
|
||||
y: pickRay.origin.y + (pickRay.direction.y * distance),
|
||||
z: pickRay.origin.z + (pickRay.direction.z * distance)
|
||||
};
|
||||
|
||||
if (targetPosition.x < 0) targetPosition.x = 0;
|
||||
if (targetPosition.y < 0) targetPosition.y = 0;
|
||||
if (targetPosition.z < 0) targetPosition.z = 0;
|
||||
|
||||
var nudgeFactor = 1;
|
||||
var newPosition = {
|
||||
x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor,
|
||||
y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor,
|
||||
z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor
|
||||
}
|
||||
|
||||
self.moveImport(newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
this.mouseReleaseEvent = function (event) {
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
||||
|
||||
if (clickedOverlay == cancelButton) {
|
||||
self._importing = false;
|
||||
self.setImportVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Would prefer to use {4} for the coords, but it would only capture the last digit.
|
||||
var fileRegex = /__(.+)__(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)__/;
|
||||
this.doImport = function () {
|
||||
if (!self._importing) {
|
||||
var filename = Window.browse("Select models to import", "", "*.svo")
|
||||
if (filename) {
|
||||
parts = fileRegex.exec(filename);
|
||||
if (parts == null) {
|
||||
Window.alert("The file you selected does not contain source domain or location information");
|
||||
} else {
|
||||
var hostname = parts[1];
|
||||
var x = parts[2];
|
||||
var y = parts[3];
|
||||
var z = parts[4];
|
||||
var s = parts[5];
|
||||
importScale = s;
|
||||
if (hostname != location.hostname) {
|
||||
if (!Window.confirm(("These models were not originally exported from this domain. Continue?"))) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (Window.confirm(("Would you like to import back to the source location?"))) {
|
||||
var success = Clipboard.importEntities(filename);
|
||||
if (success) {
|
||||
Clipboard.pasteEntities(x, y, z, 1);
|
||||
} else {
|
||||
Window.alert("There was an error importing the entity file.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
var success = Clipboard.importEntities(filename);
|
||||
if (success) {
|
||||
self._importing = true;
|
||||
self.setImportVisible(true);
|
||||
Overlays.editOverlay(importBoundaries, { size: s });
|
||||
} else {
|
||||
Window.alert("There was an error importing the entity file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.paste = function () {
|
||||
if (self._importing) {
|
||||
// self._importing = false;
|
||||
// self.setImportVisible(false);
|
||||
Clipboard.pasteEntities(importPosition.x, importPosition.y, importPosition.z, 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.cleanup = function () {
|
||||
Overlays.deleteOverlay(localModels);
|
||||
Overlays.deleteOverlay(importBoundaries);
|
||||
Overlays.deleteOverlay(cancelButton);
|
||||
Overlays.deleteOverlay(titleText);
|
||||
Overlays.deleteOverlay(background);
|
||||
}
|
||||
|
||||
Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent);
|
||||
Controller.mouseMoveEvent.connect(this.mouseMoveEvent);
|
||||
};
|
71
examples/libraries/ToolTip.js
Normal file
71
examples/libraries/ToolTip.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
function Tooltip() {
|
||||
this.x = 285;
|
||||
this.y = 115;
|
||||
this.width = 500;
|
||||
this.height = 180; // 145;
|
||||
this.margin = 5;
|
||||
this.decimals = 3;
|
||||
|
||||
this.textOverlay = Overlays.addOverlay("text", {
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
margin: this.margin,
|
||||
text: "",
|
||||
color: { red: 128, green: 128, blue: 128 },
|
||||
alpha: 0.2,
|
||||
visible: false
|
||||
});
|
||||
this.show = function (doShow) {
|
||||
Overlays.editOverlay(this.textOverlay, { visible: doShow });
|
||||
}
|
||||
this.updateText = function(properties) {
|
||||
var angles = Quat.safeEulerAngles(properties.rotation);
|
||||
var text = "Entity Properties:\n"
|
||||
text += "type: " + properties.type + "\n"
|
||||
text += "X: " + properties.position.x.toFixed(this.decimals) + "\n"
|
||||
text += "Y: " + properties.position.y.toFixed(this.decimals) + "\n"
|
||||
text += "Z: " + properties.position.z.toFixed(this.decimals) + "\n"
|
||||
text += "Pitch: " + angles.x.toFixed(this.decimals) + "\n"
|
||||
text += "Yaw: " + angles.y.toFixed(this.decimals) + "\n"
|
||||
text += "Roll: " + angles.z.toFixed(this.decimals) + "\n"
|
||||
text += "Dimensions: " + properties.dimensions.x.toFixed(this.decimals) + ", "
|
||||
+ properties.dimensions.y.toFixed(this.decimals) + ", "
|
||||
+ properties.dimensions.z.toFixed(this.decimals) + "\n";
|
||||
|
||||
text += "Natural Dimensions: " + properties.naturalDimensions.x.toFixed(this.decimals) + ", "
|
||||
+ properties.naturalDimensions.y.toFixed(this.decimals) + ", "
|
||||
+ properties.naturalDimensions.z.toFixed(this.decimals) + "\n";
|
||||
|
||||
text += "ID: " + properties.id + "\n"
|
||||
if (properties.type == "Model") {
|
||||
text += "Model URL: " + properties.modelURL + "\n"
|
||||
text += "Animation URL: " + properties.animationURL + "\n"
|
||||
text += "Animation is playing: " + properties.animationIsPlaying + "\n"
|
||||
if (properties.sittingPoints && properties.sittingPoints.length > 0) {
|
||||
text += properties.sittingPoints.length + " Sitting points: "
|
||||
for (var i = 0; i < properties.sittingPoints.length; ++i) {
|
||||
text += properties.sittingPoints[i].name + " "
|
||||
}
|
||||
} else {
|
||||
text += "No sitting points" + "\n"
|
||||
}
|
||||
}
|
||||
if (properties.lifetime > -1) {
|
||||
text += "Lifetime: " + properties.lifetime + "\n"
|
||||
}
|
||||
text += "Age: " + properties.ageAsText + "\n"
|
||||
text += "Mass: " + properties.mass + "\n"
|
||||
text += "Script: " + properties.script + "\n"
|
||||
|
||||
|
||||
Overlays.editOverlay(this.textOverlay, { text: text });
|
||||
}
|
||||
|
||||
this.cleanup = function () {
|
||||
Overlays.deleteOverlay(this.textOverlay);
|
||||
}
|
||||
}
|
||||
|
||||
tooltip = new Tooltip();
|
52
examples/libraries/dataViewHelpers.js
Normal file
52
examples/libraries/dataViewHelpers.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
if (typeof DataView.prototype.indexOf !== "function") {
|
||||
DataView.prototype.indexOf = function (searchString, position) {
|
||||
var searchLength = searchString.length,
|
||||
byteArrayLength = this.byteLength,
|
||||
maxSearchIndex = byteArrayLength - searchLength,
|
||||
searchCharCodes = [],
|
||||
found,
|
||||
i,
|
||||
j;
|
||||
|
||||
searchCharCodes[searchLength] = 0;
|
||||
for (j = 0; j < searchLength; j += 1) {
|
||||
searchCharCodes[j] = searchString.charCodeAt(j);
|
||||
}
|
||||
|
||||
i = position;
|
||||
found = false;
|
||||
while (i < maxSearchIndex && !found) {
|
||||
j = 0;
|
||||
while (j < searchLength && this.getUint8(i + j) === searchCharCodes[j]) {
|
||||
j += 1;
|
||||
}
|
||||
found = (j === searchLength);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return found ? i - 1 : -1;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof DataView.prototype.string !== "function") {
|
||||
DataView.prototype.string = function (start, length) {
|
||||
var charCodes = [],
|
||||
end,
|
||||
i;
|
||||
|
||||
if (start === undefined) {
|
||||
start = 0;
|
||||
}
|
||||
if (length === undefined) {
|
||||
length = this.length;
|
||||
}
|
||||
|
||||
end = start + length;
|
||||
for (i = start; i < end; i += 1) {
|
||||
charCodes.push(this.getUint8(i));
|
||||
}
|
||||
|
||||
return String.fromCharCode.apply(String, charCodes);
|
||||
};
|
||||
}
|
||||
|
255
examples/libraries/entityPropertyDialogBox.js
Normal file
255
examples/libraries/entityPropertyDialogBox.js
Normal file
|
@ -0,0 +1,255 @@
|
|||
//
|
||||
// entityPropertyDialogBox.js
|
||||
// examples
|
||||
//
|
||||
// Created by Brad hefta-Gaub on 10/1/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This script implements a class useful for building tools for editing entities.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
EntityPropertyDialogBox = (function () {
|
||||
var that = {};
|
||||
|
||||
var propertiesForEditedEntity;
|
||||
var editEntityFormArray;
|
||||
var decimals = 3;
|
||||
var dimensionX;
|
||||
var dimensionY;
|
||||
var dimensionZ;
|
||||
var rescalePercentage;
|
||||
var editModelID = -1;
|
||||
|
||||
that.cleanup = function () {
|
||||
};
|
||||
|
||||
that.openDialog = function (entityID) {
|
||||
print(" Edit Properties.... about to edit properties...");
|
||||
|
||||
editModelID = entityID;
|
||||
propertiesForEditedEntity = Entities.getEntityProperties(editModelID);
|
||||
var properties = propertiesForEditedEntity;
|
||||
|
||||
var array = new Array();
|
||||
var index = 0;
|
||||
if (properties.type == "Model") {
|
||||
array.push({ label: "Model URL:", value: properties.modelURL });
|
||||
index++;
|
||||
array.push({ label: "Animation URL:", value: properties.animationURL });
|
||||
index++;
|
||||
array.push({ label: "Animation is playing:", value: properties.animationIsPlaying });
|
||||
index++;
|
||||
array.push({ label: "Animation FPS:", value: properties.animationFPS });
|
||||
index++;
|
||||
array.push({ label: "Animation Frame:", value: properties.animationFrameIndex });
|
||||
index++;
|
||||
}
|
||||
array.push({ label: "Position:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "X:", value: properties.position.x.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Y:", value: properties.position.y.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Z:", value: properties.position.z.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Registration X:", value: properties.registrationPoint.x.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Registration Y:", value: properties.registrationPoint.y.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Registration Z:", value: properties.registrationPoint.z.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Rotation:", type: "header" });
|
||||
index++;
|
||||
var angles = Quat.safeEulerAngles(properties.rotation);
|
||||
array.push({ label: "Pitch:", value: angles.x.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Yaw:", value: angles.y.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Roll:", value: angles.z.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Dimensions:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Width:", value: properties.dimensions.x.toFixed(decimals) });
|
||||
dimensionX = index;
|
||||
index++;
|
||||
array.push({ label: "Height:", value: properties.dimensions.y.toFixed(decimals) });
|
||||
dimensionY = index;
|
||||
index++;
|
||||
array.push({ label: "Depth:", value: properties.dimensions.z.toFixed(decimals) });
|
||||
dimensionZ = index;
|
||||
index++;
|
||||
array.push({ label: "", type: "inlineButton", buttonLabel: "Reset to Natural Dimensions", name: "resetDimensions" });
|
||||
index++;
|
||||
array.push({ label: "Rescale Percentage:", value: 100 });
|
||||
rescalePercentage = index;
|
||||
index++;
|
||||
array.push({ label: "", type: "inlineButton", buttonLabel: "Rescale", name: "rescaleDimensions" });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Velocity:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Linear X:", value: properties.velocity.x.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Linear Y:", value: properties.velocity.y.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Linear Z:", value: properties.velocity.z.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Linear Damping:", value: properties.damping.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Angular Pitch:", value: properties.angularVelocity.x.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Angular Yaw:", value: properties.angularVelocity.y.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Angular Roll:", value: properties.angularVelocity.z.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Angular Damping:", value: properties.angularDamping.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Gravity X:", value: properties.gravity.x.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Gravity Y:", value: properties.gravity.y.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Gravity Z:", value: properties.gravity.z.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Collisions:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Mass:", value: properties.mass.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Ignore for Collisions:", value: properties.ignoreForCollisions });
|
||||
index++;
|
||||
array.push({ label: "Collisions Will Move:", value: properties.collisionsWillMove });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Visible:", value: properties.visible });
|
||||
index++;
|
||||
|
||||
if (properties.type == "Box" || properties.type == "Sphere") {
|
||||
array.push({ label: "Color:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Red:", value: properties.color.red });
|
||||
index++;
|
||||
array.push({ label: "Green:", value: properties.color.green });
|
||||
index++;
|
||||
array.push({ label: "Blue:", value: properties.color.blue });
|
||||
index++;
|
||||
}
|
||||
array.push({ button: "Cancel" });
|
||||
index++;
|
||||
|
||||
editEntityFormArray = array;
|
||||
Window.nonBlockingForm("Edit Properties", array);
|
||||
};
|
||||
|
||||
Window.inlineButtonClicked.connect(function (name) {
|
||||
if (name == "resetDimensions") {
|
||||
Window.reloadNonBlockingForm([
|
||||
{ value: propertiesForEditedEntity.naturalDimensions.x.toFixed(decimals), oldIndex: dimensionX },
|
||||
{ value: propertiesForEditedEntity.naturalDimensions.y.toFixed(decimals), oldIndex: dimensionY },
|
||||
{ value: propertiesForEditedEntity.naturalDimensions.z.toFixed(decimals), oldIndex: dimensionZ }
|
||||
]);
|
||||
}
|
||||
|
||||
if (name == "rescaleDimensions") {
|
||||
var peekValues = editEntityFormArray;
|
||||
Window.peekNonBlockingFormResult(peekValues);
|
||||
var peekX = peekValues[dimensionX].value;
|
||||
var peekY = peekValues[dimensionY].value;
|
||||
var peekZ = peekValues[dimensionZ].value;
|
||||
var peekRescale = peekValues[rescalePercentage].value;
|
||||
var rescaledX = peekX * peekRescale / 100.0;
|
||||
var rescaledY = peekY * peekRescale / 100.0;
|
||||
var rescaledZ = peekZ * peekRescale / 100.0;
|
||||
|
||||
Window.reloadNonBlockingForm([
|
||||
{ value: rescaledX.toFixed(decimals), oldIndex: dimensionX },
|
||||
{ value: rescaledY.toFixed(decimals), oldIndex: dimensionY },
|
||||
{ value: rescaledZ.toFixed(decimals), oldIndex: dimensionZ },
|
||||
{ value: 100, oldIndex: rescalePercentage }
|
||||
]);
|
||||
}
|
||||
|
||||
});
|
||||
Window.nonBlockingFormClosed.connect(function() {
|
||||
array = editEntityFormArray;
|
||||
if (Window.getNonBlockingFormResult(array)) {
|
||||
var properties = propertiesForEditedEntity;
|
||||
var index = 0;
|
||||
if (properties.type == "Model") {
|
||||
properties.modelURL = array[index++].value;
|
||||
properties.animationURL = array[index++].value;
|
||||
properties.animationIsPlaying = array[index++].value;
|
||||
properties.animationFPS = array[index++].value;
|
||||
properties.animationFrameIndex = array[index++].value;
|
||||
}
|
||||
index++; // skip header
|
||||
properties.position.x = array[index++].value;
|
||||
properties.position.y = array[index++].value;
|
||||
properties.position.z = array[index++].value;
|
||||
properties.registrationPoint.x = array[index++].value;
|
||||
properties.registrationPoint.y = array[index++].value;
|
||||
properties.registrationPoint.z = array[index++].value;
|
||||
|
||||
index++; // skip header
|
||||
var angles = Quat.safeEulerAngles(properties.rotation);
|
||||
angles.x = array[index++].value;
|
||||
angles.y = array[index++].value;
|
||||
angles.z = array[index++].value;
|
||||
properties.rotation = Quat.fromVec3Degrees(angles);
|
||||
|
||||
index++; // skip header
|
||||
properties.dimensions.x = array[index++].value;
|
||||
properties.dimensions.y = array[index++].value;
|
||||
properties.dimensions.z = array[index++].value;
|
||||
index++; // skip reset button
|
||||
index++; // skip rescale percentage
|
||||
index++; // skip rescale button
|
||||
|
||||
index++; // skip header
|
||||
properties.velocity.x = array[index++].value;
|
||||
properties.velocity.y = array[index++].value;
|
||||
properties.velocity.z = array[index++].value;
|
||||
properties.damping = array[index++].value;
|
||||
|
||||
properties.angularVelocity.x = array[index++].value;
|
||||
properties.angularVelocity.y = array[index++].value;
|
||||
properties.angularVelocity.z = array[index++].value;
|
||||
properties.angularDamping = array[index++].value;
|
||||
|
||||
properties.gravity.x = array[index++].value;
|
||||
properties.gravity.y = array[index++].value;
|
||||
properties.gravity.z = array[index++].value;
|
||||
|
||||
index++; // skip header
|
||||
properties.mass = array[index++].value;
|
||||
properties.ignoreForCollisions = array[index++].value;
|
||||
properties.collisionsWillMove = array[index++].value;
|
||||
|
||||
properties.lifetime = array[index++].value;
|
||||
properties.visible = array[index++].value;
|
||||
|
||||
if (properties.type == "Box" || properties.type == "Sphere") {
|
||||
index++; // skip header
|
||||
properties.color.red = array[index++].value;
|
||||
properties.color.green = array[index++].value;
|
||||
properties.color.blue = array[index++].value;
|
||||
}
|
||||
Entities.editEntity(editModelID, properties);
|
||||
selectionDisplay.highlightSelectable(editModelID, propeties);
|
||||
}
|
||||
modelSelected = false;
|
||||
});
|
||||
|
||||
return that;
|
||||
|
||||
}());
|
||||
|
108
examples/libraries/httpMultiPart.js
Normal file
108
examples/libraries/httpMultiPart.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
httpMultiPart = (function () {
|
||||
var that = {},
|
||||
parts,
|
||||
byteLength,
|
||||
boundaryString,
|
||||
crlf;
|
||||
|
||||
function clear() {
|
||||
boundaryString = "--boundary_" + String(Uuid.generate()).slice(1, 36) + "=";
|
||||
parts = [];
|
||||
byteLength = 0;
|
||||
crlf = "";
|
||||
}
|
||||
that.clear = clear;
|
||||
|
||||
function boundary() {
|
||||
return boundaryString.slice(2);
|
||||
}
|
||||
that.boundary = boundary;
|
||||
|
||||
function length() {
|
||||
return byteLength;
|
||||
}
|
||||
that.length = length;
|
||||
|
||||
function add(object) {
|
||||
// - name, string
|
||||
// - name, buffer
|
||||
var buffer,
|
||||
string,
|
||||
stringBuffer,
|
||||
compressedBuffer;
|
||||
|
||||
if (object.name === undefined) {
|
||||
|
||||
throw new Error("Item to add to HttpMultiPart must have a name");
|
||||
|
||||
} else if (object.string !== undefined) {
|
||||
//--<boundary>=
|
||||
//Content-Disposition: form-data; name="model_name"
|
||||
//
|
||||
//<string>
|
||||
|
||||
string = crlf + boundaryString + "\r\n"
|
||||
+ "Content-Disposition: form-data; name=\"" + object.name + "\"\r\n"
|
||||
+ "\r\n"
|
||||
+ object.string;
|
||||
buffer = string.toArrayBuffer();
|
||||
|
||||
} else if (object.buffer !== undefined) {
|
||||
//--<boundary>=
|
||||
//Content-Disposition: form-data; name="fbx"; filename="<filename>"
|
||||
//Content-Type: application/octet-stream
|
||||
//
|
||||
//<buffer>
|
||||
|
||||
string = crlf + boundaryString + "\r\n"
|
||||
+ "Content-Disposition: form-data; name=\"" + object.name
|
||||
+ "\"; filename=\"" + object.buffer.filename + "\"\r\n"
|
||||
+ "Content-Type: application/octet-stream\r\n"
|
||||
+ "\r\n";
|
||||
stringBuffer = string.toArrayBuffer();
|
||||
|
||||
compressedBuffer = object.buffer.buffer.compress();
|
||||
buffer = new Uint8Array(stringBuffer.byteLength + compressedBuffer.byteLength);
|
||||
buffer.set(new Uint8Array(stringBuffer));
|
||||
buffer.set(new Uint8Array(compressedBuffer), stringBuffer.byteLength);
|
||||
|
||||
} else {
|
||||
|
||||
throw new Error("Item to add to HttpMultiPart not recognized");
|
||||
}
|
||||
|
||||
byteLength += buffer.byteLength;
|
||||
parts.push(buffer);
|
||||
|
||||
crlf = "\r\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
that.add = add;
|
||||
|
||||
function response() {
|
||||
var buffer,
|
||||
index,
|
||||
str,
|
||||
i;
|
||||
|
||||
str = crlf + boundaryString + "--\r\n";
|
||||
buffer = str.toArrayBuffer();
|
||||
byteLength += buffer.byteLength;
|
||||
parts.push(buffer);
|
||||
|
||||
buffer = new Uint8Array(byteLength);
|
||||
index = 0;
|
||||
for (i = 0; i < parts.length; i += 1) {
|
||||
buffer.set(new Uint8Array(parts[i]), index);
|
||||
index += parts[i].byteLength;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
that.response = response;
|
||||
|
||||
clear();
|
||||
|
||||
return that;
|
||||
}());
|
690
examples/libraries/modelUploader.js
Normal file
690
examples/libraries/modelUploader.js
Normal file
|
@ -0,0 +1,690 @@
|
|||
modelUploader = (function () {
|
||||
var that = {},
|
||||
modelFile,
|
||||
modelName,
|
||||
modelURL,
|
||||
modelCallback,
|
||||
isProcessing,
|
||||
fstBuffer,
|
||||
fbxBuffer,
|
||||
//svoBuffer,
|
||||
mapping,
|
||||
geometry,
|
||||
API_URL = "https://data.highfidelity.io/api/v1/models",
|
||||
MODEL_URL = "http://public.highfidelity.io/models/content",
|
||||
NAME_FIELD = "name",
|
||||
SCALE_FIELD = "scale",
|
||||
FILENAME_FIELD = "filename",
|
||||
TEXDIR_FIELD = "texdir",
|
||||
MAX_TEXTURE_SIZE = 1024;
|
||||
|
||||
function info(message) {
|
||||
if (progressDialog.isOpen()) {
|
||||
progressDialog.update(message);
|
||||
} else {
|
||||
progressDialog.open(message);
|
||||
}
|
||||
print(message);
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
if (progressDialog.isOpen()) {
|
||||
progressDialog.close();
|
||||
}
|
||||
print(message);
|
||||
Window.alert(message);
|
||||
}
|
||||
|
||||
function randomChar(length) {
|
||||
var characters = "0123457689abcdefghijklmnopqrstuvwxyz",
|
||||
string = "",
|
||||
i;
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
string += characters[Math.floor(Math.random() * 36)];
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
function resetDataObjects() {
|
||||
fstBuffer = null;
|
||||
fbxBuffer = null;
|
||||
//svoBuffer = null;
|
||||
mapping = {};
|
||||
geometry = {};
|
||||
geometry.textures = [];
|
||||
geometry.embedded = [];
|
||||
}
|
||||
|
||||
function readFile(filename) {
|
||||
var url = "file:///" + filename,
|
||||
req = new XMLHttpRequest();
|
||||
|
||||
req.open("GET", url, false);
|
||||
req.responseType = "arraybuffer";
|
||||
req.send();
|
||||
if (req.status !== 200) {
|
||||
error("Could not read file: " + filename + " : " + req.statusText);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
filename: filename.fileName(),
|
||||
buffer: req.response
|
||||
};
|
||||
}
|
||||
|
||||
function readMapping(buffer) {
|
||||
var dv = new DataView(buffer.buffer),
|
||||
lines,
|
||||
line,
|
||||
tokens,
|
||||
i,
|
||||
name,
|
||||
value,
|
||||
remainder,
|
||||
existing;
|
||||
|
||||
mapping = {}; // { name : value | name : { value : [remainder] } }
|
||||
lines = dv.string(0, dv.byteLength).split(/\r\n|\r|\n/);
|
||||
for (i = 0; i < lines.length; i += 1) {
|
||||
line = lines[i].trim();
|
||||
if (line.length > 0 && line[0] !== "#") {
|
||||
tokens = line.split(/\s*=\s*/);
|
||||
if (tokens.length > 1) {
|
||||
name = tokens[0];
|
||||
value = tokens[1];
|
||||
if (tokens.length > 2) {
|
||||
remainder = tokens.slice(2, tokens.length).join(" = ");
|
||||
} else {
|
||||
remainder = null;
|
||||
}
|
||||
if (tokens.length === 2 && mapping[name] === undefined) {
|
||||
mapping[name] = value;
|
||||
} else {
|
||||
if (mapping[name] === undefined) {
|
||||
mapping[name] = {};
|
||||
|
||||
} else if (typeof mapping[name] !== "object") {
|
||||
existing = mapping[name];
|
||||
mapping[name] = { existing : null };
|
||||
}
|
||||
|
||||
if (mapping[name][value] === undefined) {
|
||||
mapping[name][value] = [];
|
||||
}
|
||||
mapping[name][value].push(remainder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeMapping(buffer) {
|
||||
var name,
|
||||
value,
|
||||
remainder,
|
||||
i,
|
||||
string = "";
|
||||
|
||||
for (name in mapping) {
|
||||
if (mapping.hasOwnProperty(name)) {
|
||||
if (typeof mapping[name] === "object") {
|
||||
for (value in mapping[name]) {
|
||||
if (mapping[name].hasOwnProperty(value)) {
|
||||
remainder = mapping[name][value];
|
||||
if (remainder === null) {
|
||||
string += (name + " = " + value + "\n");
|
||||
} else {
|
||||
for (i = 0; i < remainder.length; i += 1) {
|
||||
string += (name + " = " + value + " = " + remainder[i] + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
string += (name + " = " + mapping[name] + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer.buffer = string.toArrayBuffer();
|
||||
}
|
||||
|
||||
function readGeometry(fbxBuffer) {
|
||||
var textures,
|
||||
view,
|
||||
index,
|
||||
EOF,
|
||||
previousNodeFilename;
|
||||
|
||||
// Reference:
|
||||
// http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/
|
||||
|
||||
textures = {};
|
||||
view = new DataView(fbxBuffer.buffer);
|
||||
EOF = false;
|
||||
|
||||
function parseBinaryFBX() {
|
||||
var endOffset,
|
||||
numProperties,
|
||||
propertyListLength,
|
||||
nameLength,
|
||||
name,
|
||||
filename;
|
||||
|
||||
endOffset = view.getUint32(index, true);
|
||||
numProperties = view.getUint32(index + 4, true);
|
||||
propertyListLength = view.getUint32(index + 8, true);
|
||||
nameLength = view.getUint8(index + 12);
|
||||
index += 13;
|
||||
|
||||
if (endOffset === 0) {
|
||||
return;
|
||||
}
|
||||
if (endOffset < index || endOffset > view.byteLength) {
|
||||
EOF = true;
|
||||
return;
|
||||
}
|
||||
|
||||
name = view.string(index, nameLength).toLowerCase();
|
||||
index += nameLength;
|
||||
|
||||
if (name === "content" && previousNodeFilename !== "") {
|
||||
// Blender 2.71 exporter "embeds" external textures as empty binary blobs so ignore these
|
||||
if (propertyListLength > 5) {
|
||||
geometry.embedded.push(previousNodeFilename);
|
||||
}
|
||||
}
|
||||
|
||||
if (name === "relativefilename") {
|
||||
filename = view.string(index + 5, view.getUint32(index + 1, true)).fileName();
|
||||
if (!textures.hasOwnProperty(filename)) {
|
||||
textures[filename] = "";
|
||||
geometry.textures.push(filename);
|
||||
}
|
||||
previousNodeFilename = filename;
|
||||
} else {
|
||||
previousNodeFilename = "";
|
||||
}
|
||||
|
||||
index += (propertyListLength);
|
||||
|
||||
while (index < endOffset && !EOF) {
|
||||
parseBinaryFBX();
|
||||
}
|
||||
}
|
||||
|
||||
function readTextFBX() {
|
||||
var line,
|
||||
view,
|
||||
viewLength,
|
||||
charCode,
|
||||
charCodes,
|
||||
numCharCodes,
|
||||
filename,
|
||||
relativeFilename = "",
|
||||
MAX_CHAR_CODES = 250;
|
||||
|
||||
view = new Uint8Array(fbxBuffer.buffer);
|
||||
viewLength = view.byteLength;
|
||||
charCodes = [];
|
||||
numCharCodes = 0;
|
||||
|
||||
for (index = 0; index < viewLength; index += 1) {
|
||||
charCode = view[index];
|
||||
if (charCode !== 9 && charCode !== 32) {
|
||||
if (charCode === 10) { // EOL. Can ignore EOF.
|
||||
line = String.fromCharCode.apply(String, charCodes).toLowerCase();
|
||||
// For embedded textures, "Content:" line immediately follows "RelativeFilename:" line.
|
||||
if (line.slice(0, 8) === "content:" && relativeFilename !== "") {
|
||||
geometry.embedded.push(relativeFilename);
|
||||
}
|
||||
if (line.slice(0, 17) === "relativefilename:") {
|
||||
filename = line.slice(line.indexOf("\""), line.lastIndexOf("\"") - line.length).fileName();
|
||||
if (!textures.hasOwnProperty(filename)) {
|
||||
textures[filename] = "";
|
||||
geometry.textures.push(filename);
|
||||
}
|
||||
relativeFilename = filename;
|
||||
} else {
|
||||
relativeFilename = "";
|
||||
}
|
||||
charCodes = [];
|
||||
numCharCodes = 0;
|
||||
} else {
|
||||
if (numCharCodes < MAX_CHAR_CODES) { // Only interested in start of line
|
||||
charCodes.push(charCode);
|
||||
numCharCodes += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (view.string(0, 18) === "Kaydara FBX Binary") {
|
||||
previousNodeFilename = "";
|
||||
|
||||
index = 27;
|
||||
while (index < view.byteLength - 39 && !EOF) {
|
||||
parseBinaryFBX();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
readTextFBX();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function readModel() {
|
||||
var fbxFilename,
|
||||
//svoFilename,
|
||||
fileType;
|
||||
|
||||
info("Reading model file");
|
||||
print("Model file: " + modelFile);
|
||||
|
||||
if (modelFile.toLowerCase().fileType() === "fst") {
|
||||
fstBuffer = readFile(modelFile);
|
||||
if (fstBuffer === null) {
|
||||
return false;
|
||||
}
|
||||
readMapping(fstBuffer);
|
||||
fileType = mapping[FILENAME_FIELD].toLowerCase().fileType();
|
||||
if (mapping.hasOwnProperty(FILENAME_FIELD)) {
|
||||
if (fileType === "fbx") {
|
||||
fbxFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD];
|
||||
//} else if (fileType === "svo") {
|
||||
// svoFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD];
|
||||
} else {
|
||||
error("Unrecognized model type in FST file!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
error("Model file name not found in FST file!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fstBuffer = {
|
||||
filename: "Interface." + randomChar(6), // Simulate avatar model uploading behaviour
|
||||
buffer: null
|
||||
};
|
||||
|
||||
if (modelFile.toLowerCase().fileType() === "fbx") {
|
||||
fbxFilename = modelFile;
|
||||
mapping[FILENAME_FIELD] = modelFile.fileName();
|
||||
|
||||
//} else if (modelFile.toLowerCase().fileType() === "svo") {
|
||||
// svoFilename = modelFile;
|
||||
// mapping[FILENAME_FIELD] = modelFile.fileName();
|
||||
|
||||
} else {
|
||||
error("Unrecognized file type: " + modelFile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isProcessing) { return false; }
|
||||
|
||||
if (fbxFilename) {
|
||||
fbxBuffer = readFile(fbxFilename);
|
||||
if (fbxBuffer === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isProcessing) { return false; }
|
||||
|
||||
readGeometry(fbxBuffer);
|
||||
}
|
||||
|
||||
//if (svoFilename) {
|
||||
// svoBuffer = readFile(svoFilename);
|
||||
// if (svoBuffer === null) {
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
// Add any missing basic mappings
|
||||
if (!mapping.hasOwnProperty(NAME_FIELD)) {
|
||||
mapping[NAME_FIELD] = modelFile.fileName().fileBase();
|
||||
}
|
||||
if (!mapping.hasOwnProperty(TEXDIR_FIELD)) {
|
||||
mapping[TEXDIR_FIELD] = ".";
|
||||
}
|
||||
if (!mapping.hasOwnProperty(SCALE_FIELD)) {
|
||||
mapping[SCALE_FIELD] = 1.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function setProperties() {
|
||||
var form = [],
|
||||
directory,
|
||||
displayAs,
|
||||
validateAs;
|
||||
|
||||
progressDialog.close();
|
||||
print("Setting model properties");
|
||||
|
||||
form.push({ label: "Name:", value: mapping[NAME_FIELD] });
|
||||
|
||||
directory = modelFile.path() + "/" + mapping[TEXDIR_FIELD];
|
||||
displayAs = new RegExp("^" + modelFile.path().regExpEscape() + "[\\\\\\\/](.*)");
|
||||
validateAs = new RegExp("^" + modelFile.path().regExpEscape() + "([\\\\\\\/].*)?");
|
||||
|
||||
form.push({
|
||||
label: "Texture directory:",
|
||||
directory: modelFile.path() + "/" + mapping[TEXDIR_FIELD],
|
||||
title: "Choose Texture Directory",
|
||||
displayAs: displayAs,
|
||||
validateAs: validateAs,
|
||||
errorMessage: "Texture directory must be subdirectory of the model directory."
|
||||
});
|
||||
|
||||
form.push({ button: "Cancel" });
|
||||
|
||||
if (!Window.form("Set Model Properties", form)) {
|
||||
print("User cancelled uploading model");
|
||||
return false;
|
||||
}
|
||||
|
||||
mapping[NAME_FIELD] = form[0].value;
|
||||
mapping[TEXDIR_FIELD] = form[1].directory.slice(modelFile.path().length + 1);
|
||||
if (mapping[TEXDIR_FIELD] === "") {
|
||||
mapping[TEXDIR_FIELD] = ".";
|
||||
}
|
||||
|
||||
writeMapping(fstBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function createHttpMessage(callback) {
|
||||
var multiparts = [],
|
||||
lodCount,
|
||||
lodFile,
|
||||
lodBuffer,
|
||||
textureBuffer,
|
||||
textureSourceFormat,
|
||||
textureTargetFormat,
|
||||
embeddedTextures,
|
||||
i;
|
||||
|
||||
info("Preparing to send model");
|
||||
|
||||
// Model name
|
||||
if (mapping.hasOwnProperty(NAME_FIELD)) {
|
||||
multiparts.push({
|
||||
name : "model_name",
|
||||
string : mapping[NAME_FIELD]
|
||||
});
|
||||
} else {
|
||||
error("Model name is missing");
|
||||
httpMultiPart.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// FST file
|
||||
if (fstBuffer) {
|
||||
multiparts.push({
|
||||
name : "fst",
|
||||
buffer: fstBuffer
|
||||
});
|
||||
}
|
||||
|
||||
// FBX file
|
||||
if (fbxBuffer) {
|
||||
multiparts.push({
|
||||
name : "fbx",
|
||||
buffer: fbxBuffer
|
||||
});
|
||||
}
|
||||
|
||||
// SVO file
|
||||
//if (svoBuffer) {
|
||||
// multiparts.push({
|
||||
// name : "svo",
|
||||
// buffer: svoBuffer
|
||||
// });
|
||||
//}
|
||||
|
||||
// LOD files
|
||||
lodCount = 0;
|
||||
for (lodFile in mapping.lod) {
|
||||
if (mapping.lod.hasOwnProperty(lodFile)) {
|
||||
lodBuffer = readFile(modelFile.path() + "\/" + lodFile);
|
||||
if (lodBuffer === null) {
|
||||
return;
|
||||
}
|
||||
multiparts.push({
|
||||
name: "lod" + lodCount,
|
||||
buffer: lodBuffer
|
||||
});
|
||||
lodCount += 1;
|
||||
}
|
||||
if (!isProcessing) { return; }
|
||||
}
|
||||
|
||||
// Textures
|
||||
embeddedTextures = "|" + geometry.embedded.join("|") + "|";
|
||||
for (i = 0; i < geometry.textures.length; i += 1) {
|
||||
if (embeddedTextures.indexOf("|" + geometry.textures[i].fileName() + "|") === -1) {
|
||||
textureBuffer = readFile(modelFile.path() + "\/"
|
||||
+ (mapping[TEXDIR_FIELD] !== "." ? mapping[TEXDIR_FIELD] + "\/" : "")
|
||||
+ geometry.textures[i]);
|
||||
if (textureBuffer === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
textureSourceFormat = geometry.textures[i].fileType().toLowerCase();
|
||||
textureTargetFormat = (textureSourceFormat === "jpg" ? "jpg" : "png");
|
||||
textureBuffer.buffer =
|
||||
textureBuffer.buffer.recodeImage(textureSourceFormat, textureTargetFormat, MAX_TEXTURE_SIZE);
|
||||
textureBuffer.filename = textureBuffer.filename.slice(0, -textureSourceFormat.length) + textureTargetFormat;
|
||||
|
||||
multiparts.push({
|
||||
name: "texture" + i,
|
||||
buffer: textureBuffer
|
||||
});
|
||||
}
|
||||
|
||||
if (!isProcessing) { return; }
|
||||
}
|
||||
|
||||
// Model category
|
||||
multiparts.push({
|
||||
name : "model_category",
|
||||
string : "content"
|
||||
});
|
||||
|
||||
// Create HTTP message
|
||||
httpMultiPart.clear();
|
||||
Script.setTimeout(function addMultipart() {
|
||||
var multipart = multiparts.shift();
|
||||
httpMultiPart.add(multipart);
|
||||
|
||||
if (!isProcessing) { return; }
|
||||
|
||||
if (multiparts.length > 0) {
|
||||
Script.setTimeout(addMultipart, 25);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}, 25);
|
||||
}
|
||||
|
||||
function sendToHighFidelity() {
|
||||
var req,
|
||||
uploadedChecks,
|
||||
HTTP_GET_TIMEOUT = 60, // 1 minute
|
||||
HTTP_SEND_TIMEOUT = 900, // 15 minutes
|
||||
UPLOADED_CHECKS = 30,
|
||||
CHECK_UPLOADED_TIMEOUT = 1, // 1 second
|
||||
handleCheckUploadedResponses,
|
||||
handleUploadModelResponses,
|
||||
handleRequestUploadResponses;
|
||||
|
||||
function uploadTimedOut() {
|
||||
error("Model upload failed: Internet request timed out!");
|
||||
}
|
||||
|
||||
function debugResponse() {
|
||||
print("req.errorCode = " + req.errorCode);
|
||||
print("req.readyState = " + req.readyState);
|
||||
print("req.status = " + req.status);
|
||||
print("req.statusText = " + req.statusText);
|
||||
print("req.responseType = " + req.responseType);
|
||||
print("req.responseText = " + req.responseText);
|
||||
print("req.response = " + req.response);
|
||||
print("req.getAllResponseHeaders() = " + req.getAllResponseHeaders());
|
||||
}
|
||||
|
||||
function checkUploaded() {
|
||||
if (!isProcessing) { return; }
|
||||
|
||||
info("Checking uploaded model");
|
||||
|
||||
req = new XMLHttpRequest();
|
||||
req.open("HEAD", modelURL, true);
|
||||
req.timeout = HTTP_GET_TIMEOUT * 1000;
|
||||
req.onreadystatechange = handleCheckUploadedResponses;
|
||||
req.ontimeout = uploadTimedOut;
|
||||
req.send();
|
||||
}
|
||||
|
||||
handleCheckUploadedResponses = function () {
|
||||
//debugResponse();
|
||||
if (req.readyState === req.DONE) {
|
||||
if (req.status === 200) {
|
||||
// Note: Unlike avatar models, for content models we don't need to refresh texture cache.
|
||||
print("Model uploaded: " + modelURL);
|
||||
progressDialog.close();
|
||||
if (Window.confirm("Your model has been uploaded as: " + modelURL + "\nDo you want to rez it?")) {
|
||||
modelCallback(modelURL);
|
||||
}
|
||||
} else if (req.status === 404) {
|
||||
if (uploadedChecks > 0) {
|
||||
uploadedChecks -= 1;
|
||||
Script.setTimeout(checkUploaded, CHECK_UPLOADED_TIMEOUT * 1000);
|
||||
} else {
|
||||
print("Error: " + req.status + " " + req.statusText);
|
||||
error("We could not verify that your model was successfully uploaded but it may have been at: "
|
||||
+ modelURL);
|
||||
}
|
||||
} else {
|
||||
print("Error: " + req.status + " " + req.statusText);
|
||||
error("There was a problem with your upload, please try again later.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function uploadModel(method) {
|
||||
var url;
|
||||
|
||||
if (!isProcessing) { return; }
|
||||
|
||||
req = new XMLHttpRequest();
|
||||
if (method === "PUT") {
|
||||
url = API_URL + "\/" + modelName;
|
||||
req.open("PUT", url, true); //print("PUT " + url);
|
||||
} else {
|
||||
url = API_URL;
|
||||
req.open("POST", url, true); //print("POST " + url);
|
||||
}
|
||||
req.setRequestHeader("Content-Type", "multipart/form-data; boundary=\"" + httpMultiPart.boundary() + "\"");
|
||||
req.timeout = HTTP_SEND_TIMEOUT * 1000;
|
||||
req.onreadystatechange = handleUploadModelResponses;
|
||||
req.ontimeout = uploadTimedOut;
|
||||
req.send(httpMultiPart.response().buffer);
|
||||
}
|
||||
|
||||
handleUploadModelResponses = function () {
|
||||
//debugResponse();
|
||||
if (req.readyState === req.DONE) {
|
||||
if (req.status === 200) {
|
||||
uploadedChecks = UPLOADED_CHECKS;
|
||||
checkUploaded();
|
||||
} else {
|
||||
print("Error: " + req.status + " " + req.statusText);
|
||||
error("There was a problem with your upload, please try again later.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function requestUpload() {
|
||||
var url;
|
||||
|
||||
if (!isProcessing) { return; }
|
||||
|
||||
url = API_URL + "\/" + modelName; // XMLHttpRequest automatically handles authorization of API requests.
|
||||
req = new XMLHttpRequest();
|
||||
req.open("GET", url, true); //print("GET " + url);
|
||||
req.responseType = "json";
|
||||
req.timeout = HTTP_GET_TIMEOUT * 1000;
|
||||
req.onreadystatechange = handleRequestUploadResponses;
|
||||
req.ontimeout = uploadTimedOut;
|
||||
req.send();
|
||||
}
|
||||
|
||||
handleRequestUploadResponses = function () {
|
||||
var response;
|
||||
|
||||
//debugResponse();
|
||||
if (req.readyState === req.DONE) {
|
||||
if (req.status === 200) {
|
||||
if (req.responseType === "json") {
|
||||
response = JSON.parse(req.responseText);
|
||||
if (response.status === "success") {
|
||||
if (response.exists === false) {
|
||||
uploadModel("POST");
|
||||
} else if (response.can_update === true) {
|
||||
uploadModel("PUT");
|
||||
} else {
|
||||
error("This model file already exists and is owned by someone else!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("Error: " + req.status + " " + req.statusText);
|
||||
}
|
||||
error("Model upload failed! Something went wrong at the data server.");
|
||||
}
|
||||
};
|
||||
|
||||
info("Sending model to High Fidelity");
|
||||
|
||||
requestUpload();
|
||||
}
|
||||
|
||||
that.upload = function (file, callback) {
|
||||
|
||||
modelFile = file;
|
||||
modelCallback = callback;
|
||||
|
||||
isProcessing = true;
|
||||
|
||||
progressDialog.onCancel = function () {
|
||||
print("User cancelled uploading model");
|
||||
isProcessing = false;
|
||||
};
|
||||
|
||||
resetDataObjects();
|
||||
|
||||
if (readModel()) {
|
||||
if (setProperties()) {
|
||||
modelName = mapping[NAME_FIELD];
|
||||
modelURL = MODEL_URL + "\/" + mapping[NAME_FIELD] + ".fst"; // All models are uploaded as an FST
|
||||
|
||||
createHttpMessage(sendToHighFidelity);
|
||||
}
|
||||
}
|
||||
|
||||
resetDataObjects();
|
||||
};
|
||||
|
||||
return that;
|
||||
}());
|
132
examples/libraries/progressDialog.js
Normal file
132
examples/libraries/progressDialog.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
progressDialog = (function () {
|
||||
var that = {},
|
||||
progressBackground,
|
||||
progressMessage,
|
||||
cancelButton,
|
||||
displayed = false,
|
||||
backgroundWidth = 300,
|
||||
backgroundHeight = 100,
|
||||
messageHeight = 32,
|
||||
cancelWidth = 70,
|
||||
cancelHeight = 32,
|
||||
textColor = { red: 255, green: 255, blue: 255 },
|
||||
textBackground = { red: 52, green: 52, blue: 52 },
|
||||
backgroundUrl = toolIconUrl + "progress-background.svg",
|
||||
windowDimensions;
|
||||
|
||||
progressBackground = Overlays.addOverlay("image", {
|
||||
width: backgroundWidth,
|
||||
height: backgroundHeight,
|
||||
imageURL: backgroundUrl,
|
||||
alpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
progressMessage = Overlays.addOverlay("text", {
|
||||
width: backgroundWidth - 40,
|
||||
height: messageHeight,
|
||||
text: "",
|
||||
textColor: textColor,
|
||||
backgroundColor: textBackground,
|
||||
alpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
cancelButton = Overlays.addOverlay("text", {
|
||||
width: cancelWidth,
|
||||
height: cancelHeight,
|
||||
text: "Cancel",
|
||||
textColor: textColor,
|
||||
backgroundColor: textBackground,
|
||||
alpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
function move() {
|
||||
var progressX,
|
||||
progressY;
|
||||
|
||||
if (displayed) {
|
||||
|
||||
if (windowDimensions.x === Window.innerWidth && windowDimensions.y === Window.innerHeight) {
|
||||
return;
|
||||
}
|
||||
windowDimensions.x = Window.innerWidth;
|
||||
windowDimensions.y = Window.innerHeight;
|
||||
|
||||
progressX = (windowDimensions.x - backgroundWidth) / 2; // Center.
|
||||
progressY = windowDimensions.y / 2 - backgroundHeight; // A little up from center.
|
||||
|
||||
Overlays.editOverlay(progressBackground, { x: progressX, y: progressY });
|
||||
Overlays.editOverlay(progressMessage, { x: progressX + 20, y: progressY + 15 });
|
||||
Overlays.editOverlay(cancelButton, {
|
||||
x: progressX + backgroundWidth - cancelWidth - 20,
|
||||
y: progressY + backgroundHeight - cancelHeight - 15
|
||||
});
|
||||
}
|
||||
}
|
||||
that.move = move;
|
||||
|
||||
that.onCancel = undefined;
|
||||
|
||||
function open(message) {
|
||||
if (!displayed) {
|
||||
windowDimensions = { x: 0, y : 0 };
|
||||
displayed = true;
|
||||
move();
|
||||
Overlays.editOverlay(progressBackground, { visible: true });
|
||||
Overlays.editOverlay(progressMessage, { visible: true, text: message });
|
||||
Overlays.editOverlay(cancelButton, { visible: true });
|
||||
} else {
|
||||
throw new Error("open() called on progressDialog when already open");
|
||||
}
|
||||
}
|
||||
that.open = open;
|
||||
|
||||
function isOpen() {
|
||||
return displayed;
|
||||
}
|
||||
that.isOpen = isOpen;
|
||||
|
||||
function update(message) {
|
||||
if (displayed) {
|
||||
Overlays.editOverlay(progressMessage, { text: message });
|
||||
} else {
|
||||
throw new Error("update() called on progressDialog when not open");
|
||||
}
|
||||
}
|
||||
that.update = update;
|
||||
|
||||
function close() {
|
||||
if (displayed) {
|
||||
Overlays.editOverlay(cancelButton, { visible: false });
|
||||
Overlays.editOverlay(progressMessage, { visible: false });
|
||||
Overlays.editOverlay(progressBackground, { visible: false });
|
||||
displayed = false;
|
||||
} else {
|
||||
throw new Error("close() called on progressDialog when not open");
|
||||
}
|
||||
}
|
||||
that.close = close;
|
||||
|
||||
function mousePressEvent(event) {
|
||||
if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === cancelButton) {
|
||||
if (typeof this.onCancel === "function") {
|
||||
close();
|
||||
this.onCancel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
that.mousePressEvent = mousePressEvent;
|
||||
|
||||
function cleanup() {
|
||||
Overlays.deleteOverlay(cancelButton);
|
||||
Overlays.deleteOverlay(progressMessage);
|
||||
Overlays.deleteOverlay(progressBackground);
|
||||
}
|
||||
that.cleanup = cleanup;
|
||||
|
||||
return that;
|
||||
}());
|
66
examples/libraries/stringHelpers.js
Normal file
66
examples/libraries/stringHelpers.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
|
||||
|
||||
|
||||
if (typeof String.prototype.fileName !== "function") {
|
||||
String.prototype.fileName = function () {
|
||||
return this.replace(/^(.*[\/\\])*/, "");
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.fileBase !== "function") {
|
||||
String.prototype.fileBase = function () {
|
||||
var filename = this.fileName();
|
||||
return filename.slice(0, filename.indexOf("."));
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.fileType !== "function") {
|
||||
String.prototype.fileType = function () {
|
||||
return this.slice(this.lastIndexOf(".") + 1);
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.path !== "function") {
|
||||
String.prototype.path = function () {
|
||||
return this.replace(/[\\\/][^\\\/]*$/, "");
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.regExpEscape !== "function") {
|
||||
String.prototype.regExpEscape = function () {
|
||||
return this.replace(/([$\^.+*?|\\\/{}()\[\]])/g, '\\$1');
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.toArrayBuffer !== "function") {
|
||||
String.prototype.toArrayBuffer = function () {
|
||||
var length,
|
||||
buffer,
|
||||
view,
|
||||
charCode,
|
||||
charCodes,
|
||||
i;
|
||||
|
||||
charCodes = [];
|
||||
|
||||
length = this.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
charCode = this.charCodeAt(i);
|
||||
if (charCode <= 255) {
|
||||
charCodes.push(charCode);
|
||||
} else {
|
||||
charCodes.push(charCode / 256);
|
||||
charCodes.push(charCode % 256);
|
||||
}
|
||||
}
|
||||
|
||||
length = charCodes.length;
|
||||
buffer = new ArrayBuffer(length);
|
||||
view = new Uint8Array(buffer);
|
||||
for (i = 0; i < length; i += 1) {
|
||||
view[i] = charCodes[i];
|
||||
}
|
||||
|
||||
return buffer;
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue