Merge remote-tracking branch 'upstream/master' into pivot

This commit is contained in:
HifiExperiments 2020-12-18 17:33:24 -08:00
commit f33c7de67a
56 changed files with 566 additions and 292 deletions

View file

@ -14,7 +14,9 @@ env:
RELEASE_TYPE: PR
RELEASE_NUMBER: ${{ github.event.number }}
VERSION_CODE: ${{ github.event.number }}
# Sentry Crash Reporting
CMAKE_BACKTRACE_URL: ${{ secrets.MINIDUMP_TOKEN }}
CMAKE_BACKTRACE_TOKEN: PR_${{ github.event.number }}_${{ github.sha }}
# OSX specific variables
DEVELOPER_DIR: /Applications/Xcode_11.2.app/Contents/Developer
@ -169,7 +171,7 @@ jobs:
- name: Build for Android + Quest
if: matrix.build_type == 'android'
shell: bash
working-directory: ${{runner.workspace}}/project-athena
working-directory: ${{runner.workspace}}/vircadia
run: |
echo "Pre-cache the vcpkg managed dependencies"
$PYTHON_EXEC prebuild.py --build-root ${{runner.workspace}}/build --android interface

View file

@ -66,7 +66,7 @@ The above code to suppress modules is not necessary, but will speed up the build
### Clone the repository
`git clone https://github.com/kasenvr/project-athena.git`
`git clone https://github.com/vircadia/vircadia.git`
## Building & Running
@ -119,4 +119,4 @@ Some things you can try if you want to do a clean build
* In Android Studio, click _File > Invalidate Caches / Restart_ and select _Invalidate and Restart_
If you see lots of "couldn't acquire lock" errors,
* Open Task Manager and close any running Clang / Gradle processes
* Open Task Manager and close any running Clang / Gradle processes

View file

