From 874b542c0cd5797301a6b6668b35696f534fb662 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Jul 2014 04:13:53 -0700 Subject: [PATCH 01/23] Add import/export/paste model functionality to editModels.js --- examples/editModels.js | 427 +++++++++++++++++- interface/src/Application.cpp | 38 ++ interface/src/Application.h | 5 + .../scripting/ClipboardScriptingInterface.cpp | 13 + .../scripting/ClipboardScriptingInterface.h | 4 + .../scripting/WindowScriptingInterface.cpp | 24 +- .../src/scripting/WindowScriptingInterface.h | 4 +- 7 files changed, 510 insertions(+), 5 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 64c203534c..6cde543e55 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -61,6 +61,398 @@ var jointList = MyAvatar.getJointNames(); var mode = 0; +var exportMenu = null; + +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; + } + print("position: " + position); + 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.exportModels = 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") + Clipboard.exportModels(filename, x, y, z, s); + 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.mousePressEvent = function(event) { + print("Mouse press"); + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + }; + + this.mouseReleaseEvent = function(event) { + print("Mouse release"); + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + if (clickedOverlay == locationButton) { + self.showPositionPrompt(); + } else if (clickedOverlay == exportButton) { + self.exportModels(); + } 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.mousePressEvent.connect(this.mousePressEvent); + Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); +}; + +var ModelImporter = function(opts) { + var self = this; + + var height = 30; + var margin = 4; + var outerHeight = height + (2 * margin); + var titleWidth = 120; + var cancelWidth = 100; + var fullWidth = titleWidth + cancelWidth + (2 * margin); + + // TODO: Show import preview + 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: "Cancel" + }); + this._importing = false; + + this.setImportVisible = function(visible) { + Overlays.editOverlay(importBoundaries, { 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; + // TODO: Show import preview + 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() { + print("IMPORTING "); + 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]; + 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?"))) { + Window.alert("(TODO) Importing backing to source location"); + Clipboard.importModels(filename); + return; + } + } + } + Clipboard.importModels(filename); + self._importing = true; + self.setImportVisible(true); + } + } + } + + this.paste = function() { + if (self._importing) { + self._importing = false; + self.setImportVisible(false); + Clipboard.pasteModels(); + } + } + + this.cleanup = function() { + Overlays.deleteOverlay(importBoundaries); + Overlays.deleteOverlay(cancelButton); + Overlays.deleteOverlay(titleText); + Overlays.deleteOverlay(background); + } + + Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); + Controller.mouseMoveEvent.connect(this.mouseMoveEvent); +}; + +var modelImporter = new ModelImporter(); + function isLocked(properties) { // special case to lock the ground plane model in hq. if (location.hostname == "hq.highfidelity.io" && @@ -1045,7 +1437,7 @@ function mouseReleaseEvent(event) { var modelMenuAddedDelete = false; function setupModelMenus() { print("setupModelMenus()"); - // add our menuitems + // adj our menuitems Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Edit Properties...", shortcutKeyEvent: { text: "`" }, afterItem: "Models" }); @@ -1057,6 +1449,12 @@ function setupModelMenus() { } else { print("delete exists... don't add ours"); } + + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); + + Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); + Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); + Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); } function cleanupModelMenus() { @@ -1066,6 +1464,12 @@ function cleanupModelMenus() { // delete our menuitems Menu.removeMenuItem("Edit", "Delete"); } + + Menu.removeMenuItem("Edit", "Paste Models"); + + Menu.removeSeparator("File", "Models"); + Menu.removeMenuItem("File", "Export Models"); + Menu.removeMenuItem("File", "Import Models"); } function scriptEnding() { @@ -1074,6 +1478,10 @@ function scriptEnding() { toolBar.cleanup(); cleanupModelMenus(); tooltip.cleanup(); + modelImporter.cleanup(); + if (exportMenu) { + exportMenu.close(); + } } Script.scriptEnding.connect(scriptEnding); @@ -1128,6 +1536,21 @@ function handeMenuEvent(menuItem){ Models.editModel(editModelID, properties); } } + } else if (menuItem == "Paste Models") { + modelImporter.paste(); + } else if (menuItem == "Export Models") { + if (!exportMenu) { + // if (modelImporter) { + // modelImporter.close(); + // } + exportMenu = new ExportMenu({ + onClose: function() { + exportMenu = null; + } + }); + } + } else if (menuItem == "Import Models") { + modelImporter.doImport(); } tooltip.show(false); } @@ -1173,4 +1596,4 @@ Controller.keyReleaseEvent.connect(function(event) { if (event.text == "BACKSPACE") { handeMenuEvent("Delete"); } -}); \ No newline at end of file +}); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3e121bc2ee..2c097318e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -141,6 +141,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _voxelImporter(NULL), _importSucceded(false), _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), + _modelClipboardRenderer(), + _modelClipboard(), _wantToKillLocalVoxels(false), _viewFrustum(), _lastQueriedViewFrustum(), @@ -1483,6 +1485,21 @@ struct SendVoxelsOperationArgs { const unsigned char* newBaseOctCode; }; +void Application::exportModels(const QString& filename, float x, float y, float z, float scale) { + ModelTreeElement* selectedNode = _models.getTree()->getModelAt(x, y, z, scale); + if (selectedNode) { + qDebug() << "Exporting models doing it!" << filename; + ModelTree exportTree; + _models.getTree()->copySubTreeIntoNewTree(selectedNode, &exportTree, true); + exportTree.writeToSVOFile(filename.toLocal8Bit().constData()); + } else { + qDebug() << "No models were selected"; + } + + // restore the main window's active state + _window->activateWindow(); +} + bool Application::sendVoxelsOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = (VoxelTreeElement*)element; SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; @@ -1564,6 +1581,20 @@ void Application::importVoxels() { emit importDone(); } +void Application::importModels(const QString& filename) { + _importSucceded = false; + + + _models.getTree()->readFromSVOFile(filename.toLocal8Bit().constData()); + _models.getTree()->reaverageOctreeElements(); + + + // restore the main window's active state + _window->activateWindow(); + + emit importDone(); +} + void Application::cutVoxels(const VoxelDetail& sourceVoxel) { copyVoxels(sourceVoxel); deleteVoxelAt(sourceVoxel); @@ -1719,6 +1750,10 @@ void Application::init() { _models.init(); _models.setViewFrustum(getViewFrustum()); + _modelClipboardRenderer.init(); + _modelClipboardRenderer.setViewFrustum(getViewFrustum()); + _modelClipboardRenderer.setTree(&_modelClipboard); + _metavoxels.init(); _particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_avatarManager); @@ -2083,6 +2118,7 @@ void Application::update(float deltaTime) { { PerformanceTimer perfTimer("idle/update/_models"); _models.update(); // update the models... + _modelClipboardRenderer.update(); } { @@ -2566,6 +2602,7 @@ void Application::updateShadowMap() { _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); _models.render(OctreeRenderer::SHADOW_RENDER_MODE); + _modelClipboardRenderer.render(OctreeRenderer::SHADOW_RENDER_MODE); glDisable(GL_POLYGON_OFFSET_FILL); @@ -2767,6 +2804,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... models..."); _models.render(); + _modelClipboardRenderer.render(); } // render the ambient occlusion effect if enabled diff --git a/interface/src/Application.h b/interface/src/Application.h index 11f406abf0..c2f21f3738 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -308,6 +308,9 @@ public slots: void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); + void exportModels(const QString& filename, float x, float y, float z, float scale); + void importModels(const QString& filename); + void importVoxels(); // doesn't include source voxel because it goes to clipboard void cutVoxels(const VoxelDetail& sourceVoxel); void copyVoxels(const VoxelDetail& sourceVoxel); @@ -452,6 +455,8 @@ private: ParticleCollisionSystem _particleCollisionSystem; ModelTreeRenderer _models; + ModelTreeRenderer _modelClipboardRenderer; + ModelTree _modelClipboard; QByteArray _voxelsFilename; bool _wantToKillLocalVoxels; diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index e8fb545343..39b5db9418 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -100,3 +100,16 @@ void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, Application::getInstance()->nudgeVoxelsByVector(sourceVoxel, nudgeVecInTreeSpace); } + + +void ClipboardScriptingInterface::exportModels(const QString& filename, float x, float y, float z, float s) { + Application::getInstance()->exportModels(filename, x / TREE_SCALE, y / TREE_SCALE, z / TREE_SCALE, s / TREE_SCALE); +} + +void ClipboardScriptingInterface::importModels(const QString& filename) { + Application::getInstance()->importModels(filename); +} + +void ClipboardScriptingInterface::pasteModels() { + // TODO +} diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index f0258b0cc7..2ff287b29f 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -42,6 +42,10 @@ public slots: void nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); void nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec); + + void importModels(const QString& filename); + void exportModels(const QString& filename, float x, float y, float z, float s); + void pasteModels(); }; #endif // hifi_ClipboardScriptingInterface_h diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index e10197d488..84ccdc9d7e 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -53,6 +53,15 @@ QScriptValue WindowScriptingInterface::browse(const QString& title, const QStrin return retVal; } +QScriptValue WindowScriptingInterface::save(const QString& title, const QString& directory, const QString& nameFilter) { + QScriptValue retVal; + QMetaObject::invokeMethod(this, "showBrowse", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QScriptValue, retVal), + Q_ARG(const QString&, title), Q_ARG(const QString&, directory), Q_ARG(const QString&, nameFilter), + Q_ARG(QFileDialog::AcceptMode, QFileDialog::AcceptSave)); + return retVal; +} + /// Display an alert box /// \param const QString& message message to display /// \return QScriptValue::UndefinedValue @@ -93,18 +102,29 @@ QScriptValue WindowScriptingInterface::showPrompt(const QString& message, const /// \param const QString& directory directory to start the file browser at /// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog` /// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue` -QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QString& directory, const QString& nameFilter) { +QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QString& directory, const QString& nameFilter, + QFileDialog::AcceptMode acceptMode) { // On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus // filename if the directory is valid. QString path = ""; QFileInfo fileInfo = QFileInfo(directory); + qDebug() << "File: " << directory << fileInfo.isFile(); if (fileInfo.isDir()) { fileInfo.setFile(directory, "__HIFI_INVALID_FILE__"); path = fileInfo.filePath(); } QFileDialog fileDialog(Application::getInstance()->getWindow(), title, path, nameFilter); - fileDialog.setFileMode(QFileDialog::ExistingFile); + // fileDialog.setFileMode(QFileDialog::ExistingFile); + fileDialog.setAcceptMode(acceptMode); + qDebug() << "Opening!"; + QUrl fileUrl(directory); + if (acceptMode == QFileDialog::AcceptSave) { + fileDialog.setFileMode(QFileDialog::Directory); + fileDialog.selectFile(fileUrl.fileName()); + // qDebug() << "Setting filename!"; + // fileDialog.setLabelText(QFileDialog::FileName, fileUrl.fileName()); + } if (fileDialog.exec()) { return QScriptValue(fileDialog.selectedFiles().first()); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index b97113af9c..3fb0974b4f 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -31,12 +31,14 @@ public slots: QScriptValue confirm(const QString& message = ""); QScriptValue prompt(const QString& message = "", const QString& defaultText = ""); QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); + QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); private slots: QScriptValue showAlert(const QString& message); QScriptValue showConfirm(const QString& message); QScriptValue showPrompt(const QString& message, const QString& defaultText); - QScriptValue showBrowse(const QString& title, const QString& directory, const QString& nameFilter); + QScriptValue showBrowse(const QString& title, const QString& directory, const QString& nameFilter, + QFileDialog::AcceptMode acceptMode = QFileDialog::AcceptOpen); }; #endif // hifi_WindowScriptingInterface_h From ade1903595c1be26ea15d5b99a9bb475c2dfca66 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Jul 2014 04:14:47 -0700 Subject: [PATCH 02/23] Add ModelTree::getModelAt --- libraries/models/src/ModelTree.cpp | 5 +++++ libraries/models/src/ModelTree.h | 1 + 2 files changed, 6 insertions(+) diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 763f0a969e..1489f4db19 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -108,6 +108,11 @@ bool FindAndUpdateModelOperator::PostRecursion(OctreeElement* element) { return !_found; // if we haven't yet found it, keep looking } + +ModelTreeElement* ModelTree::getModelAt(float x, float y, float z, float s) const { + return static_cast(getOctreeElementAt(x, y, z, s)); +} + // TODO: improve this to not use multiple recursions void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& senderNode) { // First, look for the existing model in the tree.. diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index a2a3c9cd28..9ab081f46c 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -36,6 +36,7 @@ public: /// Type safe version of getRoot() ModelTreeElement* getRoot() { return static_cast(_rootElement); } + ModelTreeElement* getModelAt(float x, float y, float z, float s) const; // These methods will allow the OctreeServer to send your tree inbound edit packets of your // own definition. Implement these to allow your octree based server to support editing From 06294b403b0a8efbe04ed9f22081b078b1152757 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 18:31:58 -0700 Subject: [PATCH 03/23] Add pasteModels --- interface/src/Application.cpp | 19 ++++++------------- interface/src/Application.h | 3 +++ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 476cc45242..7a2a359dbb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1602,17 +1602,13 @@ void Application::importVoxels() { } void Application::importModels(const QString& filename) { - _importSucceded = false; + _modelClipboard.eraseAllOctreeElements(); + _modelClipboard.readFromSVOFile(filename.toLocal8Bit().constData()); + _modelClipboard.reaverageOctreeElements(); +} - - _models.getTree()->readFromSVOFile(filename.toLocal8Bit().constData()); - _models.getTree()->reaverageOctreeElements(); - - - // restore the main window's active state - _window->activateWindow(); - - emit importDone(); +void Application::pasteModels(float x, float y, float z) { + _modelClipboard.sendModels(&_modelEditSender, x, y, z); } void Application::cutVoxels(const VoxelDetail& sourceVoxel) { @@ -2124,7 +2120,6 @@ void Application::update(float deltaTime) { { PerformanceTimer perfTimer("models"); _models.update(); // update the models... - _modelClipboardRenderer.update(); } { @@ -2613,7 +2608,6 @@ void Application::updateShadowMap() { _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); _models.render(OctreeRenderer::SHADOW_RENDER_MODE); - _modelClipboardRenderer.render(OctreeRenderer::SHADOW_RENDER_MODE); glDisable(GL_POLYGON_OFFSET_FILL); @@ -2814,7 +2808,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... models..."); _models.render(); - _modelClipboardRenderer.render(); } // render the ambient occlusion effect if enabled diff --git a/interface/src/Application.h b/interface/src/Application.h index 1f20d21de6..82427f697a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -200,6 +200,8 @@ public: bool getImportSucceded() { return _importSucceded; } VoxelSystem* getSharedVoxelSystem() { return &_sharedVoxelSystem; } VoxelTree* getClipboard() { return &_clipboard; } + ModelTree* getModelClipboard() { return &_modelClipboard; } + ModelTreeRenderer* getModelClipboardRenderer() { return &_modelClipboardRenderer; } Environment* getEnvironment() { return &_environment; } bool isMousePressed() const { return _mousePressed; } bool isMouseHidden() const { return _mouseHidden; } @@ -312,6 +314,7 @@ public slots: void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); + void pasteModels(float x, float y, float z); void exportModels(const QString& filename, float x, float y, float z, float scale); void importModels(const QString& filename); From 051bbd5d3403ec8b4a66b51c2336c9c15c8194a5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 18:34:22 -0700 Subject: [PATCH 04/23] Add LocalModelsOverlay --- .../src/ui/overlays/LocalModelsOverlay.cpp | 45 +++++++++++++++++++ .../src/ui/overlays/LocalModelsOverlay.h | 35 +++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 interface/src/ui/overlays/LocalModelsOverlay.cpp create mode 100644 interface/src/ui/overlays/LocalModelsOverlay.h diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp new file mode 100644 index 0000000000..ed38d41603 --- /dev/null +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -0,0 +1,45 @@ +// +// LocalModelsOverlay.cpp +// interface/src/ui/overlays +// +// Created by Ryan Huffman on 07/08/14. +// Copyright 2014 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 "Application.h" + +#include "LocalModelsOverlay.h" + +LocalModelsOverlay::LocalModelsOverlay(ModelTreeRenderer* modelTreeRenderer) : + Volume3DOverlay(), + _modelTreeRenderer(modelTree) { +} + +LocalModelsOverlay::~LocalModelsOverlay() { +} + +void LocalModelsOverlay::update(float deltatime) { + _modelTreeRenderer->update(); +} + +void LocalModelsOverlay::render() { + if (_visible) { + glPushMatrix(); { + glTranslatef(_position.x, _position.y, _position.z); + glScalef(_size, _size, _size); + _modelTreeRenderer->render(); + } glPopMatrix(); + } +} + +void LocalModelsOverlay::setProperties(const QScriptValue &properties) { + Volume3DOverlay::setProperties(properties); + + if (properties.property("scale").isValid()) { + setSize(properties.property("scale").toVariant().toFloat()); + } +} + diff --git a/interface/src/ui/overlays/LocalModelsOverlay.h b/interface/src/ui/overlays/LocalModelsOverlay.h new file mode 100644 index 0000000000..02a990119a --- /dev/null +++ b/interface/src/ui/overlays/LocalModelsOverlay.h @@ -0,0 +1,35 @@ +// +// LocalModelsOverlay.h +// interface/src/ui/overlays +// +// Created by Ryan Huffman on 07/08/14. +// Copyright 2014 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_LocalModelsOverlay_h +#define hifi_LocalModelsOverlay_h + +// #include "models/ModelTree.h" +#include "models/ModelTreeRenderer.h" + +#include "Volume3DOverlay.h" + +class LocalModelsOverlay : public Volume3DOverlay { + Q_OBJECT +public: + LocalModelsOverlay(ModelTreeRenderer* modelTreeRenderer); + ~LocalModelsOverlay(); + + virtual void update(float deltatime); + virtual void render(); + + virtual void setProperties(const QScriptValue& properties); + +private: + ModelTreeRenderer *_modelTreeRenderer; +}; + +#endif // hifi_LocalModelsOverlay_h From 7bd1628465d3343c3bf1326025b8f7cdee6b8ebb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 18:36:43 -0700 Subject: [PATCH 05/23] Add SendModelsOperation --- libraries/models/src/ModelTree.cpp | 29 +++++++++++++++++++++++++ libraries/models/src/ModelTree.h | 3 +++ libraries/models/src/ModelTreeElement.h | 6 +++++ 3 files changed, 38 insertions(+) diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 1489f4db19..98902ac6c0 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelEditPacketSender.h" +#include "ModelItem.h" + #include "ModelTree.h" ModelTree::ModelTree(bool shouldReaverage) : Octree(shouldReaverage) { @@ -204,6 +207,32 @@ void ModelTree::deleteModel(const ModelItemID& modelID) { } } +void ModelTree::sendModels(ModelEditPacketSender* packetSender, float x, float y, float z) { + SendModelsOperationArgs args; + args.packetSender = packetSender; + args.root = glm::vec3(x, y, z); + recurseTreeWithOperation(sendModelsOperation, &args); + packetSender->releaseQueuedMessages(); +} + +bool ModelTree::sendModelsOperation(OctreeElement* element, void* extraData) { + SendModelsOperationArgs* args = static_cast(extraData); + ModelTreeElement* modelTreeElement = static_cast(element); + + const QList& modelList = modelTreeElement->getModels(); + + for (int i = 0; i < modelList.size(); i++) { + uint32_t creatorTokenID = ModelItem::getNextCreatorTokenID(); + ModelItemID id(NEW_MODEL, creatorTokenID, false); + ModelItemProperties properties; + properties.copyFromModelItem(modelList.at(i)); + properties.setPosition(properties.getPosition() + args->root); + args->packetSender->queueModelEditMessage(PacketTypeModelAddOrEdit, id, properties); + } + + return true; +} + // scans the tree and handles mapping locally created models to know IDs. // in the event that this tree is also viewing the scene, then we need to also // search the tree to make sure we don't have a duplicate model from the viewing diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index 9ab081f46c..7827d9f9f3 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -84,10 +84,13 @@ public: void setFBXService(ModelItemFBXService* service) { _fbxService = service; } const FBXGeometry* getGeometryForModel(const ModelItem& modelItem) { return _fbxService ? _fbxService->getGeometryForModel(modelItem) : NULL; + } + void sendModels(ModelEditPacketSender* packetSender, float x, float y, float z); private: + static bool sendModelsOperation(OctreeElement* element, void* extraData); static bool updateOperation(OctreeElement* element, void* extraData); static bool findAndUpdateOperation(OctreeElement* element, void* extraData); static bool findAndUpdateWithIDandPropertiesOperation(OctreeElement* element, void* extraData); diff --git a/libraries/models/src/ModelTreeElement.h b/libraries/models/src/ModelTreeElement.h index 8d2f5064bd..5f28b2f981 100644 --- a/libraries/models/src/ModelTreeElement.h +++ b/libraries/models/src/ModelTreeElement.h @@ -44,6 +44,12 @@ public: bool isViewing; }; +class SendModelsOperationArgs { +public: + glm::vec3 root; + ModelEditPacketSender* packetSender; +}; + class ModelTreeElement : public OctreeElement { From 521bf6023e40b137c10fb997a2da41155f4bd657 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 18:38:09 -0700 Subject: [PATCH 06/23] Implement pasteModels in Clipboard --- interface/src/scripting/ClipboardScriptingInterface.cpp | 6 +++--- interface/src/scripting/ClipboardScriptingInterface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index 39b5db9418..d75e29e423 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -103,13 +103,13 @@ void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, void ClipboardScriptingInterface::exportModels(const QString& filename, float x, float y, float z, float s) { - Application::getInstance()->exportModels(filename, x / TREE_SCALE, y / TREE_SCALE, z / TREE_SCALE, s / TREE_SCALE); + Application::getInstance()->exportModels(filename, x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, s / (float)TREE_SCALE); } void ClipboardScriptingInterface::importModels(const QString& filename) { Application::getInstance()->importModels(filename); } -void ClipboardScriptingInterface::pasteModels() { - // TODO +void ClipboardScriptingInterface::pasteModels(float x, float y, float z, float s) { + Application::getInstance()->pasteModels(x, y, z); } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 2ff287b29f..373a7308ae 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -45,7 +45,7 @@ public slots: void importModels(const QString& filename); void exportModels(const QString& filename, float x, float y, float z, float s); - void pasteModels(); + void pasteModels(float x, float y, float z, float s); }; #endif // hifi_ClipboardScriptingInterface_h From 43f61b4718c9ef47ed94bf1e3613e37b7f31181e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 18:38:42 -0700 Subject: [PATCH 07/23] Add localmodels overlay type --- interface/src/ui/overlays/Overlays.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 581947c074..d73a01103d 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -14,6 +14,7 @@ #include "Cube3DOverlay.h" #include "ImageOverlay.h" #include "Line3DOverlay.h" +#include "LocalModelsOverlay.h" #include "LocalVoxelsOverlay.h" #include "ModelOverlay.h" #include "Overlays.h" @@ -158,6 +159,13 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay->setProperties(properties); created = true; is3D = true; + } else if (type == "localmodels") { + qDebug() << "Making localmodels"; + thisOverlay = new LocalModelsOverlay(Application::getInstance()->getModelClipboardRenderer()); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + created = true; + is3D = true; } else if (type == "model") { thisOverlay = new ModelOverlay(); thisOverlay->init(_parent); From 06e6505584429e69b31aed8a972935bd0d7b2803 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 18:39:44 -0700 Subject: [PATCH 08/23] Update and add localModels overlay to editModels.js import/export --- examples/editModels.js | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index aa0505304b..47161d57a8 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -153,7 +153,7 @@ var ExportMenu = function(opts) { width: cancelWidth, height: height, color: { red: 255, green: 255, blue: 255 }, - text: "Cancel" + text: "Close" }); var voxelPreview = Overlays.addOverlay("cube", { @@ -291,6 +291,12 @@ var ModelImporter = function(opts) { var fullWidth = titleWidth + cancelWidth + (2 * margin); // TODO: Show import preview + 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, @@ -337,6 +343,7 @@ var ModelImporter = function(opts) { 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 }); @@ -346,6 +353,9 @@ var ModelImporter = function(opts) { this.moveImport = function(position) { importPosition = position; // TODO: Show import preview + 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 } }); @@ -412,14 +422,15 @@ var ModelImporter = function(opts) { 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?"))) { - Window.alert("(TODO) Importing backing to source location"); Clipboard.importModels(filename); + Clipboard.pasteModels(x, y, z, 1); return; } } @@ -427,19 +438,21 @@ var ModelImporter = function(opts) { Clipboard.importModels(filename); self._importing = true; self.setImportVisible(true); + Overlays.editOverlay(importBoundaries, { size: s }); } } } this.paste = function() { if (self._importing) { - self._importing = false; - self.setImportVisible(false); - Clipboard.pasteModels(); + // self._importing = false; + // self.setImportVisible(false); + Clipboard.pasteModels(importPosition.x, importPosition.y, importPosition.z, 1); } } this.cleanup = function() { + Overlays.deleteOverlay(localModels); Overlays.deleteOverlay(importBoundaries); Overlays.deleteOverlay(cancelButton); Overlays.deleteOverlay(titleText); From 01737e18b2e9e06c78dc650d662238923a9208de Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 19:06:10 -0700 Subject: [PATCH 09/23] Update LocalModelOverlay to work prorperly with translations --- interface/src/Application.cpp | 1 + interface/src/Application.h | 1 + .../src/ui/overlays/LocalModelsOverlay.cpp | 19 +++++++------------ .../src/ui/overlays/LocalModelsOverlay.h | 2 -- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7a2a359dbb..e85d44a901 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -179,6 +179,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()) { + // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); diff --git a/interface/src/Application.h b/interface/src/Application.h index 82427f697a..756cb7dff7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -227,6 +227,7 @@ public: float getPacketsPerSecond() const { return _packetsPerSecond; } float getBytesPerSecond() const { return _bytesPerSecond; } const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } + void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } /// if you need to access the application settings, use lockSettings()/unlockSettings() QSettings* lockSettings() { _settingsMutex.lock(); return _settings; } diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index ed38d41603..6bb1d9ce88 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -15,7 +15,7 @@ LocalModelsOverlay::LocalModelsOverlay(ModelTreeRenderer* modelTreeRenderer) : Volume3DOverlay(), - _modelTreeRenderer(modelTree) { + _modelTreeRenderer(modelTreeRenderer) { } LocalModelsOverlay::~LocalModelsOverlay() { @@ -28,18 +28,13 @@ void LocalModelsOverlay::update(float deltatime) { void LocalModelsOverlay::render() { if (_visible) { glPushMatrix(); { - glTranslatef(_position.x, _position.y, _position.z); - glScalef(_size, _size, _size); + Application* app = Application::getInstance(); + glm::vec3 oldTranslation = app->getViewMatrixTranslation(); + app->setViewMatrixTranslation(oldTranslation + _position); + _modelTreeRenderer->render(); + + Application::getInstance()->setViewMatrixTranslation(oldTranslation); } glPopMatrix(); } } - -void LocalModelsOverlay::setProperties(const QScriptValue &properties) { - Volume3DOverlay::setProperties(properties); - - if (properties.property("scale").isValid()) { - setSize(properties.property("scale").toVariant().toFloat()); - } -} - diff --git a/interface/src/ui/overlays/LocalModelsOverlay.h b/interface/src/ui/overlays/LocalModelsOverlay.h index 02a990119a..88bf55aaf0 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.h +++ b/interface/src/ui/overlays/LocalModelsOverlay.h @@ -25,8 +25,6 @@ public: virtual void update(float deltatime); virtual void render(); - - virtual void setProperties(const QScriptValue& properties); private: ModelTreeRenderer *_modelTreeRenderer; From 6a53765a47241d491b1e3924cd53faf0c4f95eef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 30 Jul 2014 19:06:23 -0700 Subject: [PATCH 10/23] Rename buttons in editModels.js --- examples/editModels.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 47161d57a8..671c79ad39 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -153,7 +153,7 @@ var ExportMenu = function(opts) { width: cancelWidth, height: height, color: { red: 255, green: 255, blue: 255 }, - text: "Close" + text: "Cancel" }); var voxelPreview = Overlays.addOverlay("cube", { @@ -337,7 +337,7 @@ var ModelImporter = function(opts) { height: height, color: { red: 255, green: 255, blue: 255 }, visible: false, - text: "Cancel" + text: "Close" }); this._importing = false; From d54e3741edc4fec430c8ba588de9158d2ae48f71 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 01:09:38 -0700 Subject: [PATCH 11/23] Add ModelTree::findModelsInCube --- libraries/models/src/ModelTree.cpp | 22 +++++++++++++++++++++- libraries/models/src/ModelTree.h | 4 +++- libraries/models/src/ModelTreeElement.cpp | 13 +++++++++++++ libraries/models/src/ModelTreeElement.h | 2 ++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 98902ac6c0..df94213213 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -387,6 +387,26 @@ public: QVector _foundModels; }; +void ModelTree::findModelsInCube(const AACube& cube, QVector& foundModels) { + FindModelsInCubeArgs args(cube); + lockForRead(); + recurseTreeWithOperation(findInCubeOperation, &args); + unlock(); + // swap the two lists of model pointers instead of copy + foundModels.swap(args._foundModels); +} + +bool ModelTree::findInCubeOperation(OctreeElement* element, void* extraData) { + FindModelsInCubeArgs* args = static_cast< FindModelsInCubeArgs*>(extraData); + const AACube& elementCube = element->getAACube(); + if (elementCube.touches(args->_cube)) { + ModelTreeElement* modelTreeElement = static_cast(element); + modelTreeElement->getModelsInside(args->_cube, args->_foundModels); + return true; + } + return false; +} + bool ModelTree::findInCubeForUpdateOperation(OctreeElement* element, void* extraData) { FindModelsInCubeArgs* args = static_cast< FindModelsInCubeArgs*>(extraData); const AACube& elementCube = element->getAACube(); @@ -398,7 +418,7 @@ bool ModelTree::findInCubeForUpdateOperation(OctreeElement* element, void* extra return false; } -void ModelTree::findModelsForUpdate(const AACube& cube, QVector foundModels) { +void ModelTree::findModelsForUpdate(const AACube& cube, QVector& foundModels) { FindModelsInCubeArgs args(cube); lockForRead(); recurseTreeWithOperation(findInCubeForUpdateOperation, &args); diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index 7827d9f9f3..3a1159c9cf 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -63,12 +63,13 @@ public: /// \param foundModels[out] vector of const ModelItem* /// \remark Side effect: any initial contents in foundModels will be lost void findModels(const glm::vec3& center, float radius, QVector& foundModels); + void findModelsInCube(const AACube& cube, QVector& foundModels); /// finds all models that touch a cube /// \param cube the query cube /// \param foundModels[out] vector of non-const ModelItem* /// \remark Side effect: any initial contents in models will be lost - void findModelsForUpdate(const AACube& cube, QVector foundModels); + void findModelsForUpdate(const AACube& cube, QVector& foundModels); void addNewlyCreatedHook(NewlyCreatedModelHook* hook); void removeNewlyCreatedHook(NewlyCreatedModelHook* hook); @@ -92,6 +93,7 @@ private: static bool sendModelsOperation(OctreeElement* element, void* extraData); static bool updateOperation(OctreeElement* element, void* extraData); + static bool findInCubeOperation(OctreeElement* element, void* extraData); static bool findAndUpdateOperation(OctreeElement* element, void* extraData); static bool findAndUpdateWithIDandPropertiesOperation(OctreeElement* element, void* extraData); static bool findNearPointOperation(OctreeElement* element, void* extraData); diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 960d1dd4cb..47ea8babac 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -399,6 +399,19 @@ void ModelTreeElement::getModels(const glm::vec3& searchPosition, float searchRa } } +void ModelTreeElement::getModelsInside(const AACube& box, QVector& foundModels) { + QList::iterator modelItr = _modelItems->begin(); + QList::iterator modelEnd = _modelItems->end(); + AACube modelCube; + while(modelItr != modelEnd) { + ModelItem* model = &(*modelItr); + if (box.contains(model->getPosition())) { + foundModels.push_back(model); + } + ++modelItr; + } +} + void ModelTreeElement::getModelsForUpdate(const AACube& box, QVector& foundModels) { QList::iterator modelItr = _modelItems->begin(); QList::iterator modelEnd = _modelItems->end(); diff --git a/libraries/models/src/ModelTreeElement.h b/libraries/models/src/ModelTreeElement.h index 5f28b2f981..c0e2e36095 100644 --- a/libraries/models/src/ModelTreeElement.h +++ b/libraries/models/src/ModelTreeElement.h @@ -138,6 +138,8 @@ public: /// \param models[out] vector of non-const ModelItem* void getModelsForUpdate(const AACube& box, QVector& foundModels); + void getModelsInside(const AACube& box, QVector& foundModels); + const ModelItem* getModelWithID(uint32_t id) const; bool removeModelWithID(uint32_t id); From 6ecc12cdeacb04eadb52758343f9b69871027529 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 01:11:05 -0700 Subject: [PATCH 12/23] Fix export models not cancelling correctly --- examples/editModels.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/editModels.js b/examples/editModels.js index 671c79ad39..1a5753838d 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -217,7 +217,9 @@ var ExportMenu = function(opts) { var s = self._scale; var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo"; filename = Window.save("Select where to save", filename, "*.svo") - Clipboard.exportModels(filename, x, y, z, s); + if (filename) { + Clipboard.exportModels(filename, x, y, z, s); + } self.close(); }; From a39a7e23564fe3b380b9ae493aa1d4b757d09e1c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 01:13:17 -0700 Subject: [PATCH 13/23] Update exportModels implementation --- interface/src/Application.cpp | 22 +++++++++++++++++----- interface/src/Application.h | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e85d44a901..e469cc7535 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1506,19 +1506,31 @@ struct SendVoxelsOperationArgs { const unsigned char* newBaseOctCode; }; -void Application::exportModels(const QString& filename, float x, float y, float z, float scale) { - ModelTreeElement* selectedNode = _models.getTree()->getModelAt(x, y, z, scale); - if (selectedNode) { - qDebug() << "Exporting models doing it!" << filename; +bool Application::exportModels(const QString& filename, float x, float y, float z, float scale) { + QVector models; + _models.getTree()->findModelsInCube(AACube(glm::vec3(x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE), scale / (float)TREE_SCALE), models); + if (models.size() > 0) { + glm::vec3 root(x, y, z); ModelTree exportTree; - _models.getTree()->copySubTreeIntoNewTree(selectedNode, &exportTree, true); + + for (int i = 0; i < models.size(); i++) { + ModelItemProperties properties; + ModelItemID id = models.at(i)->getModelItemID(); + id.isKnownID = false; + properties.copyFromModelItem(*models.at(i)); + properties.setPosition(properties.getPosition() - root); + exportTree.addModel(id, properties); + } + exportTree.writeToSVOFile(filename.toLocal8Bit().constData()); } else { qDebug() << "No models were selected"; + return false; } // restore the main window's active state _window->activateWindow(); + return true; } bool Application::sendVoxelsOperation(OctreeElement* element, void* extraData) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 756cb7dff7..44a93f5d7b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -316,7 +316,7 @@ public slots: void packetSent(quint64 length); void pasteModels(float x, float y, float z); - void exportModels(const QString& filename, float x, float y, float z, float scale); + bool exportModels(const QString& filename, float x, float y, float z, float scale); void importModels(const QString& filename); void importVoxels(); // doesn't include source voxel because it goes to clipboard From 68f1ad79d6dd0c9c5a71a6dd775ac195d3ed3de7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 01:14:07 -0700 Subject: [PATCH 14/23] Update clipboard call to exportModels to not scale to tree size --- interface/src/scripting/ClipboardScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index d75e29e423..10799c2abb 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -103,7 +103,7 @@ void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, void ClipboardScriptingInterface::exportModels(const QString& filename, float x, float y, float z, float s) { - Application::getInstance()->exportModels(filename, x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, s / (float)TREE_SCALE); + Application::getInstance()->exportModels(filename, x, y, z, s); } void ClipboardScriptingInterface::importModels(const QString& filename) { From 49e35bbc84ea2f66e641712eb7402b3c7c3691c3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 01:14:18 -0700 Subject: [PATCH 15/23] Fix bug with ModelItemProperties When copying from a ModelItem the properties should be considered changed --- libraries/models/src/ModelItem.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/models/src/ModelItem.cpp b/libraries/models/src/ModelItem.cpp index 750af8f1b6..afa64e3bc6 100644 --- a/libraries/models/src/ModelItem.cpp +++ b/libraries/models/src/ModelItem.cpp @@ -1142,19 +1142,19 @@ void ModelItemProperties::copyFromModelItem(const ModelItem& modelItem) { _id = modelItem.getID(); _idSet = true; - _positionChanged = false; - _colorChanged = false; - _radiusChanged = false; + _positionChanged = true; + _colorChanged = true; + _radiusChanged = true; - _shouldDieChanged = false; - _modelURLChanged = false; - _modelRotationChanged = false; - _animationURLChanged = false; - _animationIsPlayingChanged = false; - _animationFrameIndexChanged = false; - _animationFPSChanged = false; - _glowLevelChanged = false; - _defaultSettings = false; + _shouldDieChanged = true; + _modelURLChanged = true; + _modelRotationChanged = true; + _animationURLChanged = true; + _animationIsPlayingChanged = true; + _animationFrameIndexChanged = true; + _animationFPSChanged = true; + _glowLevelChanged = true; + _defaultSettings = true; } QScriptValue ModelItemPropertiesToScriptValue(QScriptEngine* engine, const ModelItemProperties& properties) { From 3e2bb0f1684891f28f4c6d6dff5dc70ec2855a6c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 10:40:45 -0700 Subject: [PATCH 16/23] Add more complete error handling for import/export models --- examples/editModels.js | 25 +++++++++++++------ interface/src/Application.cpp | 9 ++++--- interface/src/Application.h | 2 +- .../scripting/ClipboardScriptingInterface.cpp | 8 +++--- .../scripting/ClipboardScriptingInterface.h | 4 +-- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 1a5753838d..f3650bada2 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -218,7 +218,10 @@ var ExportMenu = function(opts) { var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo"; filename = Window.save("Select where to save", filename, "*.svo") if (filename) { - Clipboard.exportModels(filename, x, y, z, s); + var success = Clipboard.exportModels(filename, x, y, z, s); + if (!succcess) { + WIndow.alert("Export failed: no models found in selected area."); + } } self.close(); }; @@ -431,16 +434,24 @@ var ModelImporter = function(opts) { } } else { if (Window.confirm(("Would you like to import back to the source location?"))) { - Clipboard.importModels(filename); - Clipboard.pasteModels(x, y, z, 1); + var success = Clipboard.importModels(filename); + if (success) { + Clipboard.pasteModels(x, y, z, 1); + } else { + Window.alert("There was an error importing the model file."); + } return; } } } - Clipboard.importModels(filename); - self._importing = true; - self.setImportVisible(true); - Overlays.editOverlay(importBoundaries, { size: s }); + var success = Clipboard.importModels(filename); + if (success) { + self._importing = true; + self.setImportVisible(true); + Overlays.editOverlay(importBoundaries, { size: s }); + } else { + Window.alert("There was an error importing the model file."); + } } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e469cc7535..540cb47a79 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1614,10 +1614,13 @@ void Application::importVoxels() { emit importDone(); } -void Application::importModels(const QString& filename) { +bool Application::importModels(const QString& filename) { _modelClipboard.eraseAllOctreeElements(); - _modelClipboard.readFromSVOFile(filename.toLocal8Bit().constData()); - _modelClipboard.reaverageOctreeElements(); + bool success = _modelClipboard.readFromSVOFile(filename.toLocal8Bit().constData()); + if (success) { + _modelClipboard.reaverageOctreeElements(); + } + return success; } void Application::pasteModels(float x, float y, float z) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 44a93f5d7b..d15d8ae63f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -317,7 +317,7 @@ public slots: void pasteModels(float x, float y, float z); bool exportModels(const QString& filename, float x, float y, float z, float scale); - void importModels(const QString& filename); + bool importModels(const QString& filename); void importVoxels(); // doesn't include source voxel because it goes to clipboard void cutVoxels(const VoxelDetail& sourceVoxel); diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index 10799c2abb..aa4a06fa50 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -102,12 +102,12 @@ void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, } -void ClipboardScriptingInterface::exportModels(const QString& filename, float x, float y, float z, float s) { - Application::getInstance()->exportModels(filename, x, y, z, s); +bool ClipboardScriptingInterface::exportModels(const QString& filename, float x, float y, float z, float s) { + return Application::getInstance()->exportModels(filename, x, y, z, s); } -void ClipboardScriptingInterface::importModels(const QString& filename) { - Application::getInstance()->importModels(filename); +bool ClipboardScriptingInterface::importModels(const QString& filename) { + return Application::getInstance()->importModels(filename); } void ClipboardScriptingInterface::pasteModels(float x, float y, float z, float s) { diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 373a7308ae..aa5234a115 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -43,8 +43,8 @@ public slots: void nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); void nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec); - void importModels(const QString& filename); - void exportModels(const QString& filename, float x, float y, float z, float s); + bool importModels(const QString& filename); + bool exportModels(const QString& filename, float x, float y, float z, float s); void pasteModels(float x, float y, float z, float s); }; From 85ed18fd415655cfb8817fa45e1ce71073d47061 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 10:43:44 -0700 Subject: [PATCH 17/23] Cleanup editModels.js --- examples/editModels.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index f3650bada2..fc1c43e934 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -186,7 +186,6 @@ var ExportMenu = function(opts) { if (positionStr == null) { break; } - print("position: " + position); var position = self.parsePosition(positionStr); if (position != null) { self.setPosition(position.x, position.y, position.z); @@ -238,13 +237,7 @@ var ExportMenu = function(opts) { }; - this.mousePressEvent = function(event) { - print("Mouse press"); - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - }; - this.mouseReleaseEvent = function(event) { - print("Mouse release"); var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); if (clickedOverlay == locationButton) { @@ -281,7 +274,6 @@ var ExportMenu = function(opts) { }; print("CONNECTING!"); - Controller.mousePressEvent.connect(this.mousePressEvent); Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); }; @@ -313,7 +305,7 @@ var ModelImporter = function(opts) { var pos = { x: windowDimensions.x / 2 - (fullWidth / 2), y: windowDimensions.y - 100 }; - var background= Overlays.addOverlay("text", { + var background = Overlays.addOverlay("text", { x: pos.x, y: pos.y, opacity: 1, @@ -414,7 +406,6 @@ var ModelImporter = function(opts) { // 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() { - print("IMPORTING "); if (!self._importing) { var filename = Window.browse("Select models to import", "", "*.svo") if (filename) { @@ -1609,9 +1600,6 @@ function handeMenuEvent(menuItem){ modelImporter.paste(); } else if (menuItem == "Export Models") { if (!exportMenu) { - // if (modelImporter) { - // modelImporter.close(); - // } exportMenu = new ExportMenu({ onClose: function() { exportMenu = null; From a670889ffb15c82a36a3e299d2f4481768f48d47 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 10:44:36 -0700 Subject: [PATCH 18/23] Remove TODO comment --- examples/editModels.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index fc1c43e934..c0dfad871d 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -287,7 +287,6 @@ var ModelImporter = function(opts) { var cancelWidth = 100; var fullWidth = titleWidth + cancelWidth + (2 * margin); - // TODO: Show import preview var localModels = Overlays.addOverlay("localmodels", { position: { x: 1, y: 1, z: 1 }, scale: 1, @@ -349,7 +348,6 @@ var ModelImporter = function(opts) { var importPosition = { x: 0, y: 0, z: 0 }; this.moveImport = function(position) { importPosition = position; - // TODO: Show import preview Overlays.editOverlay(localModels, { position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } }); From aa1c9d88dd88da6aeeb52878af086ba8d77e3dfa Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 10:48:26 -0700 Subject: [PATCH 19/23] Cleaup several qDebug calls and commented lines --- interface/src/scripting/WindowScriptingInterface.cpp | 3 --- interface/src/ui/overlays/LocalModelsOverlay.h | 1 - interface/src/ui/overlays/Overlays.cpp | 1 - 3 files changed, 5 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index f9b1b47549..ea0eeb0dd9 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -204,15 +204,12 @@ QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QS } QFileDialog fileDialog(Application::getInstance()->getWindow(), title, path, nameFilter); - // fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setAcceptMode(acceptMode); qDebug() << "Opening!"; QUrl fileUrl(directory); if (acceptMode == QFileDialog::AcceptSave) { fileDialog.setFileMode(QFileDialog::Directory); fileDialog.selectFile(fileUrl.fileName()); - // qDebug() << "Setting filename!"; - // fileDialog.setLabelText(QFileDialog::FileName, fileUrl.fileName()); } if (fileDialog.exec()) { return QScriptValue(fileDialog.selectedFiles().first()); diff --git a/interface/src/ui/overlays/LocalModelsOverlay.h b/interface/src/ui/overlays/LocalModelsOverlay.h index 88bf55aaf0..7c4bffa342 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.h +++ b/interface/src/ui/overlays/LocalModelsOverlay.h @@ -12,7 +12,6 @@ #ifndef hifi_LocalModelsOverlay_h #define hifi_LocalModelsOverlay_h -// #include "models/ModelTree.h" #include "models/ModelTreeRenderer.h" #include "Volume3DOverlay.h" diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d73a01103d..8ef800ef7b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -160,7 +160,6 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope created = true; is3D = true; } else if (type == "localmodels") { - qDebug() << "Making localmodels"; thisOverlay = new LocalModelsOverlay(Application::getInstance()->getModelClipboardRenderer()); thisOverlay->init(_parent); thisOverlay->setProperties(properties); From 054e832cf874b97ceddc3667b6d97d4ab640621b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 31 Jul 2014 11:32:17 -0700 Subject: [PATCH 20/23] Fix misspelled variable names --- examples/editModels.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index c0dfad871d..93954d84f3 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -218,8 +218,8 @@ var ExportMenu = function(opts) { filename = Window.save("Select where to save", filename, "*.svo") if (filename) { var success = Clipboard.exportModels(filename, x, y, z, s); - if (!succcess) { - WIndow.alert("Export failed: no models found in selected area."); + if (!success) { + Window.alert("Export failed: no models found in selected area."); } } self.close(); From 355cf074433c7fbd406091780f8e149b57e4af68 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 Aug 2014 13:03:10 -0700 Subject: [PATCH 21/23] Fix style issue --- libraries/models/src/ModelTree.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index df94213213..53ee60d696 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -397,7 +397,7 @@ void ModelTree::findModelsInCube(const AACube& cube, QVector& foundM } bool ModelTree::findInCubeOperation(OctreeElement* element, void* extraData) { - FindModelsInCubeArgs* args = static_cast< FindModelsInCubeArgs*>(extraData); + FindModelsInCubeArgs* args = static_cast(extraData); const AACube& elementCube = element->getAACube(); if (elementCube.touches(args->_cube)) { ModelTreeElement* modelTreeElement = static_cast(element); @@ -408,7 +408,7 @@ bool ModelTree::findInCubeOperation(OctreeElement* element, void* extraData) { } bool ModelTree::findInCubeForUpdateOperation(OctreeElement* element, void* extraData) { - FindModelsInCubeArgs* args = static_cast< FindModelsInCubeArgs*>(extraData); + FindModelsInCubeArgs* args = static_cast(extraData); const AACube& elementCube = element->getAACube(); if (elementCube.touches(args->_cube)) { ModelTreeElement* modelTreeElement = static_cast(element); From b98ee351a5817a0ac064be36b2a0031fc5c960bc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 Aug 2014 13:04:03 -0700 Subject: [PATCH 22/23] Remove unused ModelTree::getModelAt --- libraries/models/src/ModelTree.cpp | 4 ---- libraries/models/src/ModelTree.h | 2 -- 2 files changed, 6 deletions(-) diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 53ee60d696..b9b4faed07 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -112,10 +112,6 @@ bool FindAndUpdateModelOperator::PostRecursion(OctreeElement* element) { } -ModelTreeElement* ModelTree::getModelAt(float x, float y, float z, float s) const { - return static_cast(getOctreeElementAt(x, y, z, s)); -} - // TODO: improve this to not use multiple recursions void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& senderNode) { // First, look for the existing model in the tree.. diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index 3a1159c9cf..e61cc6057e 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -36,8 +36,6 @@ public: /// Type safe version of getRoot() ModelTreeElement* getRoot() { return static_cast(_rootElement); } - ModelTreeElement* getModelAt(float x, float y, float z, float s) const; - // These methods will allow the OctreeServer to send your tree inbound edit packets of your // own definition. Implement these to allow your octree based server to support editing virtual bool getWantSVOfileVersions() const { return true; } From d01d605b4029fdf70529d07d952386e84b3a032b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 Aug 2014 13:52:00 -0700 Subject: [PATCH 23/23] Add ModelItemProperties::copyFromNewModelItem --- interface/src/Application.cpp | 2 +- libraries/models/src/ModelItem.cpp | 32 ++++++++++++++++++++++++++++++ libraries/models/src/ModelItem.h | 1 + libraries/models/src/ModelTree.cpp | 2 +- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 540cb47a79..490e5441d2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1517,7 +1517,7 @@ bool Application::exportModels(const QString& filename, float x, float y, float ModelItemProperties properties; ModelItemID id = models.at(i)->getModelItemID(); id.isKnownID = false; - properties.copyFromModelItem(*models.at(i)); + properties.copyFromNewModelItem(*models.at(i)); properties.setPosition(properties.getPosition() - root); exportTree.addModel(id, properties); } diff --git a/libraries/models/src/ModelItem.cpp b/libraries/models/src/ModelItem.cpp index afa64e3bc6..2a3a88fb65 100644 --- a/libraries/models/src/ModelItem.cpp +++ b/libraries/models/src/ModelItem.cpp @@ -1142,6 +1142,38 @@ void ModelItemProperties::copyFromModelItem(const ModelItem& modelItem) { _id = modelItem.getID(); _idSet = true; + _positionChanged = false; + _colorChanged = false; + _radiusChanged = false; + + _shouldDieChanged = false; + _modelURLChanged = false; + _modelRotationChanged = false; + _animationURLChanged = false; + _animationIsPlayingChanged = false; + _animationFrameIndexChanged = false; + _animationFPSChanged = false; + _glowLevelChanged = false; + _defaultSettings = false; +} + +void ModelItemProperties::copyFromNewModelItem(const ModelItem& modelItem) { + _position = modelItem.getPosition() * (float) TREE_SCALE; + _color = modelItem.getXColor(); + _radius = modelItem.getRadius() * (float) TREE_SCALE; + _shouldDie = modelItem.getShouldDie(); + _modelURL = modelItem.getModelURL(); + _modelRotation = modelItem.getModelRotation(); + _animationURL = modelItem.getAnimationURL(); + _animationIsPlaying = modelItem.getAnimationIsPlaying(); + _animationFrameIndex = modelItem.getAnimationFrameIndex(); + _animationFPS = modelItem.getAnimationFPS(); + _glowLevel = modelItem.getGlowLevel(); + _sittingPoints = modelItem.getSittingPoints(); + + _id = modelItem.getID(); + _idSet = true; + _positionChanged = true; _colorChanged = true; _radiusChanged = true; diff --git a/libraries/models/src/ModelItem.h b/libraries/models/src/ModelItem.h index 43aaca48a0..3e3c46a12d 100644 --- a/libraries/models/src/ModelItem.h +++ b/libraries/models/src/ModelItem.h @@ -74,6 +74,7 @@ public: void copyToModelItem(ModelItem& modelItem) const; void copyFromModelItem(const ModelItem& modelItem); + void copyFromNewModelItem(const ModelItem& modelItem); const glm::vec3& getPosition() const { return _position; } xColor getColor() const { return _color; } diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index b9b4faed07..206e67078c 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -221,7 +221,7 @@ bool ModelTree::sendModelsOperation(OctreeElement* element, void* extraData) { uint32_t creatorTokenID = ModelItem::getNextCreatorTokenID(); ModelItemID id(NEW_MODEL, creatorTokenID, false); ModelItemProperties properties; - properties.copyFromModelItem(modelList.at(i)); + properties.copyFromNewModelItem(modelList.at(i)); properties.setPosition(properties.getPosition() + args->root); args->packetSender->queueModelEditMessage(PacketTypeModelAddOrEdit, id, properties); }