diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index 4d0773f5f5..adfde4439a 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v2.zip - URL_MD5 d76bdb3e2bf7ae5d20115bd97b0c44a8 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v3.zip + URL_MD5 ea608c2e4c90539ab3c1d66acf0e005a CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index bdedf4cbba..28ac320e42 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -1234,6 +1234,9 @@ Section "Uninstall" @CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + ;Remove the installer information file + Delete "$INSTDIR\installer.ini" + ;Remove files we installed. ;Keep the list of directories here in sync with the File commands above. @CPACK_NSIS_DELETE_FILES@ diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index a622349d00..009aa8f852 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -51,7 +51,24 @@ Rectangle { onCertificateInfoResult: { if (result.status !== 'success') { - console.log("Failed to get certificate info", result.message); + console.log("Failed to get certificate info", result.data.message); + // We should still tell the user that static cert verification failed + if (root.certificateStatus !== 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED + root.useGoldCert = false; + root.certTitleTextColor = hifi.colors.redHighlight; + root.certTextColor = hifi.colors.redHighlight; + root.infoTextColor = hifi.colors.redHighlight; + titleBarText.text = "Certificate Unavailable"; + popText.text = ""; + showInMarketplaceButton.visible = false; + root.certInfoReplaceMode = 0; + root.itemName = ""; + root.itemEdition = ""; + root.itemOwner = ""; + root.dateOfPurchase = ""; + root.itemCost = ""; + errorText.text = "Information about this certificate is currently unavailable. Please try again later."; + } } else { root.marketplaceUrl = result.data.marketplace_item_url; root.isMyCert = result.isMyCert ? result.isMyCert : false; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6c071defff..df7546cd33 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -447,6 +447,9 @@ Menu::Menu() { textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture512MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture1024MB, 0, false)); textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture2048MB, 0, false)); + textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture4096MB, 0, false)); + textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture6144MB, 0, false)); + textureGroup->addAction(addCheckableActionToQMenuAndActionHash(textureMenu, MenuOption::RenderMaxTexture8192MB, 0, false)); connect(textureGroup, &QActionGroup::triggered, [textureGroup] { auto checked = textureGroup->checkedAction(); auto text = checked->text(); @@ -463,6 +466,12 @@ Menu::Menu() { newMaxTextureMemory = MB_TO_BYTES(1024); } else if (MenuOption::RenderMaxTexture2048MB == text) { newMaxTextureMemory = MB_TO_BYTES(2048); + } else if (MenuOption::RenderMaxTexture4096MB == text) { + newMaxTextureMemory = MB_TO_BYTES(4096); + } else if (MenuOption::RenderMaxTexture6144MB == text) { + newMaxTextureMemory = MB_TO_BYTES(6144); + } else if (MenuOption::RenderMaxTexture8192MB == text) { + newMaxTextureMemory = MB_TO_BYTES(8192); } gpu::Texture::setAllowedGPUMemoryUsage(newMaxTextureMemory); }); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index cf9eed1a27..4d418a16d2 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -155,6 +155,10 @@ namespace MenuOption { const QString RenderMaxTexture512MB = "512 MB"; const QString RenderMaxTexture1024MB = "1024 MB"; const QString RenderMaxTexture2048MB = "2048 MB"; + const QString RenderMaxTexture3072MB = "3072 MB"; + const QString RenderMaxTexture4096MB = "4096 MB"; + const QString RenderMaxTexture6144MB = "6144 MB"; + const QString RenderMaxTexture8192MB = "8192 MB"; const QString RenderResolution = "Scale Resolution"; const QString RenderResolutionOne = "1"; const QString RenderResolutionTwoThird = "2/3"; diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index cb06cdfed7..573d4db33c 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -35,12 +35,19 @@ QJsonObject Ledger::apiResponse(const QString& label, QNetworkReply& reply) { QJsonObject Ledger::failResponse(const QString& label, QNetworkReply& reply) { QString response = reply.readAll(); qWarning(commerce) << "FAILED" << label << response; - QJsonObject result - { - { "status", "fail" }, - { "message", response } - }; - return result; + + // tempResult will be NULL if the response isn't valid JSON. + QJsonDocument tempResult = QJsonDocument::fromJson(response.toLocal8Bit()); + if (tempResult.isNull()) { + QJsonObject result + { + { "status", "fail" }, + { "message", response } + }; + return result; + } else { + return tempResult.object(); + } } #define ApiHandler(NAME) void Ledger::NAME##Success(QNetworkReply& reply) { emit NAME##Result(apiResponse(#NAME, reply)); } #define FailHandler(NAME) void Ledger::NAME##Failure(QNetworkReply& reply) { emit NAME##Result(failResponse(#NAME, reply)); } @@ -337,7 +344,9 @@ void Ledger::certificateInfoSuccess(QNetworkReply& reply) { qInfo(commerce) << "certificateInfo" << "response" << QJsonDocument(replyObject).toJson(QJsonDocument::Compact); emit certificateInfoResult(replyObject); } -void Ledger::certificateInfoFailure(QNetworkReply& reply) { failResponse("certificateInfo", reply); } +void Ledger::certificateInfoFailure(QNetworkReply& reply) { + emit certificateInfoResult(failResponse("certificateInfo", reply)); +} void Ledger::certificateInfo(const QString& certificateId) { QString endpoint = "proof_of_purchase_status/transfer"; QJsonObject request; diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h index 2fe55eaea0..9e0271601b 100644 --- a/interface/src/scripting/SettingsScriptingInterface.h +++ b/interface/src/scripting/SettingsScriptingInterface.h @@ -15,6 +15,11 @@ #include #include +/**jsdoc + * The Settings API provides a facility to store and retrieve values that persist between Interface runs. + * @namespace Settings + */ + class SettingsScriptingInterface : public QObject { Q_OBJECT SettingsScriptingInterface() { }; @@ -22,8 +27,37 @@ public: static SettingsScriptingInterface* getInstance(); public slots: + + /**jsdoc + * Retrieve the value from a named setting. + * @function Settings.getValue + * @param {string} key - The name of the setting. + * @param {string|number|boolean|object} [defaultValue=""] - The value to return if the setting doesn't exist. + * @returns {string|number|boolean|object} The value stored in the named setting if it exists, otherwise the + * defaultValue. + * @example Retrieve non-existent setting values. + * var value1 = Settings.getValue("Script Example/Nonexistent Key"); + * print("Value: " + (typeof value1) + " " + JSON.stringify(value1)); // string "" + * + * var value2 = Settings.getValue("Script Example/Nonexistent Key", true); + * print("Value: " + (typeof value2) + " " + JSON.stringify(value2)); // boolean true + */ QVariant getValue(const QString& setting); QVariant getValue(const QString& setting, const QVariant& defaultValue); + + /**jsdoc + * Store a value in a named setting. If the setting already exists its value is overwritten, otherwise a new setting is + * created. If the value is set to null or undefined, the setting is deleted. + * @function Settings.setValue + * @param {string} key - The name of the setting. Be sure to use a unique name if creating a new setting. + * @param {string|number|boolean|object|undefined} value - The value to store in the setting. If null or + * undefined is specified, the setting is deleted. + * @example Store and retrieve an object value. + * Settings.setValue("Script Example/My Key", { x: 0, y: 10, z: 0 }); + * + * var value = Settings.getValue("Script Example/My Key"); + * print("Value: " + (typeof value) + " " + JSON.stringify(value)); // object {"x":0,"y":10,"z":0} + */ void setValue(const QString& setting, const QVariant& value); }; diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 58ec744f4e..9c46f9e98a 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -51,7 +51,7 @@ WindowScriptingInterface::WindowScriptingInterface() { } }); - connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &WindowScriptingInterface::geometryChanged); + connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &WindowScriptingInterface::onWindowGeometryChanged); } WindowScriptingInterface::~WindowScriptingInterface() { @@ -390,11 +390,22 @@ glm::vec2 WindowScriptingInterface::getDeviceSize() const { } int WindowScriptingInterface::getX() { - return qApp->getWindow()->x(); + return qApp->getWindow()->geometry().x(); } int WindowScriptingInterface::getY() { - return qApp->getWindow()->y(); + auto menu = qApp->getPrimaryMenu(); + int menuHeight = menu ? menu->geometry().height() : 0; + return qApp->getWindow()->geometry().y() + menuHeight; +} + +void WindowScriptingInterface::onWindowGeometryChanged(const QRect& windowGeometry) { + auto geometry = windowGeometry; + auto menu = qApp->getPrimaryMenu(); + if (menu) { + geometry.setY(geometry.y() + menu->geometry().height()); + } + emit geometryChanged(geometry); } void WindowScriptingInterface::copyToClipboard(const QString& text) { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index e3b092d011..dd74358064 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -33,8 +33,10 @@ * @property {number} innerHeight - The height of the drawable area of the Interface window (i.e., without borders or other * chrome), in pixels. Read-only. * @property {object} location - Provides facilities for working with your current metaverse location. See {@link location}. - * @property {number} x - The x coordinate of the top left corner of the Interface window on the display. Read-only. - * @property {number} y - The y coordinate of the top left corner of the Interface window on the display. Read-only. + * @property {number} x - The x display coordinate of the top left corner of the drawable area of the Interface window. + * Read-only. + * @property {number} y - The y display coordinate of the top left corner of the drawable area of the Interface window. + * Read-only. */ class WindowScriptingInterface : public QObject, public Dependency { @@ -522,6 +524,7 @@ public slots: void closeMessageBox(int id); private slots: + void onWindowGeometryChanged(const QRect& geometry); void onMessageBoxSelected(int button); void disconnectedFromDomain(); diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 9bb1da59d2..9c920efb93 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -20,7 +20,8 @@ #include const int FIXED_FONT_POINT_SIZE = 40; -const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 80.0f; // this is a ratio determined through experimentation +const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line + // height. const float LINE_SCALE_RATIO = 1.2f; QString const Text3DOverlay::TYPE = "text3d"; diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 359ff6b33a..06a487d6ea 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -128,6 +128,7 @@ namespace controller { makeButtonPair(Action::TOGGLE_MUTE, "ToggleMute"), makeButtonPair(Action::CYCLE_CAMERA, "CycleCamera"), makeButtonPair(Action::TOGGLE_OVERLAY, "ToggleOverlay"), + makeButtonPair(Action::SPRINT, "Sprint"), makeAxisPair(Action::RETICLE_CLICK, "ReticleClick"), makeAxisPair(Action::RETICLE_X, "ReticleX"), diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index aab8777862..fe88f21a23 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -62,7 +62,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : EntityItem::~EntityItem() { // these pointers MUST be correct at delete, else we probably have a dangling backpointer // to this EntityItem in the corresponding data structure. - assert(!_simulated); + assert(!_simulated || (!_element && !_physicsInfo)); assert(!_element); assert(!_physicsInfo); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 0568a859ab..cc832146e8 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -502,6 +502,12 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, CertificateID, certificateID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, StaticCertificateVersion, staticCertificateVersion, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalPosition, localPosition, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalRotation, localRotation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalVelocity, localVelocity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalAngularVelocity, localAngularVelocity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalDimensions, localDimensions, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, HazeMode, hazeMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, KeyLightMode, keyLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientLightMode, ambientLightMode, ""); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 2e9b386ba5..c80eb0b78f 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -477,6 +477,27 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } } }); + } else { + // Sometimes ESS don't have the entity they are trying to edit in their local tree. In this case, + // convertPropertiesFromScriptSemantics doesn't get called and local* edits will get dropped. + // This is because, on the script side, "position" is in world frame, but in the network + // protocol and in the internal data-structures, "position" is "relative to parent". + // Compensate here. The local* versions will get ignored during the edit-packet encoding. + if (properties.localPositionChanged()) { + properties.setPosition(properties.getLocalPosition()); + } + if (properties.localRotationChanged()) { + properties.setRotation(properties.getLocalRotation()); + } + if (properties.localVelocityChanged()) { + properties.setVelocity(properties.getLocalVelocity()); + } + if (properties.localAngularVelocityChanged()) { + properties.setAngularVelocity(properties.getLocalAngularVelocity()); + } + if (properties.localDimensionsChanged()) { + properties.setDimensions(properties.getLocalDimensions()); + } } }); if (!entityFound) { diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index d799577fc2..06e7069f72 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -158,7 +158,6 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { EntityMotionState* motionState = static_cast(&(*stateItr)); assert(motionState); EntityItemPointer entity = motionState->getEntity(); - entity->setPhysicsInfo(nullptr); // TODO: someday when we invert the entities/physics lib dependencies we can let EntityItem delete its own PhysicsInfo // until then we must do it here delete motionState; diff --git a/libraries/ui/src/MainWindow.cpp b/libraries/ui/src/MainWindow.cpp index 091fd850af..f9fc71e417 100644 --- a/libraries/ui/src/MainWindow.cpp +++ b/libraries/ui/src/MainWindow.cpp @@ -79,12 +79,12 @@ void MainWindow::closeEvent(QCloseEvent* event) { } void MainWindow::moveEvent(QMoveEvent* event) { - emit windowGeometryChanged(QRect(event->pos(), size())); + emit windowGeometryChanged(QRect(QPoint(geometry().x(), geometry().y()), size())); // Geometry excluding the window frame. QMainWindow::moveEvent(event); } void MainWindow::resizeEvent(QResizeEvent* event) { - emit windowGeometryChanged(QRect(QPoint(x(), y()), event->size())); + emit windowGeometryChanged(QRect(QPoint(geometry().x(), geometry().y()), size())); // Geometry excluding the window frame. QMainWindow::resizeEvent(event); } diff --git a/scripts/system/edit.js b/scripts/system/edit.js index cfaf517487..ea22359805 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -116,11 +116,19 @@ var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode"; var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode"; +var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)"; +var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models"; +var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models"; +var MENU_ALLOW_SELECTION_LIGHTS = "Allow Selecting of Lights"; + var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode"; var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; +var SETTING_EDIT_PREFIX = "Edit/"; + + var CREATE_ENABLED_ICON = "icons/tablet-icons/edit-i.svg"; var CREATE_DISABLED_ICON = "icons/tablet-icons/edit-disabled.svg"; @@ -226,7 +234,7 @@ function adjustPositionPerBoundingBox(position, direction, registration, dimensi var TOOLS_PATH = Script.resolvePath("assets/images/tools/"); var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit"; -var GRABBABLE_ENTITIES_MENU_ITEM = "Create Entities As Grabbable (except Zones, Particles, and Lights)"; + var toolBar = (function () { var EDIT_SETTING = "io.highfidelity.isEditing"; // for communication with other scripts @@ -280,7 +288,7 @@ var toolBar = (function () { position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions); properties.position = position; - if (Menu.isOptionChecked(GRABBABLE_ENTITIES_MENU_ITEM) && + if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) && !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) { properties.userData = JSON.stringify({ grabbableKey: { grabbable: true } }); } else { @@ -338,7 +346,6 @@ var toolBar = (function () { if (systemToolbar) { systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); } - Menu.removeMenuItem(GRABBABLE_ENTITIES_MENU_CATEGORY, GRABBABLE_ENTITIES_MENU_ITEM); } var buttonHandlers = {}; // only used to tablet mode @@ -1143,34 +1150,35 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: GRABBABLE_ENTITIES_MENU_CATEGORY, - menuItemName: GRABBABLE_ENTITIES_MENU_ITEM, + menuItemName: MENU_CREATE_ENTITIES_GRABBABLE, afterItem: "Unparent Entity", isCheckable: true, - isChecked: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true), grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", - menuItemName: "Allow Selecting of Large Models", - afterItem: GRABBABLE_ENTITIES_MENU_ITEM, + menuItemName: MENU_ALLOW_SELECTION_LARGE, + afterItem: MENU_CREATE_ENTITIES_GRABBABLE, isCheckable: true, - isChecked: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true), grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", - menuItemName: "Allow Selecting of Small Models", - afterItem: "Allow Selecting of Large Models", + menuItemName: MENU_ALLOW_SELECTION_SMALL, + afterItem: MENU_ALLOW_SELECTION_LARGE, isCheckable: true, - isChecked: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true), grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", - menuItemName: "Allow Selecting of Lights", - afterItem: "Allow Selecting of Small Models", + menuItemName: MENU_ALLOW_SELECTION_LIGHTS, + afterItem: MENU_ALLOW_SELECTION_SMALL, isCheckable: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false), grouping: "Advanced" }); Menu.addMenuItem({ @@ -1275,6 +1283,12 @@ Script.scriptEnding.connect(function () { Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + Settings.setValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE)); + Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE)); + Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL)); + Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(GRABBABLE_ENTITIES_MENU_ITEM)); + + progressDialog.cleanup(); cleanupModelMenus(); tooltip.cleanup(); diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 19d4417a12..3be6ac0b00 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -2,15 +2,7 @@ var GRID_CONTROLS_HTML_URL = Script.resolvePath('../html/gridControls.html'); Grid = function(opts) { var that = {}; - - var colors = [ - { red: 0, green: 0, blue: 0 }, - { red: 255, green: 255, blue: 255 }, - { red: 255, green: 0, blue: 0 }, - { red: 0, green: 255, blue: 0 }, - { red: 0, green: 0, blue: 255 }, - ]; - var colorIndex = 0; + var gridColor = { red: 0, green: 0, blue: 0 }; var gridAlpha = 0.6; var origin = { x: 0, y: +MyAvatar.getJointPosition('LeftToeBase').y.toFixed(1) + 0.1, z: 0 }; var scale = 500; @@ -28,10 +20,10 @@ Grid = function(opts) { position: origin, visible: false, drawInFront: false, - color: colors[0], + color: gridColor, alpha: gridAlpha, minorGridEvery: minorGridEvery, - majorGridEvery: majorGridEvery, + majorGridEvery: majorGridEvery }); that.visible = false; @@ -39,26 +31,38 @@ Grid = function(opts) { that.getOrigin = function() { return origin; - } + }; + + that.getMinorIncrement = function() { + return minorGridEvery; + }; - that.getMinorIncrement = function() { return minorGridEvery; }; that.setMinorIncrement = function(value) { minorGridEvery = value; updateGrid(); - } - that.getMajorIncrement = function() { return majorGridEvery; }; + }; + + that.getMajorIncrement = function() { + return majorGridEvery; + }; + that.setMajorIncrement = function(value) { majorGridEvery = value; updateGrid(); }; - that.getColorIndex = function() { return colorIndex; }; - that.setColorIndex = function(value) { - colorIndex = value; + that.getColor = function() { + return gridColor; + }; + + that.setColor = function(value) { + gridColor = value; updateGrid(); }; - that.getSnapToGrid = function() { return snapToGrid; }; + that.getSnapToGrid = function() { + return snapToGrid; + }; that.setSnapToGrid = function(value) { snapToGrid = value; that.emitUpdate(); @@ -67,9 +71,11 @@ Grid = function(opts) { that.setEnabled = function(enabled) { that.enabled = enabled; updateGrid(); - } + }; - that.getVisible = function() { return that.visible; }; + that.getVisible = function() { + return that.visible; + }; that.setVisible = function(visible, noUpdate) { that.visible = visible; updateGrid(); @@ -77,7 +83,7 @@ Grid = function(opts) { if (!noUpdate) { that.emitUpdate(); } - } + }; that.snapToSurface = function(position, dimensions, registration) { if (!snapToGrid) { @@ -97,7 +103,7 @@ Grid = function(opts) { y: origin.y + (registration.y * dimensions.y), z: position.z }; - } + }; that.snapToGrid = function(position, majorOnly, dimensions, registration) { if (!snapToGrid) { @@ -121,7 +127,7 @@ Grid = function(opts) { position.z = Math.round(position.z / spacing) * spacing; return Vec3.sum(Vec3.sum(position, Vec3.multiplyVbyV(registration, dimensions)), origin); - } + }; that.snapToSpacing = function(delta, majorOnly) { if (!snapToGrid) { @@ -133,11 +139,11 @@ Grid = function(opts) { var snappedDelta = { x: Math.round(delta.x / spacing) * spacing, y: Math.round(delta.y / spacing) * spacing, - z: Math.round(delta.z / spacing) * spacing, + z: Math.round(delta.z / spacing) * spacing }; return snappedDelta; - } + }; that.setPosition = function(newPosition, noUpdate) { @@ -157,7 +163,7 @@ Grid = function(opts) { majorGridEvery: majorGridEvery, gridSize: halfSize, visible: that.visible, - snapToGrid: snapToGrid, + snapToGrid: snapToGrid }); } }; @@ -183,8 +189,8 @@ Grid = function(opts) { majorGridEvery = data.majorGridEvery; } - if (data.colorIndex !== undefined) { - colorIndex = data.colorIndex; + if (data.gridColor) { + gridColor = data.gridColor; } if (data.gridSize) { @@ -196,7 +202,7 @@ Grid = function(opts) { } updateGrid(true); - } + }; function updateGrid(noUpdate) { Overlays.editOverlay(gridOverlay, { @@ -204,8 +210,8 @@ Grid = function(opts) { visible: that.visible && that.enabled, minorGridEvery: minorGridEvery, majorGridEvery: majorGridEvery, - color: colors[colorIndex], - alpha: gridAlpha, + color: gridColor, + alpha: gridAlpha }); if (!noUpdate) { @@ -219,7 +225,7 @@ Grid = function(opts) { that.addListener = function(callback) { that.onUpdate = callback; - } + }; Script.scriptEnding.connect(cleanup); updateGrid(); @@ -238,7 +244,7 @@ GridTool = function(opts) { var webView = null; webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - webView.setVisible = function(value) {}; + webView.setVisible = function(value) { }; horizontalGrid.addListener(function(data) { webView.emitScriptEvent(JSON.stringify(data)); @@ -250,8 +256,8 @@ GridTool = function(opts) { webView.webEventReceived.connect(function(data) { try { data = JSON.parse(data); - } catch(e) { - print("gridTool.js: Error parsing JSON: " + e.name + " data " + data) + } catch (e) { + print("gridTool.js: Error parsing JSON: " + e.name + " data " + data); return; } @@ -280,11 +286,11 @@ GridTool = function(opts) { that.addListener = function(callback) { listeners.push(callback); - } + }; that.setVisible = function(visible) { webView.setVisible(visible); - } + }; return that; }; diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 70456ea493..9c994ed2ea 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -12,9 +12,9 @@ Script.include("/~/system/libraries/utils.js"); if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position){ - position = position || 0; - return this.substr(position, searchString.length) === searchString; - }; + position = position || 0; + return this.substr(position, searchString.length) === searchString; + }; } var SETTING_KEY = "com.highfidelity.avatar.isSitting"; @@ -122,20 +122,10 @@ this.rolesToOverride = function() { return MyAvatar.getAnimationRoles().filter(function(role) { - return !(role.startsWith("right") || role.startsWith("left")); + return !(role.startsWith("right") || role.startsWith("left")); }); } - // Handler for user changing the avatar model while sitting. There's currently an issue with changing avatar models while override role animations are applied, - // so to avoid that problem, re-apply the role overrides once the model has finished changing. - this.modelURLChangeFinished = function () { - print("Sitter's model has FINISHED changing. Reapply anim role overrides."); - var roles = this.rolesToOverride(); - for (i in roles) { - MyAvatar.overrideRoleAnimation(roles[i], ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME); - } - } - this.sitDown = function() { if (this.checkSeatForAvatar()) { print("Someone is already sitting in that chair."); @@ -155,11 +145,11 @@ MyAvatar.characterControllerEnabled = false; MyAvatar.hmdLeanRecenterEnabled = false; var roles = this.rolesToOverride(); - for (i in roles) { + for (var i = 0; i < roles.length; i++) { MyAvatar.overrideRoleAnimation(roles[i], ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME); } - for (var i in OVERRIDEN_DRIVE_KEYS) { + for (i = 0; i < OVERRIDEN_DRIVE_KEYS.length; i++) { MyAvatar.disableDriveKey(OVERRIDEN_DRIVE_KEYS[i]); } @@ -174,14 +164,12 @@ return { headType: 0 }; }, ["headType"]); Script.update.connect(this, this.update); - MyAvatar.onLoadComplete.connect(this, this.modelURLChangeFinished); } this.standUp = function() { print("Standing up (" + this.entityID + ")"); MyAvatar.removeAnimationStateHandler(this.animStateHandlerID); Script.update.disconnect(this, this.update); - MyAvatar.onLoadComplete.disconnect(this, this.modelURLChangeFinished); if (MyAvatar.sessionUUID === this.getSeatUser()) { this.setSeatUser(null); @@ -190,12 +178,12 @@ if (Settings.getValue(SETTING_KEY) === this.entityID) { Settings.setValue(SETTING_KEY, ""); - for (var i in OVERRIDEN_DRIVE_KEYS) { + for (var i = 0; i < OVERRIDEN_DRIVE_KEYS.length; i++) { MyAvatar.enableDriveKey(OVERRIDEN_DRIVE_KEYS[i]); } var roles = this.rolesToOverride(); - for (i in roles) { + for (i = 0; i < roles.length; i++) { MyAvatar.restoreRoleAnimation(roles[i]); } MyAvatar.characterControllerEnabled = true; @@ -272,7 +260,7 @@ // Check if a drive key is pressed var hasActiveDriveKey = false; for (var i in OVERRIDEN_DRIVE_KEYS) { - if (MyAvatar.getRawDriveKey(OVERRIDEN_DRIVE_KEYS[i]) != 0.0) { + if (MyAvatar.getRawDriveKey(OVERRIDEN_DRIVE_KEYS[i]) !== 0.0) { hasActiveDriveKey = true; break; } @@ -343,7 +331,7 @@ } this.cleanupOverlay(); } - + this.clickDownOnEntity = function (id, event) { if (isInEditMode()) { return; @@ -352,4 +340,4 @@ this.sitDown(); } } -}); +}); \ No newline at end of file diff --git a/tools/bake-tools/bake.py b/tools/bake-tools/bake.py index 0c8d5e1048..cad638c911 100644 --- a/tools/bake-tools/bake.py +++ b/tools/bake-tools/bake.py @@ -1,6 +1,16 @@ import os, json, sys, shutil, subprocess, shlex, time EXE = os.environ['HIFI_OVEN'] +def getRelativePath(path1, path2, stop): + parts1 = path1.split('/'); + parts2 = path2.split('/'); + if len(parts1) <= len(parts2): + for part in parts1: + if part != stop and part != '': + index = parts2.index(part) + parts2.pop(index) + return os.path.join(*parts2) + def listFiles(directory, extension): items = os.listdir(directory) fileList = [] @@ -44,18 +54,20 @@ def bakeFile(filePath, outputDirectory): groupKTXFiles(outputDirectory, bakedFile) def bakeFilesInDirectory(directory, outputDirectory): + rootDirectory = os.path.basename(os.path.normpath(directory)) for root, subFolders, filenames in os.walk(directory): for filename in filenames: + appendPath = getRelativePath(directory, root, rootDirectory); if filename.endswith('.fbx'): filePath = os.sep.join([root, filename]) absFilePath = os.path.abspath(filePath) - outputFolder = os.path.join(outputDirectory, os.path.relpath(root)) + outputFolder = os.path.join(outputDirectory, appendPath) print "Baking file: " + filename bakeFile(absFilePath, outputFolder) else: filePath = os.sep.join([root, filename]) absFilePath = os.path.abspath(filePath) - outputFolder = os.path.join(outputDirectory, os.path.relpath(root)) + outputFolder = os.path.join(outputDirectory, appendPath) newFilePath = os.sep.join([outputFolder, filename]) createDirectory(outputFolder) print "moving file: " + filename + " to: " + outputFolder