@ -1,9 +1,11 @@
# Build Linux
*Last Updated on April 11, 2020*
*Last Updated on December 1, 2020*
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Linux specific instructions are found in this file.
You can use the [Vircadia Builder](https://github.com/vircadia/vircadia-builder) to build on Linux more easily. Alternatively, you can follow the manual steps below.
## Ubuntu 16.04/18.04 specific build guide
### Ubuntu 16.04 only
Add the following line to *.bash_profile*
@ -76,7 +78,7 @@ sudo apt-get install nodejs
Clone this repository:
```bash
git clone https://github.com/kasenvr/project-athena.git
git clone https://github.com/vircadia/vircadia.git
```
To compile a DEV version checkout the branch you need. To get a list of all tags:
@ -86,7 +88,7 @@ git fetch -a
Then checkout the main branch with:
```bash
git checkout kasen/core
git checkout master
```
### Using a custom Qt build
@ -103,7 +105,7 @@ Qt must be installed in `$HIFI_QT_BASE/$VIRCADIA_USE_QT_VERSION/qt5-install`.
Create the build directory:
```bash
cd project-athena
cd vircadia
mkdir build
cd build
```

View file

@ -107,7 +107,7 @@ Note: You can also run Interface by launching it from command line or File Explo
For any problems after Step #6, first try this:
* Delete your locally cloned copy of the Vircadia repository
* Restart your computer
* Redownload the [repository](https://github.com/kasenvr/project-athena)
* Redownload the [repository](https://github.com/vircadia/vircadia)
* Restart directions from Step #6
#### CMake gives you the same error message repeatedly after the build fails

View file

@ -41,6 +41,12 @@ endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" "${EXTERNAL_BUILD_ASSETS}")
MESSAGE(STATUS "EXTERNAL_BUILD_ASSETS: ${EXTERNAL_BUILD_ASSETS}")
set(GLES_OPTION "$ENV{USE_GLES}")
# Will affect VCPKG dependencies
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/USE_GLES.txt" "${GLES_OPTION}")
MESSAGE(STATUS "GLES_OPTION: ${GLES_OPTION}")
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/TargetPython.cmake")
target_python()
@ -129,7 +135,6 @@ set(BUILD_TESTS_OPTION OFF)
set(BUILD_MANUAL_TESTS_OPTION ${BUILD_TESTS_OPTION})
set(BUILD_TOOLS_OPTION ON)
set(BUILD_INSTALLER_OPTION ON)
set(GLES_OPTION OFF)
set(DISABLE_QML_OPTION OFF)
set(DOWNLOAD_SERVERLESS_CONTENT_OPTION OFF)

View file

@ -1,3 +1,4 @@
The project embraces distributed development and if you'd like to help, it would be greatly appreciated. Just open a pull request with the revisions.
Contributing
@ -6,7 +7,7 @@ Contributing
2. Clone your fork of the repository locally
```
git clone git://github.com/USERNAME/project-athena.git
git clone git://github.com/USERNAME/vircadia.git
```
3. Create a new branch
@ -20,7 +21,7 @@ Contributing
6. Update your branch
```
git remote add upstream https://github.com/kasenvr/project-athena
git remote add upstream https://github.com/vircadia/vircadia
git pull upstream master
```
@ -35,13 +36,22 @@ Contributing
*You can follow [GitHub's guide](https://help.github.com/articles/creating-a-pull-request) to find out how to create a pull request.*
Tips for Pull Requests
===
To make the QA process go as smoothly as possible.
1. Have a basic description in your pull request.
2. Write a basic test plan if you are altering or adding features.
3. If a new API is added, try to make sure that some level of basic documentation on how you can utilize it is included.
4. If an added API or feature requires an external service, try to document or link to instructions on how to create a basic working setup.
Reporting Bugs
===
1. Always update to the latest code on master, we make many merges every day and it is possible the bug has already been fixed!
2. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already reported the same bug.
3. [Add](https://github.com/kasenvr/project-athena/issues/new) your report to the issues list!
2. Search [issues](https://github.com/vircadia/vircadia/issues) to make sure that somebody has not already reported the same bug.
3. [Add](https://github.com/vircadia/vircadia/issues/new) your report to the issues list!
Requesting a Feature
===
1. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already requested the same feature.
2. [Add](https://github.com/kasenvr/project-athena/issues/new) your request to the issues list!
1. Search [issues](https://github.com/vircadia/vircadia/issues) to make sure that somebody has not already requested the same feature.
2. [Add](https://github.com/vircadia/vircadia/issues/new) your request to the issues list!

View file

@ -8,17 +8,17 @@ Vircadia is a 3D social software project seeking to incrementally bring about a
### Releases
[View Releases here](https://github.com/kasenvr/project-athena/releases/)
[View Releases here](https://github.com/vircadia/vircadia/releases/)
### How to build the Interface
[For Windows](https://github.com/kasenvr/project-athena/blob/master/BUILD_WIN.md)
[For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md)
[For Mac](https://github.com/kasenvr/project-athena/blob/master/BUILD_OSX.md)
[For Mac](https://github.com/vircadia/vircadia/blob/master/BUILD_OSX.md)
[For Linux](https://github.com/kasenvr/project-athena/blob/master/BUILD_LINUX.md)
[For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md)
[For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder)
[For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
### How to deploy a Server
@ -26,13 +26,13 @@ Vircadia is a 3D social software project seeking to incrementally bring about a
### How to build a Server
[For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder)
[For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
### How to generate an Installer
[For Windows](https://github.com/kasenvr/project-athena/blob/master/INSTALL.md)
[For Windows](https://github.com/vircadia/vircadia/blob/master/INSTALL.md)
[For Linux - AppImage - Vircadia Builder](https://github.com/kasenvr/vircadia-builder/blob/master/README.md#building-appimages)
[For Linux - AppImage - Vircadia Builder](https://github.com/vircadia/vircadia-builder/blob/master/README.md#building-appimages)
### Boot to Metaverse: The Goal

View file

@ -17,7 +17,7 @@ test -z "$STABLE_BUILD" && export STABLE_BUILD=0
docker run \
--rm \
--security-opt seccomp:unconfined \
-v "${WORKSPACE}":/home/gha/project-athena \
-v "${WORKSPACE}":/home/gha/vircadia \
-e RELEASE_NUMBER \
-e RELEASE_TYPE \
-e ANDROID_APP \

View file

@ -72,17 +72,17 @@ RUN mkdir "$HIFI_BASE" && \
mkdir "$HIFI_ANDROID_PRECOMPILED"
# Download the repo
RUN git clone https://github.com/kasenvr/project-athena.git
RUN git clone https://github.com/vircadia/vircadia.git
WORKDIR /home/gha/project-athena
WORKDIR /home/gha/vircadia
RUN mkdir build
# Pre-cache the vcpkg managed dependencies
WORKDIR /home/gha/project-athena/build
WORKDIR /home/gha/vircadia/build
RUN python3 ../prebuild.py --build-root `pwd` --android interface
# Pre-cache the gradle dependencies
WORKDIR /home/gha/project-athena/android
WORKDIR /home/gha/vircadia/android
RUN ./gradlew -m tasks -PHIFI_ANDROID_PRECOMPILED=$HIFI_ANDROID_PRECOMPILED
#RUN ./gradlew extractDependencies -PHIFI_ANDROID_PRECOMPILED=$HIFI_ANDROID_PRECOMPILED

View file

@ -1,6 +1,6 @@
macro(target_oculus_mobile)
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/oculus_1.22/VrApi)
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/ovr_sdk_mobile_1.37.0/VrApi)
# Mobile SDK
set(OVR_MOBILE_INCLUDE_DIRS ${INSTALL_DIR}/Include)
@ -12,7 +12,7 @@ macro(target_oculus_mobile)
target_link_libraries(${TARGET_NAME} ${OVR_MOBILE_LIBRARIES})
# Platform SDK
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/oculusPlatform)
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/ovr_platform_sdk_23.0.0)
set(OVR_PLATFORM_INCLUDE_DIRS ${INSTALL_DIR}/Include)
target_include_directories(${TARGET_NAME} PRIVATE ${OVR_PLATFORM_INCLUDE_DIRS})
set(OVR_PLATFORM_LIBRARIES ${INSTALL_DIR}/Android/libs/arm64-v8a/libovrplatformloader.so)

View file

@ -19,7 +19,7 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO kasenvr/etc2comp
REPO vircadia/etc2comp
REF 7f1843bf07825c21cab711360c1ddbad04641036
SHA512 d747076acda8537d39585858c793a35c3dcc9ef283d723619a47f8c81ec1454c95b3340ad35f0655a939eae5b8271c801c48a9a7568311a01903a344c44af25b
HEAD_REF master

View file

@ -2,13 +2,22 @@ include(vcpkg_common_functions)
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS)
file(READ "${VCPKG_ROOT_DIR}/_env/USE_GLES.txt" USE_GLES)
# GitHub Actions Android builds fail with `FILENAME` set while desktop builds with GLES fail without a set `FILENAME`.
if (ANDROID)
vcpkg_download_distfile(
SOURCE_ARCHIVE
URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip
SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65
)
elseif (USE_GLES)
vcpkg_download_distfile(
SOURCE_ARCHIVE
URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip
SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65
FILENAME glad32es.zip
)
else()
# else Linux desktop
vcpkg_download_distfile(

View file

@ -3,7 +3,7 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO kasenvr/scribe
REPO vircadia/scribe
REF 1bd638a36ca771e5a68d01985b6389b71835cbd2
SHA512 dbe241d86df3912e544f6b9839873f9875df54efc93822b145e7b13243eaf2e3d690bc8a28b1e52d05bdcd7e68fca6b0b2f5c43ffd0f56a9b7a50d54dcf9e31e
HEAD_REF master

View file

@ -9,7 +9,7 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO kasenvr/nvidia-texture-tools
REPO vircadia/nvidia-texture-tools
REF 330c4d56274a0f602a5c70596e2eb670a4ed56c2
SHA512 4c0bc2f369120d696cc27710b6d33086b27eef55f537ec66b9a5c8b1839bc2426c0413670b0f65be52c5d353468f0126dfe024be1f0690611d4d7e33ac530127
HEAD_REF master

View file

@ -3,8 +3,8 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO oneapi-src/oneTBB
REF 4bdba61bafc6ba2d636f31564f1de5702d365cf7
SHA512 f2a8d7e0476f846039390f4a79af3fe13770e23b01bf4741e738136f7ddb401357a0e50f35212e8d0fa5fc4cf1563418337309227d7243fc3676edd406ae652d
REF eca91f16d7490a8abfdee652dadf457ec820cc37
SHA512 7144e1dc68304b5358e6ea330431b6f0c61fadb147efa353a5b242777d6fabf7b8cf99b79cffb51b49b911dd17a9f1879619d6eebdf319f23ec3235c89cffc25
HEAD_REF tbb_2019
PATCHES fix-static-build.patch
)

View file

@ -2,7 +2,7 @@
//
// index.html
//
// Created by kasenvr@gmail.com on 21 Jul 2020
// Created by somnilibertas@gmail.com on 21 Jul 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.

View file

@ -1,3 +1,3 @@
// Here you can put a script that will be run by an assignment-client (AC)
// For examples, please go to https://github.com/kasenvr/project-athena/tree/master/script-archive/acScripts
// For examples, please go to https://github.com/vircadia/vircadia/tree/master/script-archive/acScripts
// The directory named acScripts contains assignment-client specific scripts you can try.

View file

@ -39,15 +39,15 @@ ANDROID_PACKAGES = {
'sharedLibFolder': 'lib',
'includeLibs': ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so']
},
'oculus_1.22': {
'file': 'ovr_sdk_mobile_1.22.zip',
'checksum': '1ac3c5b0521e5406f287f351015daff8',
'ovr_sdk_mobile_1.37.0': {
'file': 'ovr_sdk_mobile_1.37.0.zip',
'checksum': '6040e1966f335a3e5015295154cd7383',
'sharedLibFolder': 'VrApi/Libs/Android/arm64-v8a/Release',
'includeLibs': ['libvrapi.so']
},
'oculusPlatform': {
'file': 'OVRPlatformSDK_v1.34.0.zip',
'checksum': '16e4c5f39520f122bc49cb6d5bb88289',
'ovr_platform_sdk_23.0.0': {
'file': 'ovr_platform_sdk_23.0.0.zip',
'checksum': '29d02b560f60d0fa7b8a64cd965dd55b',
'sharedLibFolder': 'Android/libs/arm64-v8a',
'includeLibs': ['libovrplatformloader.so']
},

View file

@ -12,7 +12,7 @@ import functools
print = functools.partial(print, flush=True)
# Encapsulates the vcpkg system
# Encapsulates the vcpkg system
class QtDownloader:
CMAKE_TEMPLATE = """
# this file auto-generated by hifi_qt.py
@ -72,7 +72,7 @@ endif()
self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz'
elif u_major == 19 and u_minor == 10:
self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.6-ubuntu-19.10.tar.xz'
elif u_major > 18 and ( u_major != 19 and u_minor != 4):
elif u_major > 19:
print("We don't support " + distro.name(pretty=True) + " yet. Perhaps consider helping us out?")
raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!')
else:
@ -81,7 +81,7 @@ endif()
else:
print("Sorry, " + distro.name(pretty=True) + " is not supported. Please consider helping us out.")
print("It's also possible to build Qt for your distribution, please see the documentation at:")
print("https://github.com/kasenvr/project-athena/tree/kasen/core/tools/qt-builder")
print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder")
raise Exception('UNKNOWN LINUX VERSION!!!')
else:
print("System : " + platform.system())

View file

@ -309,8 +309,8 @@ FocusScope {
if (child.hasOwnProperty("modality")) {
var mappedPoint = mapToItem(child, point.x, point.y);
if (child.hasOwnProperty("frame")) {
var outLine = child.frame.children[2];
var framePoint = outLine.mapFromGlobal(point.x, point.y);
var outLine = child.frame.children[2]; // sizeOutline
var framePoint = mapToItem(outLine, point.x, point.y);
if (outLine.contains(framePoint)) {
return true;
}

View file

@ -54,10 +54,10 @@ Rectangle {
textFormat: Text.StyledText
linkColor: "#00B4EF"
color: "white"
text: "<a href=\"https://github.com/kasenvr/project-athena\">Vircadia Github</a>."
text: "<a href=\"https://github.com/vircadia/vircadia\">Vircadia Github</a>."
size: 20
onLinkActivated: {
About.openUrl("https:/github.com/kasenvr/project-athena");
About.openUrl("https:/github.com/vircadia/vircadia");
}
}

View file

@ -2,8 +2,8 @@
// EntityScriptQMLWhitelist.qml
// interface/resources/qml/hifi/dialogs/security
//
// Created by Kasen IO on 2019.12.05 | realities.dev | kasenvr@gmail.com
// Copyright 2019 Kasen IO
// Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com
// Copyright 2019 Kalila L.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html

View file

@ -314,7 +314,7 @@ Rectangle {
onClicked: {
lightboxPopup.titleText = "Script Plugin Infrastructure";
lightboxPopup.bodyText = "Toggles the activation of scripting plugins in the 'plugins/scripting' folder. \n\n"
+ "Created by:\n humbletim@gmail.com\n kasenvr@gmail.com";
+ "Created by:\n humbletim@gmail.com\n somnilibertas@gmail.com";
lightboxPopup.button1text = "OK";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;

View file

@ -27,7 +27,6 @@ Item {
readonly property int frameMarginRight: frame.decoration ? frame.decoration.frameMarginRight : 0
readonly property int frameMarginTop: frame.decoration ? frame.decoration.frameMarginTop : 0
readonly property int frameMarginBottom: frame.decoration ? frame.decoration.frameMarginBottom : 0
readonly property int offsetCorrection: 20
// Frames always fill their parents, but their decorations may extend
// beyond the window via negative margin sizes
@ -76,7 +75,7 @@ Item {
Rectangle {
id: sizeOutline
x: -frameMarginLeft
y: -frameMarginTop - offsetCorrection
y: -frameMarginTop
width: window ? window.width + frameMarginLeft + frameMarginRight + 2 : 0
height: window ? window.height + frameMarginTop + frameMarginBottom + 2 : 0
color: hifi.colors.baseGrayHighlight15

View file

@ -89,6 +89,7 @@ int main(int argc, const char* argv[]) {
QCommandLineOption displayNameOption("displayName", "set user display name <string>", "string");
QCommandLineOption setBookmarkOption("setBookmark", "set bookmark key=value pair", "string");
QCommandLineOption defaultScriptOverrideOption("defaultScriptsOverride", "override defaultsScripts.js", "string");
QCommandLineOption forceCrashReportingOption("forceCrashReporting", "Force crash reporting to initialize");
parser.addOption(urlOption);
parser.addOption(noLauncherOption);
@ -103,6 +104,7 @@ int main(int argc, const char* argv[]) {
parser.addOption(displayNameOption);
parser.addOption(setBookmarkOption);
parser.addOption(defaultScriptOverrideOption);
parser.addOption(forceCrashReportingOption);
if (!parser.parse(arguments)) {
std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam
@ -218,8 +220,9 @@ int main(int argc, const char* argv[]) {
}
qDebug() << "UserActivityLogger is enabled:" << ual.isEnabled();
qDebug() << "Crash handler logger is enabled:" << ual.isCrashMonitorEnabled();
if (ual.isCrashMonitorEnabled()) {
bool isCrashHandlerEnabled = ual.isCrashMonitorEnabled() || parser.isSet(forceCrashReportingOption);
qDebug() << "Crash handler logger is enabled:" << isCrashHandlerEnabled;
if (isCrashHandlerEnabled) {
auto crashHandlerStarted = startCrashHandler(argv[0]);
qDebug() << "Crash handler started:" << crashHandlerStarted;
}

View file

@ -23,7 +23,7 @@ OverlayConductor::OverlayConductor() {
OverlayConductor::~OverlayConductor() {
}
bool OverlayConductor::headOutsideOverlay() const {
bool OverlayConductor::headNotCenteredInOverlay() const {
glm::mat4 hmdMat = qApp->getHMDSensorPose();
glm::vec3 hmdPos = extractTranslation(hmdMat);
glm::vec3 hmdForward = transformVectorFast(hmdMat, glm::vec3(0.0f, 0.0f, -1.0f));
@ -32,8 +32,8 @@ bool OverlayConductor::headOutsideOverlay() const {
glm::vec3 uiPos = uiTransform.getTranslation();
glm::vec3 uiForward = uiTransform.getRotation() * glm::vec3(0.0f, 0.0f, -1.0f);
const float MAX_COMPOSITOR_DISTANCE = 0.99f; // If you're 1m from center of ui sphere, you're at the surface.
const float MAX_COMPOSITOR_ANGLE = 180.0f; // rotation check is effectively disabled
const float MAX_COMPOSITOR_DISTANCE = 0.33f;
const float MAX_COMPOSITOR_ANGLE = 90.0f;
if (glm::distance(uiPos, hmdPos) > MAX_COMPOSITOR_DISTANCE ||
glm::dot(uiForward, hmdForward) < cosf(glm::radians(MAX_COMPOSITOR_ANGLE))) {
return true;
@ -70,6 +70,8 @@ bool OverlayConductor::updateAvatarIsAtRest() {
void OverlayConductor::centerUI() {
// place the overlay at the current hmd position in sensor space
auto camMat = cancelOutRollAndPitch(qApp->getHMDSensorPose());
// Set its radius.
camMat = glm::scale(camMat, glm::vec3(HUD_RADIUS));
qApp->getApplicationCompositor().setModelTransform(Transform(camMat));
}
@ -83,7 +85,6 @@ void OverlayConductor::update(float dt) {
if (!desktop) {
return;
}
bool currentVisible = !desktop->property("pinned").toBool();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
// centerUI when hmd mode is first enabled and mounted
@ -96,24 +97,24 @@ void OverlayConductor::update(float dt) {
_hmdMode = false;
}
bool shouldRecenter = false;
if (_suppressedByHead) {
if (updateAvatarIsAtRest()) {
_suppressedByHead = false;
shouldRecenter = true;
}
} else {
if (_hmdMode && headOutsideOverlay()) {
_suppressedByHead = true;
}
bool initiateRecenter = false;
if (_hmdMode && headNotCenteredInOverlay()) {
initiateRecenter = true;
}
bool shouldRecenter = false;
if (initiateRecenter || _suppressedByHead) {
_suppressedByHead = !updateAvatarIsAtRest();
shouldRecenter = !_suppressedByHead;
}
bool currentVisible = !desktop->property("pinned").toBool();
bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && !_suppressedByHead;
if (targetVisible != currentVisible) {
offscreenUi->setPinned(!targetVisible);
}
if (shouldRecenter && !_suppressedByHead) {
if (shouldRecenter) {
centerUI();
}
#endif

View file

@ -22,7 +22,7 @@ public:
void centerUI();
private:
bool headOutsideOverlay() const;
bool headNotCenteredInOverlay() const;
bool updateAvatarIsAtRest();
#if !defined(DISABLE_QML)

View file

@ -41,10 +41,10 @@ static const float reticleSize = TWO_PI / 100.0f;
//EntityItemID CompositorHelper::_noItemId;
static QString _tooltipId;
const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(3960, 1188); // ~10% more pixel density than old version, 72dx240d FOV
const QRect CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT = QRect(956, 0, 2048, 1188); // don't include entire width only center 2048
const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(2640, 1188);
const QRect CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT = QRect(296, 0, 2048, 1188); // Center 2048 pixels.
const float CompositorHelper::VIRTUAL_UI_ASPECT_RATIO = (float)VIRTUAL_SCREEN_SIZE.x / (float)VIRTUAL_SCREEN_SIZE.y;
const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI * 3.0f / 2.0f, PI * 3.0f / 2.0f / VIRTUAL_UI_ASPECT_RATIO);
const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI, PI / VIRTUAL_UI_ASPECT_RATIO);
const vec2 CompositorHelper::MOUSE_EXTENTS_ANGULAR_SIZE = vec2(PI * 2.0f, PI * 0.95f); // horizontal: full sphere, vertical: ~5deg from poles
const vec2 CompositorHelper::MOUSE_EXTENTS_PIXELS = vec2(VIRTUAL_SCREEN_SIZE) * (MOUSE_EXTENTS_ANGULAR_SIZE / VIRTUAL_UI_TARGET_FOV);
@ -384,9 +384,9 @@ bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, c
glm::vec3 localPosition = transformPoint(worldToUi, position);
glm::vec3 localDirection = glm::normalize(transformVectorFast(worldToUi, direction));
const float UI_RADIUS = 1.0f;
const float UNIT_RADIUS = 1.0f;
float intersectionDistance;
if (raySphereIntersect(localDirection, localPosition, UI_RADIUS, &intersectionDistance)) {
if (raySphereIntersect(localDirection, localPosition, UNIT_RADIUS, &intersectionDistance)) {
result = transformPoint(uiToWorld, localPosition + localDirection * intersectionDistance);
#ifdef WANT_DEBUG
DebugDraw::getInstance().drawRay(position, result, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
@ -407,9 +407,8 @@ bool CompositorHelper::calculateParabolaUICollisionPoint(const glm::vec3& origin
glm::vec3 localVelocity = glm::normalize(transformVectorFast(worldToUi, velocity));
glm::vec3 localAcceleration = glm::normalize(transformVectorFast(worldToUi, acceleration));
const float UI_RADIUS = 1.0f;
float intersectionDistance;
if (findParabolaSphereIntersection(localOrigin, localVelocity, localAcceleration, glm::vec3(0.0f), UI_RADIUS, intersectionDistance)) {
if (findParabolaSphereIntersection(localOrigin, localVelocity, localAcceleration, glm::vec3(0.0f), HUD_RADIUS, intersectionDistance)) {
result = origin + velocity * intersectionDistance + 0.5f * acceleration * intersectionDistance * intersectionDistance;
parabolicDistance = intersectionDistance;
return true;

View file

@ -27,7 +27,8 @@
class ReticleInterface;
const float DEFAULT_RETICLE_DEPTH = 1.0f; // FIXME - probably should be based on UI radius
const float HUD_RADIUS = 1.5f;
const float DEFAULT_RETICLE_DEPTH = HUD_RADIUS;
const float MAGNIFY_WIDTH = 220.0f;
const float MAGNIFY_HEIGHT = 100.0f;
@ -154,7 +155,7 @@ private:
std::unique_ptr<QPropertyAnimation> _alphaPropertyAnimation;
std::atomic<bool> _reticleVisible { true };
std::atomic<float> _reticleDepth { 1.0f };
std::atomic<float> _reticleDepth { DEFAULT_RETICLE_DEPTH };
// NOTE: when the compositor is running in HMD mode, it will control the reticle position as a custom
// application specific position, when it's in desktop mode, the reticle position will simply move

View file

@ -716,7 +716,7 @@ void RenderableModelEntityItem::setJointMap(std::vector<int> jointMap) {
int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) {
int result = -1;
int mapSize = (int) _jointMap.size();
int mapSize = (int)_jointMap.size();
if (modelJointIndex >= 0 && modelJointIndex < mapSize) {
result = _jointMap[modelJointIndex];
}

View file

@ -35,11 +35,6 @@ class GLPaintEngine : public QPaintEngine {
};
GLWidget::GLWidget() {
#ifdef Q_OS_LINUX
// Cause GLWidget::eventFilter to be called.
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
qApp->installEventFilter(this);
#endif
setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_PaintOnScreen);
@ -118,39 +113,6 @@ bool GLWidget::event(QEvent* event) {
return QWidget::event(event);
}
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
//
// This filter catches events before QMenuBar can steal the keyboard focus.
// The idea was borrowed from
// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html
bool GLWidget::eventFilter(QObject*, QEvent* event) {
switch (event->type()) {
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::ShortcutOverride:
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) {
if (event->type() == QEvent::KeyPress) {
keyPressEvent(keyEvent);
} else if (event->type() == QEvent::KeyRelease) {
keyReleaseEvent(keyEvent);
} else {
QWidget::event(event);
}
return true;
}
}
default:
break;
}
return false;
}
bool GLWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) {
#ifdef Q_OS_WIN32
MSG* win32message = static_cast<MSG*>(message);

View file

@ -42,9 +42,6 @@ protected:
virtual bool event(QEvent* event) override;
gl::Context* _context { nullptr };
private slots:
virtual bool eventFilter(QObject*, QEvent* event) override;
private:
QPaintEngine* _paintEngine { nullptr };
bool _vsyncSupported { false };

View file

@ -153,7 +153,7 @@ void GLBackend::init() {
if (vendor.contains("NVIDIA") ) {
qCDebug(gpugllogging) << "NVIDIA card detected";
#if !defined(Q_OS_ANDROID)
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
GL_GET_INTEGER(GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX);
GL_GET_INTEGER(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX);
GL_GET_INTEGER(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX);
@ -170,7 +170,7 @@ void GLBackend::init() {
} else if (vendor.contains("ATI")) {
qCDebug(gpugllogging) << "ATI card detected";
#if !defined(Q_OS_ANDROID)
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
GL_GET_INTEGER(TEXTURE_FREE_MEMORY_ATI);
#endif
@ -219,19 +219,21 @@ void GLBackend::init() {
}
size_t GLBackend::getAvailableMemory() {
GLint mem;
// GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX returns 1 value
// GL_TEXTURE_FREE_MEMORY_ATI returns 4 values, we only need the first
GLint mem[4] = {0,0,0,0};
switch( _videoCard ) {
case NVIDIA:
#if !defined(Q_OS_ANDROID)
glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &mem);
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &mem[0]);
#endif
return mem * BYTES_PER_KIB;
return mem[0] * BYTES_PER_KIB;
case ATI:
#if !defined(Q_OS_ANDROID)
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &mem);
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &mem[0]);
#endif
return mem * BYTES_PER_KIB;
return mem[0] * BYTES_PER_KIB;
case MESA:
return 0; // Don't know the current value
case Unknown:
@ -1002,4 +1004,4 @@ void GLBackend::setCameraCorrection(const Mat4& correction, const Mat4& prevRend
void GLBackend::syncProgram(const gpu::ShaderPointer& program) {
gpu::gl::GLShader::sync(*this, *program);
}
}

View file

@ -72,7 +72,7 @@ namespace NetworkingConstants {
const QUrl HELP_FORUM_URL { "https://forums.vircadia.dev" };
const QUrl HELP_SCRIPTING_REFERENCE_URL{ "https://apidocs.vircadia.dev/" };
const QUrl HELP_RELEASE_NOTES_URL{ "https://docs.vircadia.dev/release-notes.html" };
const QUrl HELP_BUG_REPORT_URL{ "https://github.com/kasenvr/project-athena/issues" };
const QUrl HELP_BUG_REPORT_URL{ "https://github.com/vircadia/vircadia/issues" };
const QString DEFAULT_VIRCADIA_ADDRESS = "file:///~/serverless/tutorial.json";
const QString DEFAULT_HOME_ADDRESS = "file:///~/serverless/tutorial.json";

View file

@ -31,9 +31,9 @@ static inline void for_each_eye(const std::function<void(ovrEye)>& f) {
f(VRAPI_EYE_RIGHT);
}
static inline void for_each_hand(const std::function<void(ovrHandedness)>& f) {
f(VRAPI_HAND_LEFT);
f(VRAPI_HAND_RIGHT);
static inline void for_each_hand(const std::function<void(ovrTrackedDeviceTypeId)>& f) {
f(VRAPI_TRACKED_DEVICE_HAND_LEFT);
f(VRAPI_TRACKED_DEVICE_HAND_RIGHT);
}
static inline glm::mat4 toGlm(const ovrMatrix4f& om) {

View file

@ -324,7 +324,7 @@ struct VrSurface : public TaskQueue {
vrapi_SetTrackingSpace( session, VRAPI_TRACKING_SPACE_LOCAL);
vrapi_SetPerfThread(session, VRAPI_PERF_THREAD_TYPE_RENDERER, gettid());
vrapi_SetClockLevels(session, 2, 4);
vrapi_SetExtraLatencyMode(session, VRAPI_EXTRA_LATENCY_MODE_DYNAMIC);
vrapi_SetExtraLatencyMode(session, VRAPI_EXTRA_LATENCY_MODE_ON);
// Generates a warning on the quest: "vrapi_SetDisplayRefreshRate: Dynamic Display Refresh Rate not supported"
// vrapi_SetDisplayRefreshRate(session, 72);
});

View file

@ -31,7 +31,7 @@ const quint64 LOST_TRACKING_DELAY = 3000000;
namespace ovr {
controller::Pose toControllerPose(ovrHandedness hand, const ovrRigidBodyPosef& handPose) {
controller::Pose toControllerPose(ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose) {
// When the sensor-to-world rotation is identity the coordinate axes look like this:
//
// user
@ -111,7 +111,7 @@ namespace ovr {
return pose;
}
controller::Pose toControllerPose(ovrHandedness hand,
controller::Pose toControllerPose(ovrTrackedDeviceTypeId hand,
const ovrRigidBodyPosef& handPose,
const ovrRigidBodyPosef& lastHandPose) {
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
@ -165,9 +165,9 @@ public:
private:
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData,
ovrHandedness hand, const ovrRigidBodyPosef& handPose);
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose);
void handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData,
ovrHandedness hand, const ovrRigidBodyPosef& handPose);
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose);
void handleHeadPose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData,
const ovrRigidBodyPosef& headPose);
@ -379,9 +379,9 @@ void OculusMobileInputDevice::update(float deltaTime, const controller::InputCal
handleHeadPose(deltaTime, inputCalibrationData, _headTracking.HeadPose);
static const auto REQUIRED_HAND_STATUS = VRAPI_TRACKING_STATUS_ORIENTATION_TRACKED | VRAPI_TRACKING_STATUS_POSITION_TRACKED;
ovr::for_each_hand([&](ovrHandedness hand) {
size_t handIndex = (hand == VRAPI_HAND_LEFT) ? 0 : 1;
int controller = (hand == VRAPI_HAND_LEFT) ? controller::LEFT_HAND : controller::RIGHT_HAND;
ovr::for_each_hand([&](ovrTrackedDeviceTypeId hand) {
size_t handIndex = (hand == VRAPI_TRACKED_DEVICE_HAND_LEFT) ? 0 : 1;
int controller = (hand == VRAPI_TRACKED_DEVICE_HAND_LEFT) ? controller::LEFT_HAND : controller::RIGHT_HAND;
auto& handData = _hands[handIndex];
const auto& tracking = handData.tracking;
++numTrackedControllers;
@ -476,7 +476,7 @@ void OculusMobileInputDevice::focusOutEvent() {
void OculusMobileInputDevice::handlePose(float deltaTime,
const controller::InputCalibrationData& inputCalibrationData,
ovrHandedness hand, const ovrRigidBodyPosef& handPose) {
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose) {
auto poseId = (hand == VRAPI_HAND_LEFT) ? controller::LEFT_HAND : controller::RIGHT_HAND;
auto& pose = _poseStateMap[poseId];
pose = ovr::toControllerPose(hand, handPose);
@ -507,7 +507,7 @@ void OculusMobileInputDevice::handleHeadPose(float deltaTime,
}
void OculusMobileInputDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData,
ovrHandedness hand, const ovrRigidBodyPosef& handPose) {
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose) {
auto poseId = (hand == VRAPI_HAND_LEFT ? controller::LEFT_HAND : controller::RIGHT_HAND);
auto& pose = _poseStateMap[poseId];
const auto& lastHandPose = (hand == VRAPI_HAND_LEFT) ? _hands[0].lastPose : _hands[1].lastPose;

View file

@ -980,7 +980,7 @@ void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePoi
render::Transaction transaction;
for (int i = 0; i < (int) _modelMeshRenderItemIDs.size(); i++) {
for (int i = 0; i < (int)_modelMeshRenderItemIDs.size(); i++) {
auto itemID = _modelMeshRenderItemIDs[i];
auto meshIndex = _modelMeshRenderItemShapes[i].meshIndex;
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);

View file

@ -188,7 +188,7 @@ public slots:
* @param {number} roll - The roll angle in degrees.
* @returns {Quat} A quaternion created using the <code>pitch</code>, <code>yaw</code>, and <code>roll</code> Euler angles.
* @example <caption>Create a rotation of 180 degrees about the y axis.</caption>
* var rotation = Quat.fromPitchYawRollDgrees(0, 180, 0 );
* var rotation = Quat.fromPitchYawRollDegrees(0, 180, 0 );
*/
glm::quat fromPitchYawRollDegrees(float pitch, float yaw, float roll);

View file

@ -1,5 +1,5 @@
Collection of scripts to create server distribution packages. Most of these scripts assume
use of the build script at https://github.com/kasenvr/vircadia-builder, specifically that
use of the build script at https://github.com/vircadia/vircadia-builder, specifically that
the following directory structure exists
base folder/

View file

@ -5,8 +5,8 @@ Maintainer: Heather Anderson <heath@odysseus.anderson.name>
Build-Depends: debhelper (>= 10)
Standards-Version: 4.1.2
Homepage: https://vircadia.com
Vcs-Git: https://github.com/kasenvr/project-athena.git
Vcs-Browser: https://github.com/kasenvr/project-athena
Vcs-Git: https://github.com/vircadia/vircadia.git
Vcs-Browser: https://github.com/vircadia/vircadia
Package: vircadia-server
Architecture: any

View file

@ -9,7 +9,7 @@ Summary: Vircadia metaverse platform, based on the High Fidelity Engine.
License: ASL 2.0
URL: https://vircadia.com
Source0: https://github.com/kasenvr/vircadia-builder/blob/master/vircadia-builder
Source0: https://github.com/vircadia/vircadia-builder/blob/master/vircadia-builder
#BuildRequires: systemd-rpm-macros
BuildRequires: chrpath

View file

@ -3,7 +3,7 @@
// plugins/JSAPIExample/src
//
// Copyright (c) 2019-2020 humbletim (humbletim@gmail.com)
// Copyright (c) 2019 Kalila L. (kasenvr@gmail.com)
// Copyright (c) 2019 Kalila L. (somnilibertas@gmail.com)
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html

View file

@ -102,7 +102,7 @@ def parse_args():
if True:
args = parser.parse_args()
else:
args = parser.parse_args(['--android', 'questInterface', '--build-root', 'C:/git/project-athena/android/apps/questInterface/.externalNativeBuild/cmake/debug/arm64-v8a'])
args = parser.parse_args(['--android', 'questInterface', '--build-root', 'C:/git/vircadia/android/apps/questInterface/.externalNativeBuild/cmake/debug/arm64-v8a'])
return args
def main():

View file

@ -655,6 +655,12 @@
"yargs-parser": "^13.0.0"
},
"dependencies": {
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@ -680,6 +686,16 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
},
"yargs-parser": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
@ -1091,9 +1107,9 @@
"dev": true
},
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
"integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",
"dev": true
},
"is-arrayish": {
@ -2246,23 +2262,13 @@
"requires": {
"ansi-regex": "^4.1.0"
}
},
"yargs-parser": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"yargs-parser": {
"version": "13.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
"integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
"dev": true,
"version": "15.0.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
"integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
@ -2271,8 +2277,7 @@
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
}
}
},

View file

@ -41,7 +41,7 @@ Script.include([
var CreateWindow = Script.require('./modules/createWindow.js');
var TITLE_OFFSET = 60;
var CREATE_TOOLS_WIDTH = 490;
var CREATE_TOOLS_WIDTH = 750;
var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942;
var ENTIRE_DOMAIN_SCAN_RADIUS = 27713;
@ -117,8 +117,10 @@ var gridTool = new GridTool({
});
gridTool.setVisible(false);
var entityShapeVisualizerSessionName = "SHAPE_VISUALIZER_" + Uuid.generate();
var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js');
var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]);
var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"], entityShapeVisualizerSessionName);
var entityListTool = new EntityListTool(shouldUseEditTabletApp);
@ -146,7 +148,10 @@ var DEFAULT_DIMENSIONS = {
var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
var SUBMENU_ENTITY_EDITOR_PREFERENCES = "Edit > Create Application - Preferences";
var MENU_IMPORT_FROM_FILE = "Import Entities (.json) From a File";
var MENU_IMPORT_FROM_URL = "Import Entities (.json) From a URL";
var MENU_CREATE_SEPARATOR = "Create Application";
var SUBMENU_ENTITY_EDITOR_PREFERENCES = "Edit > Preferences";
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
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";
@ -878,13 +883,11 @@ var toolBar = (function () {
});
addButton("importEntitiesButton", function() {
Window.browseChanged.connect(onFileOpenChanged);
Window.browseAsync("Select .json to Import", "", "*.json");
importEntitiesFromFile();
});
addButton("importEntitiesFromUrlButton", function() {
Window.promptTextChanged.connect(onPromptTextChanged);
Window.promptAsync("URL of a .json to import", "");
importEntitiesFromUrl();
});
addButton("openAssetBrowserButton", function() {
@ -1400,6 +1403,22 @@ function setupModelMenus() {
position: 1,
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: MENU_CREATE_SEPARATOR,
isSeparator: true
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: MENU_IMPORT_FROM_FILE,
afterItem: MENU_CREATE_SEPARATOR
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: MENU_IMPORT_FROM_URL,
afterItem: MENU_IMPORT_FROM_FILE
});
Menu.addMenu(SUBMENU_ENTITY_EDITOR_PREFERENCES);
Menu.addMenuItem({
@ -1482,7 +1501,10 @@ function cleanupModelMenus() {
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_SHOW_ZONES_IN_EDIT_MODE);
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_CREATE_ENTITIES_GRABBABLE);
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_ENTITY_LIST_DEFAULT_RADIUS);
Menu.removeMenu(SUBMENU_ENTITY_EDITOR_PREFERENCES);
Menu.removeMenu(SUBMENU_ENTITY_EDITOR_PREFERENCES);
Menu.removeMenuItem("Edit", MENU_IMPORT_FROM_URL);
Menu.removeMenuItem("Edit", MENU_IMPORT_FROM_FILE);
Menu.removeSeparator("Edit", MENU_CREATE_SEPARATOR);
}
Script.scriptEnding.connect(function () {
@ -1856,6 +1878,10 @@ function handleMenuEvent(menuItem) {
} else if (menuItem === MENU_ENTITY_LIST_DEFAULT_RADIUS) {
Window.promptTextChanged.connect(onPromptTextChangedDefaultRadiusUserPref);
Window.promptAsync("Entity List Default Radius (in meters)", "" + Settings.getValue(SETTING_ENTITY_LIST_DEFAULT_RADIUS, 100));
} else if (menuItem === MENU_IMPORT_FROM_FILE) {
importEntitiesFromFile();
} else if (menuItem === MENU_IMPORT_FROM_URL) {
importEntitiesFromUrl();
}
tooltip.show(false);
}
@ -2013,18 +2039,27 @@ function toggleKey(value) {
}
function focusKey(value) {
if (value === 0) { // on release
cameraManager.enable();
if (selectionManager.hasSelection()) {
cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
}
setCameraFocusToSelection();
}
}
function gridKey(value) {
if (value === 0) { // on release
if (selectionManager.hasSelection()) {
grid.moveToSelection();
}
alignGridToSelection();
}
}
function viewGridKey(value) {
if (value === 0) { // on release
toggleGridVisibility();
}
}
function snapKey(value) {
if (value === 0) { // on release
entityListTool.toggleSnapToGrid();
}
}
function gridToAvatarKey(value) {
if (value === 0) { // on release
alignGridToAvatar();
}
}
function recursiveAdd(newParentID, parentData) {
@ -2424,7 +2459,6 @@ var PropertiesTool = function (opts) {
}
}
if (data.onlyUpdateEntities) {
blockPropertyUpdates = true;
} else {
@ -2433,6 +2467,10 @@ var PropertiesTool = function (opts) {
}
selectionManager._update(false, this);
blockPropertyUpdates = false;
if (data.snapToGrid !== undefined) {
entityListTool.setListMenuSnapToGrid(data.snapToGrid);
}
} else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') {
data.ids.forEach(function(entityID) {
Entities.editEntity(entityID, data.properties);
@ -2787,7 +2825,10 @@ if (isOnMacPlatform) {
}
mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey);
mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey);
mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey);
mapping.from([Controller.Hardware.Keyboard.J]).to(gridKey);
mapping.from([Controller.Hardware.Keyboard.G]).to(viewGridKey);
mapping.from([Controller.Hardware.Keyboard.H]).to(snapKey);
mapping.from([Controller.Hardware.Keyboard.K]).to(gridToAvatarKey);
mapping.from([Controller.Hardware.Keyboard.X])
.when([Controller.Hardware.Keyboard.Control])
.to(whenReleased(function() { selectionManager.cutSelectedEntities() }));
@ -2828,8 +2869,14 @@ keyUpEventFromUIWindow = function(keyUpEvent) {
toggleKey(pressedValue);
} else if (keyUpEvent.keyCodeString === "F") {
focusKey(pressedValue);
} else if (keyUpEvent.keyCodeString === "G") {
} else if (keyUpEvent.keyCodeString === "J") {
gridKey(pressedValue);
} else if (keyUpEvent.keyCodeString === "G") {
viewGridKey(pressedValue);
} else if (keyUpEvent.keyCodeString === "H") {
snapKey(pressedValue);
} else if (keyUpEvent.keyCodeString === "K") {
gridToAvatarKey(pressedValue);
} else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") {
selectionManager.cutSelectedEntities();
} else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") {
@ -2908,7 +2955,7 @@ function zoneSortOrder(a, b) {
function getParentState(id) {
var state = "NONE";
var properties = Entities.getEntityProperties(id, ["parentID"]);
var children = Entities.getChildrenIDs(id);
var children = getDomainOnlyChildrenIDs(id);
if (properties.parentID !== Uuid.NULL) {
if (children.length > 0) {
state = "PARENT_CHILDREN";
@ -2923,4 +2970,59 @@ function getParentState(id) {
return state;
}
function getDomainOnlyChildrenIDs(id) {
var allChildren = Entities.getChildrenIDs(id);
var realChildren = [];
var properties;
for (var i = 0; i < allChildren.length; i++) {
properties = Entities.getEntityProperties(allChildren[i], ["name"]);
if (properties.name !== undefined && properties.name !== entityShapeVisualizerSessionName) {
realChildren.push(allChildren[i]);
}
}
return realChildren;
}
function importEntitiesFromFile() {
Window.browseChanged.connect(onFileOpenChanged);
Window.browseAsync("Select .json to Import", "", "*.json");
}
function importEntitiesFromUrl() {
Window.promptTextChanged.connect(onPromptTextChanged);
Window.promptAsync("URL of a .json to import", "");
}
function setCameraFocusToSelection() {
cameraManager.enable();
if (selectionManager.hasSelection()) {
cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
}
}
function alignGridToSelection() {
if (selectionManager.hasSelection()) {
if (!grid.getVisible()) {
grid.setVisible(true, true);
}
grid.moveToSelection();
}
}
function alignGridToAvatar() {
if (!grid.getVisible()) {
grid.setVisible(true, true);
}
grid.moveToAvatar();
}
function toggleGridVisibility() {
if (!grid.getVisible()) {
grid.setVisible(true, true);
} else {
grid.setVisible(false, true);
}
}
}()); // END LOCAL_SCOPE

View file

@ -146,6 +146,20 @@ EntityListTool = function(shouldUseEditTabletApp) {
});
};
that.setListMenuSnapToGrid = function (isSnapToGrid) {
emitJSONScriptEvent({ "type": "setSnapToGrid", "snap": isSnapToGrid });
};
that.toggleSnapToGrid = function () {
if (!grid.getSnapToGrid()) {
grid.setSnapToGrid(true);
emitJSONScriptEvent({ "type": "setSnapToGrid", "snap": true });
} else {
grid.setSnapToGrid(false);
emitJSONScriptEvent({ "type": "setSnapToGrid", "snap": false });
}
};
function valueIfDefined(value) {
return value !== undefined ? value : "";
}
@ -381,7 +395,22 @@ EntityListTool = function(shouldUseEditTabletApp) {
});
} else if (data.type === 'saveColumnsConfigSetting') {
Settings.setValue(SETTING_EDITOR_COLUMNS_SETUP, data.columnsData);
} else if (data.type === 'importFromFile') {
importEntitiesFromFile();
} else if (data.type === 'importFromUrl') {
importEntitiesFromUrl();
} else if (data.type === 'setCameraFocusToSelection') {
setCameraFocusToSelection();
} else if (data.type === 'alignGridToSelection') {
alignGridToSelection();
} else if (data.type === 'alignGridToAvatar') {
alignGridToAvatar();
} else if (data.type === 'toggleGridVisibility') {
toggleGridVisibility();
} else if (data.type === 'toggleSnapToGrid') {
that.toggleSnapToGrid();
}
};
webView.webEventReceived.connect(onWebEventReceived);

View file

@ -32,8 +32,9 @@
</div>
<button id="toggle-space-mode" class="hifi-edit-button space-mode-local">Local</button>
<input type="button" class="vglyph" id="hmdmultiselect" value="I" style="display: none;" />
<input type="button" class="normal" id="selection" value="Selection..." />
<input type="button" class="normal" id="actions" value="Actions..." />
<input type="button" class="normal" id="selection" value="Select&#9662;" />
<input type="button" class="normal" id="actions" value="Edit&#9662;" />
<input type="button" class="normal" id="tools" value="Tools&#9662;" />
</div>
<div id="entity-list">
<div id="filter-area">
@ -159,7 +160,7 @@
<div class="entity-list-menu" id="selection-menu" >
<button class="menu-button" id="selectall" >
<div class = "menu-item">
<div class = "menu-item-caption">Select All</div>
<div class = "menu-item-caption">Select All (in List)</div>
<div class = "menu-item-shortcut">Ctrl-A</div>
</div>
</button>
@ -171,7 +172,7 @@
</button>
<button class="menu-button" id="selectinverse" >
<div class = "menu-item">
<div class = "menu-item-caption">Inverse Selection</div>
<div class = "menu-item-caption">Inverse Selection (in List)</div>
<div class = "menu-item-shortcut">Ctrl-I</div>
</div>
</button>
@ -219,13 +220,71 @@
<div class = "menu-item-shortcut"></div>
</div>
</button>
<div class="menu-separator"></div>
</div>
<div class="entity-list-menu" id="tools-menu" >
<button class="menu-button" id="setCameraFocusToSelection" >
<div class = "menu-item">
<div class = "menu-item-caption">Set Camera Focus To Selection</div>
<div class = "menu-item-shortcut">F</div>
</div>
</button>
<button class="menu-button" id="teleport-to-entity" >
<div class = "menu-item">
<div class = "menu-item-caption">Teleport To Selected Entities</div>
<div class = "menu-item-shortcut"></div>
</div>
</button>
<div class="menu-separator"></div>
<button class="menu-button" id="toggleLocalWorldMode" >
<div class = "menu-item">
<div class = "menu-item-caption">Toggle Local/World Mode</div>
<div class = "menu-item-shortcut">T</div>
</div>
</button>
<div class="menu-separator"></div>
<button class="menu-button" id="exportSelectedEntities" >
<div class = "menu-item">
<div class = "menu-item-caption">Export Selected Entities</div>
<div class = "menu-item-shortcut"></div>
</div>
</button>
<button class="menu-button" id="importEntitiesFromFile" >
<div class = "menu-item">
<div class = "menu-item-caption">Import Entities (.json) From a File</div>
<div class = "menu-item-shortcut"></div>
</div>
</button>
<button class="menu-button" id="importEntitiesFromUrl" >
<div class = "menu-item">
<div class = "menu-item-caption">Import Entities (.json) From a URL</div>
<div class = "menu-item-shortcut"></div>
</div>
</button>
<div class="menu-separator"></div>
<button class="menu-button" id="gridActivator" >
<div class = "menu-item">
<div class = "menu-item-caption">Toggle Grid</div>
<div class = "menu-item-shortcut">G</div>
</div>
</button>
<button class="menu-button" id="snapToGridActivator" >
<div class = "menu-item">
<div class = "menu-item-caption" id="snapToGridActivatorCaption">Activate Snap to Grid</div>
<div class = "menu-item-shortcut">H</div>
</div>
</button>
<button class="menu-button" id="alignGridToSelection" >
<div class = "menu-item">
<div class = "menu-item-caption">Align Grid to Selected Entities</div>
<div class = "menu-item-shortcut">J</div>
</div>
</button>
<button class="menu-button" id="alignGridToAvatar" >
<div class = "menu-item">
<div class = "menu-item-caption">Align Grid to Avatar</div>
<div class = "menu-item-shortcut">K</div>
</div>
</button>
</div>
<div id="menuBackgroundOverlay" ></div>
</body>

View file

@ -9,8 +9,8 @@
const ASCENDING_SORT = 1;
const DESCENDING_SORT = -1;
const ASCENDING_STRING = '&#x25B4;';
const DESCENDING_STRING = '&#x25BE;';
const ASCENDING_STRING = "&#x25B4;";
const DESCENDING_STRING = "&#x25BE;";
const BYTES_PER_MEGABYTE = 1024 * 1024;
const COLLAPSE_EXTRA_INFO = "E";
const EXPAND_EXTRA_INFO = "D";
@ -34,7 +34,7 @@ function displayIfNonZero(number) {
}
function getFilename(url) {
let urlParts = url.split('/');
let urlParts = url.split("/");
return urlParts[urlParts.length - 1];
}
@ -195,7 +195,7 @@ let lastSelectedEntity;
*/
let entityListContextMenu = null;
let currentSortColumnID = 'type';
let currentSortColumnID = "type";
let currentSortOrder = ASCENDING_SORT;
let elSortOrders = {};
let typeFilters = [];
@ -226,6 +226,7 @@ let elEntityTable,
elToggleVisible,
elActionsMenu,
elSelectionMenu,
elToolsMenu,
elMenuBackgroundOverlay,
elHmdMultiSelect,
elHmdCopy,
@ -249,6 +250,16 @@ let elEntityTable,
elSelectFamily,
elSelectTopFamily,
elTeleportToEntity,
elSetCameraFocusToSelection,
elToggleLocalWorldMode,
elExportSelectedEntities,
elImportEntitiesFromFile,
elImportEntitiesFromUrl,
elGridActivator,
elSnapToGridActivator,
elSnapToGridActivatorCaption,
elAlignGridToSelection,
elAlignGridToAvatar,
elFilterTypeMultiselectBox,
elFilterTypeText,
elFilterTypeOptions,
@ -268,7 +279,7 @@ let elEntityTable,
elRenameInput;
const ENABLE_PROFILING = false;
let profileIndent = '';
let profileIndent = "";
const PROFILE_NOOP = function(_name, fn, args) {
fn.apply(this, args);
} ;
@ -298,6 +309,7 @@ function loaded() {
elHmdMultiSelect = document.getElementById("hmdmultiselect");
elActionsMenu = document.getElementById("actions");
elSelectionMenu = document.getElementById("selection");
elToolsMenu = document.getElementById("tools");
elMenuBackgroundOverlay = document.getElementById("menuBackgroundOverlay");
elHmdCopy = document.getElementById("hmdcopy");
elHmdCut = document.getElementById("hmdcut");
@ -320,6 +332,16 @@ function loaded() {
elSelectFamily = document.getElementById("selectfamily");
elSelectTopFamily = document.getElementById("selecttopfamily");
elTeleportToEntity = document.getElementById("teleport-to-entity");
elSetCameraFocusToSelection = document.getElementById("setCameraFocusToSelection");
elToggleLocalWorldMode = document.getElementById("toggleLocalWorldMode");
elExportSelectedEntities = document.getElementById("exportSelectedEntities");
elImportEntitiesFromFile = document.getElementById("importEntitiesFromFile");
elImportEntitiesFromUrl = document.getElementById("importEntitiesFromUrl");
elGridActivator = document.getElementById("gridActivator");
elSnapToGridActivator = document.getElementById("snapToGridActivator");
elSnapToGridActivatorCaption = document.getElementById("snapToGridActivatorCaption");
elAlignGridToSelection = document.getElementById("alignGridToSelection");
elAlignGridToAvatar = document.getElementById("alignGridToAvatar");
elFilterTypeMultiselectBox = document.getElementById("filter-type-multiselect-box");
elFilterTypeText = document.getElementById("filter-type-text");
elFilterTypeOptions = document.getElementById("filter-type-options");
@ -335,17 +357,17 @@ function loaded() {
elNoEntitiesMessage = document.getElementById("no-entities");
elColumnsMultiselectBox = document.getElementById("entity-table-columns-multiselect-box");
elColumnsOptions = document.getElementById("entity-table-columns-options");
elToggleSpaceMode = document.getElementById('toggle-space-mode');
elToggleSpaceMode = document.getElementById("toggle-space-mode");
document.body.onclick = onBodyClick;
elToggleLocked.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleLocked' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleLocked" }));
};
elToggleVisible.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleVisible' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleVisible" }));
};
elExport.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'export'}));
EventBridge.emitWebEvent(JSON.stringify({ type: "export"}));
};
elHmdMultiSelect.onclick = function() {
if (hmdMultiSelectMode) {
@ -355,7 +377,7 @@ function loaded() {
elHmdMultiSelect.className = "white vglyph";
hmdMultiSelectMode = true;
}
EventBridge.emitWebEvent(JSON.stringify({ type: 'hmdMultiSelectMode', value: hmdMultiSelectMode }));
EventBridge.emitWebEvent(JSON.stringify({ type: "hmdMultiSelectMode", value: hmdMultiSelectMode }));
};
elActionsMenu.onclick = function() {
document.getElementById("menuBackgroundOverlay").style.display = "block";
@ -365,47 +387,51 @@ function loaded() {
document.getElementById("menuBackgroundOverlay").style.display = "block";
document.getElementById("selection-menu").style.display = "block";
};
elToolsMenu.onclick = function() {
document.getElementById("menuBackgroundOverlay").style.display = "block";
document.getElementById("tools-menu").style.display = "block";
};
elMenuBackgroundOverlay.onclick = function() {
closeAllEntityListMenu();
};
elHmdCopy.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'copy' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "copy" }));
closeAllEntityListMenu();
};
elHmdCut.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'cut' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "cut" }));
closeAllEntityListMenu();
};
elHmdPaste.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'paste' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "paste" }));
closeAllEntityListMenu();
};
elHmdDuplicate.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'duplicate' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "duplicate" }));
closeAllEntityListMenu();
};
elParent.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "parent" }));
closeAllEntityListMenu();
};
elUnparent.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "unparent" }));
closeAllEntityListMenu();
};
elUndo.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'undo' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "undo" }));
closeAllEntityListMenu();
};
elRedo.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'redo' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "redo" }));
closeAllEntityListMenu();
};
elDelete.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "delete" }));
closeAllEntityListMenu();
};
elMoveEntitySelectionToAvatar.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'moveEntitySelectionToAvatar' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "moveEntitySelectionToAvatar" }));
closeAllEntityListMenu();
};
elSelectAll.onclick = function() {
@ -467,39 +493,75 @@ function loaded() {
closeAllEntityListMenu();
};
elSelectAllInBox.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectAllInBox' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "selectAllInBox" }));
closeAllEntityListMenu();
};
elSelectAllTouchingBox.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectAllTouchingBox' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "selectAllTouchingBox" }));
closeAllEntityListMenu();
};
elSelectParent.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectParent' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "selectParent" }));
closeAllEntityListMenu();
};
elSelectTopParent.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectTopParent' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "selectTopParent" }));
closeAllEntityListMenu();
};
elAddChildrenToSelection.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'addChildrenToSelection' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "addChildrenToSelection" }));
closeAllEntityListMenu();
};
elSelectFamily.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectFamily' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "selectFamily" }));
closeAllEntityListMenu();
};
elSelectTopFamily.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectTopFamily' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "selectTopFamily" }));
closeAllEntityListMenu();
};
elTeleportToEntity.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "teleportToEntity" }));
closeAllEntityListMenu();
};
elSetCameraFocusToSelection.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "setCameraFocusToSelection" }));
closeAllEntityListMenu();
};
elToggleLocalWorldMode.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSpaceMode" }));
closeAllEntityListMenu();
};
elExportSelectedEntities.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "export"}));
closeAllEntityListMenu();
};
elImportEntitiesFromFile.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "importFromFile"}));
closeAllEntityListMenu();
};
elImportEntitiesFromUrl.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "importFromUrl"}));
closeAllEntityListMenu();
};
elGridActivator.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleGridVisibility" }));
closeAllEntityListMenu();
};
elSnapToGridActivator.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSnapToGrid" }));
closeAllEntityListMenu();
};
elAlignGridToSelection.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "alignGridToSelection" }));
closeAllEntityListMenu();
};
elAlignGridToAvatar.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: "alignGridToAvatar" }));
closeAllEntityListMenu();
};
elToggleSpaceMode.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleSpaceMode' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSpaceMode" }));
};
elRefresh.onclick = refreshEntities;
elFilterTypeMultiselectBox.onclick = onToggleTypeDropdown;
@ -517,11 +579,11 @@ function loaded() {
let type = FILTER_TYPES[i];
let typeFilterID = "filter-type-" + type;
let elDiv = document.createElement('div');
let elDiv = document.createElement("div");
elDiv.onclick = onToggleTypeFilter;
elFilterTypeOptions.insertBefore(elDiv, elFilterTypeOptionsButtons);
let elInput = document.createElement('input');
let elInput = document.createElement("input");
elInput.setAttribute("type", "checkbox");
elInput.setAttribute("id", typeFilterID);
elInput.setAttribute("filterType", type);
@ -529,12 +591,12 @@ function loaded() {
elFilterTypeInputs[type] = elInput;
elDiv.appendChild(elInput);
let elLabel = document.createElement('label');
let elLabel = document.createElement("label");
elLabel.setAttribute("for", typeFilterID);
elLabel.innerText = type;
elDiv.appendChild(elLabel);
let elSpan = document.createElement('span');
let elSpan = document.createElement("span");
elSpan.setAttribute("class", "typeIcon");
elSpan.innerHTML = ENTITY_TYPE_ICON[type];
@ -567,11 +629,11 @@ function loaded() {
elTh.innerText = columnData.columnHeader;
}
elTh.onmousedown = function(event) {
if (event.target.nodeName === 'TH') {
if (event.target.nodeName === "TH") {
elTargetTh = event.target;
targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex"));
lastColumnSwapPosition = event.clientX;
} else if (event.target.nodeName === 'SPAN') {
} else if (event.target.nodeName === "SPAN") {
elTargetSpan = event.target;
}
initialThEvent = event;
@ -594,18 +656,18 @@ function loaded() {
if (columnData.alwaysShown !== true) {
let columnDropdownID = "entity-table-column-" + columnID;
let elDiv = document.createElement('div');
let elDiv = document.createElement("div");
elDiv.onclick = onToggleColumn;
elColumnsOptions.appendChild(elDiv);
let elInput = document.createElement('input');
let elInput = document.createElement("input");
elInput.setAttribute("type", "checkbox");
elInput.setAttribute("id", columnDropdownID);
elInput.setAttribute("columnID", columnID);
elInput.checked = columnData.initiallyShown === true;
elDiv.appendChild(elInput);
let elLabel = document.createElement('label');
let elLabel = document.createElement("label");
elLabel.setAttribute("for", columnDropdownID);
elLabel.innerText = columnData.dropdownLabel;
elDiv.appendChild(elLabel);
@ -640,7 +702,7 @@ function loaded() {
let elCell = entity.elRow.childNodes[getColumnIndex("name")];
elRenameInput = document.createElement("input");
elRenameInput.setAttribute('class', 'rename-entity');
elRenameInput.setAttribute("class", "rename-entity");
elRenameInput.value = entity.name;
let ignoreClicks = function(event) {
event.stopPropagation();
@ -705,22 +767,22 @@ function loaded() {
entityListContextMenu.setOnSelectedCallback(function(optionName, selectedEntityID) {
switch (optionName) {
case "Cut":
EventBridge.emitWebEvent(JSON.stringify({ type: 'cut' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "cut" }));
break;
case "Copy":
EventBridge.emitWebEvent(JSON.stringify({ type: 'copy' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "copy" }));
break;
case "Paste":
EventBridge.emitWebEvent(JSON.stringify({ type: 'paste' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "paste" }));
break;
case "Rename":
startRenamingEntity(selectedEntityID);
break;
case "Duplicate":
EventBridge.emitWebEvent(JSON.stringify({ type: 'duplicate' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "duplicate" }));
break;
case "Delete":
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "delete" }));
break;
}
});
@ -744,11 +806,11 @@ function loaded() {
}));
}
let enabledContextMenuItems = ['Copy', 'Paste', 'Duplicate'];
let enabledContextMenuItems = ["Copy", "Paste", "Duplicate"];
if (entitiesByID[entityID] && !entitiesByID[entityID].locked) {
enabledContextMenuItems.push('Cut');
enabledContextMenuItems.push('Rename');
enabledContextMenuItems.push('Delete');
enabledContextMenuItems.push("Cut");
enabledContextMenuItems.push("Rename");
enabledContextMenuItems.push("Delete");
}
entityListContextMenu.open(clickEvent, entityID, enabledContextMenuItems);
@ -947,7 +1009,7 @@ function loaded() {
if (id === deletedIDs[i]) {
let elRow = entities[j].elRow;
if (elRow) {
elRow.className = '';
elRow.className = "";
elRow.dataset.entityID = EMPTY_ENTITY_ID;
}
entities.splice(j, 1);
@ -1030,7 +1092,7 @@ function loaded() {
}
function refreshEntities() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "refresh" }));
}
function refreshFooter() {
@ -1057,7 +1119,7 @@ function loaded() {
if (entity !== undefined) {
entity.selected = false;
if (entity.elRow) {
entity.elRow.className = '';
entity.elRow.className = "";
}
}
});
@ -1071,9 +1133,9 @@ function loaded() {
entity.selected = true;
if (entity.elRow) {
if (id === lastSelectedEntity) {
entity.elRow.className = 'last-selected';
entity.elRow.className = "last-selected";
} else {
entity.elRow.className = 'selected';
entity.elRow.className = "selected";
}
}
} else {
@ -1144,12 +1206,12 @@ function loaded() {
// if this entity was previously selected flag it's row as selected
if (itemData.selected) {
if (itemData.id === lastSelectedEntity) {
elRow.className = 'last-selected';
elRow.className = "last-selected";
} else {
elRow.className = 'selected';
elRow.className = "selected";
}
} else {
elRow.className = '';
elRow.className = "";
}
// if this row previously had an associated entity ID that wasn't the new entity ID then clear
@ -1202,9 +1264,9 @@ function loaded() {
}
function onRadiusChange() {
elFilterRadius.value = elFilterRadius.value.replace(/[^0-9]/g, '');
elFilterRadius.value = elFilterRadius.value.replace(/[^0-9]/g, "");
elFilterRadius.value = Math.max(elFilterRadius.value, 0);
EventBridge.emitWebEvent(JSON.stringify({ type: 'radius', radius: elFilterRadius.value }));
EventBridge.emitWebEvent(JSON.stringify({ type: "radius", radius: elFilterRadius.value }));
refreshEntities();
}
@ -1425,7 +1487,7 @@ function loaded() {
}
if (isColumnsSettingLoaded) {
EventBridge.emitWebEvent(JSON.stringify({ type: 'saveColumnsConfigSetting', columnsData: columns }));
EventBridge.emitWebEvent(JSON.stringify({ type: "saveColumnsConfigSetting", columnsData: columns }));
}
entityList.refresh();
@ -1628,7 +1690,7 @@ function loaded() {
}
EventBridge.emitWebEvent(JSON.stringify({
type: 'keyUpEvent',
type: "keyUpEvent",
keyUpEvent: {
code,
key,
@ -1673,6 +1735,12 @@ function loaded() {
removeEntities(data.ids);
} else if (data.type === "setSpaceMode") {
setSpaceMode(data.spaceMode);
} else if (data.type === "setSnapToGrid") {
if (data.snap) {
elSnapToGridActivatorCaption.innerHTML = "&#x2713; Deactivate Snap to Grid";
} else {
elSnapToGridActivatorCaption.innerHTML = "Activate Snap to Grid";
}
} else if (data.type === "confirmHMDstate") {
if (data.isHmd) {
document.getElementById("hmdmultiselect").style.display = "inline";
@ -1722,7 +1790,7 @@ function loaded() {
}
}
} else {
EventBridge.emitWebEvent(JSON.stringify({ type: 'saveColumnsConfigSetting', columnsData: "" }));
EventBridge.emitWebEvent(JSON.stringify({ type: "saveColumnsConfigSetting", columnsData: "" }));
}
}
isColumnsSettingLoaded = true;
@ -1735,7 +1803,7 @@ function loaded() {
window.addEventListener("resize", updateColumnWidths);
EventBridge.emitWebEvent(JSON.stringify({ type: 'loadConfigSetting' }));
EventBridge.emitWebEvent(JSON.stringify({ type: "loadConfigSetting" }));
});
augmentSpinButtons();
@ -1758,6 +1826,7 @@ function loaded() {
document.getElementById("menuBackgroundOverlay").style.display = "none";
document.getElementById("selection-menu").style.display = "none";
document.getElementById("actions-menu").style.display = "none";
document.getElementById("tools-menu").style.display = "none";
}
}

View file

@ -724,12 +724,12 @@ SelectionManager = (function() {
that.addChildrenToSelection = function() {
if (that.hasSelection()) {
for (var i = 0; i < that.selections.length; i++) {
var childrenIDs = Entities.getChildrenIDs(that.selections[i]);
var collectNewChildren;
var childrenIDs = getDomainOnlyChildrenIDs(that.selections[i]);
var collectNewChildren;
var j;
var k = 0;
do {
collectNewChildren = Entities.getChildrenIDs(childrenIDs[k]);
collectNewChildren = getDomainOnlyChildrenIDs(childrenIDs[k]);
if (collectNewChildren.length > 0) {
for (j = 0; j < collectNewChildren.length; j++) {
childrenIDs.push(collectNewChildren[j]);
@ -746,7 +746,7 @@ SelectionManager = (function() {
that._update(true, this);
} else {
audioFeedback.rejection();
Window.notifyEditError("You have nothing selected.");
Window.notifyEditError("You have nothing selected.");
}
};
@ -832,7 +832,7 @@ SelectionDisplay = (function() {
const BOUNDING_EDGE_OFFSET = 0.5;
const DUPLICATOR_OFFSET = { x: 0.6, y: 0, z: 0.6 };
const DUPLICATOR_OFFSET = { x: 0.6, y: 0, z: 0.6 };
const CTRL_KEY_CODE = 16777249;

View file

@ -116,12 +116,14 @@ function deepCopy(v) {
return JSON.parse(JSON.stringify(v));
}
function EntityShape(entityID) {
function EntityShape(entityID, entityShapeVisualizerSessionName) {
this.entityID = entityID;
this.entityShapeVisualizerSessionName = entityShapeVisualizerSessionName;
var propertiesForType = getEntityShapePropertiesForType(Entities.getEntityProperties(entityID, REQUESTED_ENTITY_SHAPE_PROPERTIES));
this.previousPropertiesForType = propertiesForType;
this.initialize(propertiesForType);
}
@ -130,6 +132,7 @@ EntityShape.prototype = {
// Create new instance of JS object:
var overlayProperties = deepCopy(properties);
overlayProperties.name = this.entityShapeVisualizerSessionName;
overlayProperties.localPosition = Vec3.ZERO;
overlayProperties.localRotation = Quat.IDENTITY;
overlayProperties.canCastShadows = false;
@ -172,11 +175,11 @@ EntityShape.prototype = {
}
};
function EntityShapeVisualizer(visualizedTypes) {
function EntityShapeVisualizer(visualizedTypes, entityShapeVisualizerSessionName) {
this.acceptedEntities = [];
this.ignoredEntities = [];
this.entityShapes = {};
this.entityShapeVisualizerSessionName = entityShapeVisualizerSessionName;
this.visualizedTypes = visualizedTypes;
}
@ -185,7 +188,7 @@ EntityShapeVisualizer.prototype = {
if (this.entityShapes[entityID]) {
return;
}
this.entityShapes[entityID] = new EntityShape(entityID);
this.entityShapes[entityID] = new EntityShape(entityID, this.entityShapeVisualizerSessionName);
},
updateEntity: function(entityID) {

View file

@ -210,8 +210,8 @@ TabBar {
text: "Import Entities (.json) from a File"
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
anchors.right: parent.horizontalCenter
anchors.rightMargin: 10
anchors.right: parent.right
anchors.rightMargin: 55
anchors.left: parent.left
anchors.leftMargin: 55
anchors.top: assetServerButton.bottom
@ -231,9 +231,9 @@ TabBar {
colorScheme: hifi.colorSchemes.dark
anchors.right: parent.right
anchors.rightMargin: 55
anchors.left: parent.horizontalCenter
anchors.leftMargin: 10
anchors.top: assetServerButton.bottom
anchors.left: parent.left
anchors.leftMargin: 55
anchors.top: importButton.bottom
anchors.topMargin: 20
onClicked: {
editRoot.sendToScript({

View file

@ -404,7 +404,7 @@ input[type=button], button.hifi-edit-button {
text-transform: uppercase;
vertical-align: top;
height: 28px;
min-width: 120px;
min-width: 70px;
padding: 0 18px;
margin-right: 6px;
border-radius: 5px;

View file

@ -1,10 +1,19 @@
// gridTool.js
//
// Created by Ryan Huffman on 6 Nov 2014
// Copyright 2014 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global keyUpEventFromUIWindow */
var GRID_CONTROLS_HTML_URL = Script.resolvePath('../html/gridControls.html');
Grid = function() {
var that = {};
var gridColor = { red: 0, green: 0, blue: 0 };
var gridColor = { red: 255, green: 255, blue: 255 };
var gridAlpha = 0.6;
var origin = { x: 0, y: +MyAvatar.getJointPosition('LeftToeBase').y.toFixed(1) + 0.1, z: 0 };
var scale = 500;
@ -16,18 +25,19 @@ Grid = function() {
var snapToGrid = false;
var gridOverlay = Overlays.addOverlay("grid", {
var gridEntityTool = Entities.addEntity({
type: "Grid",
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
dimensions: { x: scale, y: scale, z: scale },
position: origin,
visible: false,
drawInFront: false,
renderLayer: "world",
color: gridColor,
alpha: gridAlpha,
minorGridEvery: minorGridEvery,
majorGridEvery: majorGridEvery,
ignorePickIntersection: true
});
}, "local");
that.visible = false;
that.enabled = false;
@ -163,6 +173,14 @@ Grid = function() {
newPosition = Vec3.subtract(newPosition, { x: 0, y: SelectionManager.worldDimensions.y * 0.5, z: 0 });
that.setPosition(newPosition);
};
that.moveToAvatar = function() {
var position = MyAvatar.getJointPosition("LeftFoot");
if (position.x === 0.0 && position.y === 0.0 && position.z === 0.0) {
position = MyAvatar.position;
}
that.setPosition(position);
};
that.emitUpdate = function() {
if (that.onUpdate) {
@ -214,7 +232,7 @@ Grid = function() {
};
function updateGrid(noUpdate) {
Overlays.editOverlay(gridOverlay, {
Entities.editEntity(gridEntityTool, {
position: { x: 0, y: origin.y, z: 0 },
visible: that.visible && that.enabled,
minorGridEvery: minorGridEvery,
@ -222,6 +240,7 @@ Grid = function() {
color: gridColor,
alpha: gridAlpha
});
if (!noUpdate) {
that.emitUpdate();
@ -229,7 +248,7 @@ Grid = function() {
}
function cleanup() {
Overlays.deleteOverlay(gridOverlay);
Entities.deleteEntity(gridEntityTool);
}
that.addListener = function(callback) {
@ -283,11 +302,7 @@ GridTool = function(opts) {
} else if (data.type === "action") {
var action = data.action;
if (action === "moveToAvatar") {
var position = MyAvatar.getJointPosition("LeftFoot");
if (position.x === 0 && position.y === 0 && position.z === 0) {
position = MyAvatar.position;
}
horizontalGrid.setPosition(position);
horizontalGrid.moveToAvatar();
} else if (action === "moveToSelection") {
horizontalGrid.moveToSelection();
}

View file

@ -5,8 +5,8 @@
// Created by Keb Helion, February 2020.
// Copyright 2020 Vircadia contributors.
//
// App maintained in: https://github.com/kasenvr/community-apps
// App copied to: https://github.com/kasenvr/project-athena
// App maintained in: https://github.com/vircadia/community-apps
// App copied to: https://github.com/vircadia/vircadia
//
//
// Distributed under the Apache License, Version 2.0.

View file

@ -13,7 +13,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/kasenvr/project-athena.git"
"url": "https://github.com/vircadia/vircadia.git"
},
"main": "src/main.js",
"scripts": {