mirror of
https://github.com/overte-org/overte.git
synced 2025-04-13 03:42:10 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into overlay-children
This commit is contained in:
commit
15e2140cb2
105 changed files with 2673 additions and 2526 deletions
|
@ -72,6 +72,6 @@ module.exports = {
|
|||
"spaced-comment": ["error", "always", {
|
||||
"line": { "markers": ["/"] }
|
||||
}],
|
||||
"space-before-function-paren": ["error", {"anonymous": "always", "named": "never"}]
|
||||
"space-before-function-paren": ["error", {"anonymous": "ignore", "named": "never"}]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,13 +23,13 @@ function(AUTOSCRIBE_SHADER SHADER_FILE)
|
|||
|
||||
#Extract the unique include shader paths
|
||||
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||
#message(Hifi for includes ${INCLUDES})
|
||||
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
||||
#message(${TARGET_NAME} Hifi for includes ${INCLUDES})
|
||||
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
||||
#message(ready for includes ${SHADER_INCLUDES_PATHS})
|
||||
#message(ready for includes ${SHADER_INCLUDES_PATHS})
|
||||
|
||||
# make the scribe include arguments
|
||||
set(SCRIBE_INCLUDES)
|
||||
|
@ -77,6 +77,7 @@ endfunction()
|
|||
|
||||
|
||||
macro(AUTOSCRIBE_SHADER_LIB)
|
||||
set(HIFI_LIBRARIES_SHADER_INCLUDE_FILES "")
|
||||
file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}")
|
||||
foreach(HIFI_LIBRARY ${ARGN})
|
||||
#if (NOT TARGET ${HIFI_LIBRARY})
|
||||
|
@ -86,7 +87,7 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
#file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src/*.slh)
|
||||
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src)
|
||||
endforeach()
|
||||
#message(${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||
#message("${TARGET_NAME} ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES}")
|
||||
|
||||
file(GLOB_RECURSE SHADER_INCLUDE_FILES src/*.slh)
|
||||
file(GLOB_RECURSE SHADER_SOURCE_FILES src/*.slv src/*.slf src/*.slg)
|
||||
|
@ -95,13 +96,14 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders/${TARGET_NAME}")
|
||||
file(MAKE_DIRECTORY ${SHADERS_DIR})
|
||||
|
||||
#message(${SHADER_INCLUDE_FILES})
|
||||
#message("${TARGET_NAME} ${SHADER_INCLUDE_FILES}")
|
||||
set(AUTOSCRIBE_SHADER_SRC "")
|
||||
foreach(SHADER_FILE ${SHADER_SOURCE_FILES})
|
||||
AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES})
|
||||
file(TO_CMAKE_PATH "${AUTOSCRIBE_SHADER_RETURN}" AUTOSCRIBE_GENERATED_FILE)
|
||||
list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_GENERATED_FILE})
|
||||
endforeach()
|
||||
#message(${AUTOSCRIBE_SHADER_SRC})
|
||||
#message(${TARGET_NAME} ${AUTOSCRIBE_SHADER_SRC})
|
||||
|
||||
if (WIN32)
|
||||
source_group("Shaders" FILES ${SHADER_INCLUDE_FILES})
|
||||
|
@ -116,4 +118,4 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
# Link library shaders, if they exist
|
||||
include_directories("${SHADERS_DIR}")
|
||||
|
||||
endmacro()
|
||||
endmacro()
|
|
@ -54,8 +54,9 @@ macro(SETUP_HIFI_LIBRARY)
|
|||
target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE})
|
||||
endforeach()
|
||||
|
||||
# Don't make scribed shaders cumulative
|
||||
# Don't make scribed shaders or QT resource files cumulative
|
||||
set(AUTOSCRIBE_SHADER_LIB_SRC "")
|
||||
set(QT_RESOURCES_FILE "")
|
||||
|
||||
target_glm()
|
||||
|
||||
|
|
|
@ -1233,7 +1233,10 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
|||
callbackParameters.errorCallbackReceiver = this;
|
||||
callbackParameters.errorCallbackMethod = "handleFailedICEServerAddressUpdate";
|
||||
|
||||
qDebug() << "Updating ice-server address in High Fidelity Metaverse API to" << _iceServerSocket.getAddress().toString();
|
||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
||||
("Updating ice-server address in High Fidelity Metaverse API to [^ \n]+");
|
||||
qDebug() << "Updating ice-server address in High Fidelity Metaverse API to"
|
||||
<< _iceServerSocket.getAddress().toString();
|
||||
|
||||
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
||||
|
||||
|
|
|
@ -63,6 +63,19 @@
|
|||
["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraFirstPerson",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A", "Keyboard.Left", "Keyboard.TouchpadLeft"],
|
||||
["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraThirdPerson",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
{ "from": { "makeAxis" : [ ["Keyboard.A"], ["Keyboard.D"] ] },
|
||||
"when": "Application.CameraFSM",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
|
@ -81,9 +94,10 @@
|
|||
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Down", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" },
|
||||
{ "from": "Keyboard.Up", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" },
|
||||
|
||||
{ "from": "Keyboard.Up", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.Down", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.Up", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.Down", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
{ "from": "Keyboard.Down", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
|
||||
{ "from": "Keyboard.PgDown", "to": "Actions.VERTICAL_DOWN" },
|
||||
{ "from": "Keyboard.PgUp", "to": "Actions.VERTICAL_UP" },
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
{
|
||||
"name": "Oculus Touch to Standard",
|
||||
"channels": [
|
||||
{ "from": "OculusTouch.A", "to": "Standard.RightPrimaryThumb" },
|
||||
{ "from": "OculusTouch.X", "to": "Standard.LeftPrimaryThumb" },
|
||||
{ "from": "OculusTouch.A", "to": "Standard.RightPrimaryThumb", "peek": true },
|
||||
{ "from": "OculusTouch.X", "to": "Standard.LeftPrimaryThumb", "peek": true },
|
||||
|
||||
{ "from": "OculusTouch.A", "to": "Standard.A" },
|
||||
{ "from": "OculusTouch.B", "to": "Standard.B" },
|
||||
{ "from": "OculusTouch.X", "to": "Standard.X" },
|
||||
{ "from": "OculusTouch.Y", "to": "Standard.Y" },
|
||||
|
||||
{ "from": "OculusTouch.LY", "to": "Standard.LY",
|
||||
"filters": [
|
||||
|
|
|
@ -32,9 +32,6 @@
|
|||
{ "from": "Standard.Back", "to": "Actions.CycleCamera" },
|
||||
{ "from": "Standard.Start", "to": "Actions.ContextMenu" },
|
||||
|
||||
{ "from": [ "Standard.DU", "Standard.DL", "Standard.DR", "Standard.DD" ], "to": "Standard.LeftPrimaryThumb" },
|
||||
{ "from": [ "Standard.A", "Standard.B", "Standard.X", "Standard.Y" ], "to": "Standard.RightPrimaryThumb" },
|
||||
|
||||
{ "from": "Standard.LT", "to": "Actions.LeftHandClick" },
|
||||
{ "from": "Standard.RT", "to": "Actions.RightHandClick" },
|
||||
|
||||
|
|
|
@ -15,12 +15,14 @@
|
|||
|
||||
{ "from": "GamePad.Back", "to": "Standard.Back" },
|
||||
{ "from": "GamePad.Start", "to": "Standard.Start" },
|
||||
|
||||
|
||||
{ "from": [ "GamePad.DU", "GamePad.DL", "GamePad.DR", "GamePad.DD" ], "to": "Standard.LeftPrimaryThumb", "peek": true },
|
||||
{ "from": "GamePad.DU", "to": "Standard.DU" },
|
||||
{ "from": "GamePad.DD", "to": "Standard.DD" },
|
||||
{ "from": "GamePad.DL", "to": "Standard.DL" },
|
||||
{ "from": "GamePad.DR", "to": "Standard.DR" },
|
||||
|
||||
{ "from": [ "GamePad.A", "GamePad.B", "GamePad.X", "GamePad.Y" ], "to": "Standard.RightPrimaryThumb", "peek": true },
|
||||
{ "from": "GamePad.A", "to": "Standard.A" },
|
||||
{ "from": "GamePad.B", "to": "Standard.B" },
|
||||
{ "from": "GamePad.X", "to": "Standard.X" },
|
||||
|
|
BIN
interface/resources/images/Default-Sky-9-ambient.jpg
Normal file
BIN
interface/resources/images/Default-Sky-9-ambient.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
BIN
interface/resources/images/Default-Sky-9-cubemap.jpg
Normal file
BIN
interface/resources/images/Default-Sky-9-cubemap.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 394 KiB |
|
@ -521,14 +521,15 @@ ScrollingWindow {
|
|||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
var index = treeView.indexAt(mouse.x, mouse.y);
|
||||
|
||||
treeView.selection.setCurrentIndex(index, 0x0002);
|
||||
|
||||
contextMenu.currentIndex = index;
|
||||
contextMenu.popup();
|
||||
if (!HMD.active) { // Popup only displays properly on desktop
|
||||
var index = treeView.indexAt(mouse.x, mouse.y);
|
||||
treeView.selection.setCurrentIndex(index, 0x0002);
|
||||
contextMenu.currentIndex = index;
|
||||
contextMenu.popup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
HifiControls.ContentSection {
|
||||
id: uploadSection
|
||||
|
|
|
@ -24,6 +24,7 @@ Item {
|
|||
Rectangle { color: hifi.colors.baseGray; anchors.fill: parent; radius: 4 }
|
||||
|
||||
Component.onCompleted: {
|
||||
jointChooser.model = MyAvatar.jointNames;
|
||||
completed = true;
|
||||
}
|
||||
|
||||
|
@ -82,7 +83,6 @@ Item {
|
|||
HifiControls.ComboBox {
|
||||
id: jointChooser;
|
||||
anchors { bottom: parent.bottom; left: parent.left; right: parent.right }
|
||||
model: MyAvatar.jointNames
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
currentIndex: attachment ? model.indexOf(attachment.jointName) : -1
|
||||
onCurrentIndexChanged: {
|
||||
|
|
|
@ -139,7 +139,6 @@
|
|||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
#include "Stars.h"
|
||||
#include "ui/AddressBarDialog.h"
|
||||
#include "ui/AvatarInputs.h"
|
||||
#include "ui/DialogsManager.h"
|
||||
|
@ -391,6 +390,11 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
}
|
||||
|
||||
static const QString STATE_IN_HMD = "InHMD";
|
||||
static const QString STATE_CAMERA_FULL_SCREEN_MIRROR = "CameraFSM";
|
||||
static const QString STATE_CAMERA_FIRST_PERSON = "CameraFirstPerson";
|
||||
static const QString STATE_CAMERA_THIRD_PERSON = "CameraThirdPerson";
|
||||
static const QString STATE_CAMERA_ENTITY = "CameraEntity";
|
||||
static const QString STATE_CAMERA_INDEPENDENT = "CameraIndependent";
|
||||
static const QString STATE_SNAP_TURN = "SnapTurn";
|
||||
static const QString STATE_GROUNDED = "Grounded";
|
||||
static const QString STATE_NAV_FOCUSED = "NavigationFocused";
|
||||
|
@ -470,7 +474,9 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
DependencyManager::set<InterfaceActionFactory>();
|
||||
DependencyManager::set<AudioInjectorManager>();
|
||||
DependencyManager::set<MessagesClient>();
|
||||
controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_SNAP_TURN, STATE_GROUNDED, STATE_NAV_FOCUSED } });
|
||||
controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR,
|
||||
STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT,
|
||||
STATE_SNAP_TURN, STATE_GROUNDED, STATE_NAV_FOCUSED } });
|
||||
DependencyManager::set<UserInputMapper>();
|
||||
DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>();
|
||||
DependencyManager::set<InterfaceParentFinder>();
|
||||
|
@ -962,6 +968,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
_applicationStateDevice->setInputVariant(STATE_IN_HMD, []() -> float {
|
||||
return qApp->isHMDMode() ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_CAMERA_FULL_SCREEN_MIRROR, []() -> float {
|
||||
return qApp->getCamera()->getMode() == CAMERA_MODE_MIRROR ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_CAMERA_FIRST_PERSON, []() -> float {
|
||||
return qApp->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_CAMERA_THIRD_PERSON, []() -> float {
|
||||
return qApp->getCamera()->getMode() == CAMERA_MODE_THIRD_PERSON ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_CAMERA_ENTITY, []() -> float {
|
||||
return qApp->getCamera()->getMode() == CAMERA_MODE_ENTITY ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_CAMERA_INDEPENDENT, []() -> float {
|
||||
return qApp->getCamera()->getMode() == CAMERA_MODE_INDEPENDENT ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_SNAP_TURN, []() -> float {
|
||||
return qApp->getMyAvatar()->getSnapTurn() ? 1 : 0;
|
||||
});
|
||||
|
@ -1212,6 +1233,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
|
||||
qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0);
|
||||
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
||||
QString skyboxUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-cubemap.jpg" };
|
||||
QString skyboxAmbientUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-ambient.jpg" };
|
||||
|
||||
_defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, NetworkTexture::CUBE_TEXTURE, { { "generateIrradiance", false } });
|
||||
_defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, NetworkTexture::CUBE_TEXTURE, { { "generateIrradiance", true } });
|
||||
|
||||
_defaultSkybox->setCubemap(_defaultSkyboxTexture);
|
||||
_defaultSkybox->setColor({ 1.0, 1.0, 1.0 });
|
||||
|
||||
// After all of the constructor is completed, then set firstRun to false.
|
||||
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
|
||||
firstRun.set(false);
|
||||
|
@ -2280,7 +2312,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
}
|
||||
|
||||
case Qt::Key_Asterisk:
|
||||
Menu::getInstance()->triggerOption(MenuOption::Stars);
|
||||
Menu::getInstance()->triggerOption(MenuOption::DefaultSkybox);
|
||||
break;
|
||||
|
||||
case Qt::Key_S:
|
||||
|
@ -4205,8 +4237,6 @@ public:
|
|||
typedef render::Payload<BackgroundRenderData> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
Stars _stars;
|
||||
|
||||
static render::ItemID _item; // unique WorldBoxRenderData
|
||||
};
|
||||
|
||||
|
@ -4241,15 +4271,26 @@ namespace render {
|
|||
|
||||
// Fall through: if no skybox is available, render the SKY_DOME
|
||||
case model::SunSkyStage::SKY_DOME: {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
||||
PerformanceTimer perfTimer("stars");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::payloadRender<BackgroundRenderData>() ... My god, it's full of stars...");
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
|
||||
static const glm::vec3 DEFAULT_SKYBOX_COLOR { 255.0f / 255.0f, 220.0f / 255.0f, 194.0f / 255.0f };
|
||||
static const float DEFAULT_SKYBOX_INTENSITY { 0.2f };
|
||||
static const float DEFAULT_SKYBOX_AMBIENT_INTENSITY { 2.0f };
|
||||
static const glm::vec3 DEFAULT_SKYBOX_DIRECTION { 0.0f, 0.0f, -1.0f };
|
||||
|
||||
static const float alpha = 1.0f;
|
||||
background->_stars.render(args, alpha);
|
||||
}
|
||||
auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
|
||||
auto sceneKeyLight = scene->getKeyLight();
|
||||
scene->setSunModelEnable(false);
|
||||
sceneKeyLight->setColor(DEFAULT_SKYBOX_COLOR);
|
||||
sceneKeyLight->setIntensity(DEFAULT_SKYBOX_INTENSITY);
|
||||
sceneKeyLight->setAmbientIntensity(DEFAULT_SKYBOX_AMBIENT_INTENSITY);
|
||||
sceneKeyLight->setDirection(DEFAULT_SKYBOX_DIRECTION);
|
||||
|
||||
auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture();
|
||||
sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance());
|
||||
sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
|
||||
|
||||
qApp->getDefaultSkybox()->render(batch, args->getViewFrustum());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4443,7 +4484,6 @@ void Application::updateWindowTitle() const {
|
|||
#endif
|
||||
_window->setWindowTitle(title);
|
||||
}
|
||||
|
||||
void Application::clearDomainOctreeDetails() {
|
||||
|
||||
// if we're about to quit, we really don't need to do any of these things...
|
||||
|
@ -4469,6 +4509,7 @@ void Application::clearDomainOctreeDetails() {
|
|||
getEntities()->clear();
|
||||
|
||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
|
||||
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
|
||||
|
||||
_recentlyClearedDomain = true;
|
||||
|
|
|
@ -65,6 +65,9 @@
|
|||
#include "ui/overlays/Overlays.h"
|
||||
#include "UndoStackScriptingInterface.h"
|
||||
|
||||
#include <procedural/ProceduralSkybox.h>
|
||||
#include <model/Skybox.h>
|
||||
|
||||
class OffscreenGLCanvas;
|
||||
class GLCanvas;
|
||||
class FaceTracker;
|
||||
|
@ -249,6 +252,10 @@ public:
|
|||
float getAvatarSimrate() const { return _avatarSimCounter.rate(); }
|
||||
float getAverageSimsPerSecond() const { return _simCounter.rate(); }
|
||||
|
||||
model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; }
|
||||
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
|
||||
gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; }
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
||||
|
@ -565,6 +572,10 @@ private:
|
|||
QString _returnFromFullScreenMirrorTo;
|
||||
|
||||
ConnectionMonitor _connectionMonitor;
|
||||
|
||||
model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() } ;
|
||||
gpu::TexturePointer _defaultSkyboxTexture;
|
||||
gpu::TexturePointer _defaultSkyboxAmbientTexture;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -337,7 +337,7 @@ Menu::Menu() {
|
|||
// Developer > Render >>>
|
||||
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DefaultSkybox, 0, true);
|
||||
|
||||
// Developer > Render > Throttle FPS If Not Focus
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true);
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace MenuOption {
|
|||
const QString CrashNewFaultThreaded = "New Fault (threaded)";
|
||||
const QString DeadlockInterface = "Deadlock Interface";
|
||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||
const QString DefaultSkybox = "Default Skybox";
|
||||
const QString DeleteBookmark = "Delete Bookmark...";
|
||||
const QString DisableActivityLogger = "Disable Activity Logger";
|
||||
const QString DisableEyelidAdjustment = "Disable Eyelid Adjustment";
|
||||
|
@ -175,7 +176,6 @@ namespace MenuOption {
|
|||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode";
|
||||
const QString SimulateEyeTracking = "Simulate";
|
||||
const QString SMIEyeTracking = "SMI Eye Tracking";
|
||||
const QString Stars = "Stars";
|
||||
const QString Stats = "Stats";
|
||||
const QString StopAllScripts = "Stop All Scripts";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
|
|
|
@ -1,216 +0,0 @@
|
|||
//
|
||||
// Stars.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Tobias Schwinger on 3/22/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Stars.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <NumericalConstants.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <TextureCache.h>
|
||||
#include <RenderArgs.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include <render-utils/stars_vert.h>
|
||||
#include <render-utils/stars_frag.h>
|
||||
|
||||
#include <render-utils/standardTransformPNTC_vert.h>
|
||||
#include <render-utils/starsGrid_frag.h>
|
||||
|
||||
//static const float TILT = 0.23f;
|
||||
static const float TILT = 0.0f;
|
||||
static const unsigned int STARFIELD_NUM_STARS = 50000;
|
||||
static const unsigned int STARFIELD_SEED = 1;
|
||||
static const float STAR_COLORIZATION = 0.1f;
|
||||
|
||||
static const float TAU = 6.28318530717958f;
|
||||
//static const float HALF_TAU = TAU / 2.0f;
|
||||
//static const float QUARTER_TAU = TAU / 4.0f;
|
||||
//static const float MILKY_WAY_WIDTH = TAU / 30.0f; // width in radians of one half of the Milky Way
|
||||
//static const float MILKY_WAY_INCLINATION = 0.0f; // angle of Milky Way from horizontal in degrees
|
||||
//static const float MILKY_WAY_RATIO = 0.4f;
|
||||
static const char* UNIFORM_TIME_NAME = "iGlobalTime";
|
||||
|
||||
// Produce a random float value between 0 and 1
|
||||
static float frand() {
|
||||
return (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
|
||||
// http://mathworld.wolfram.com/SpherePointPicking.html
|
||||
static vec2 randPolar() {
|
||||
vec2 result(frand(), frand());
|
||||
result.x *= TAU;
|
||||
result.y = powf(result.y, 2.0) / 2.0f;
|
||||
if (frand() > 0.5f) {
|
||||
result.y = 0.5f - result.y;
|
||||
} else {
|
||||
result.y += 0.5f;
|
||||
}
|
||||
result.y = acos((2.0f * result.y) - 1.0f);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static vec3 fromPolar(const vec2& polar) {
|
||||
float sinTheta = sin(polar.x);
|
||||
float cosTheta = cos(polar.x);
|
||||
float sinPhi = sin(polar.y);
|
||||
float cosPhi = cos(polar.y);
|
||||
return vec3(
|
||||
cosTheta * sinPhi,
|
||||
cosPhi,
|
||||
sinTheta * sinPhi);
|
||||
}
|
||||
|
||||
|
||||
// computeStarColor
|
||||
// - Generate a star color.
|
||||
//
|
||||
// colorization can be a value between 0 and 1 specifying how colorful the resulting star color is.
|
||||
//
|
||||
// 0 = completely black & white
|
||||
// 1 = very colorful
|
||||
unsigned computeStarColor(float colorization) {
|
||||
unsigned char red, green, blue;
|
||||
if (randFloat() < 0.3f) {
|
||||
// A few stars are colorful
|
||||
red = 2 + (rand() % 254);
|
||||
green = 2 + round((red * (1 - colorization)) + ((rand() % 254) * colorization));
|
||||
blue = 2 + round((red * (1 - colorization)) + ((rand() % 254) * colorization));
|
||||
} else {
|
||||
// Most stars are dimmer and white
|
||||
red = green = blue = 2 + (rand() % 128);
|
||||
}
|
||||
return red | (green << 8) | (blue << 16);
|
||||
}
|
||||
|
||||
struct StarVertex {
|
||||
vec4 position;
|
||||
vec4 colorAndSize;
|
||||
};
|
||||
|
||||
static const int STARS_VERTICES_SLOT{ 0 };
|
||||
static const int STARS_COLOR_SLOT{ 1 };
|
||||
|
||||
gpu::PipelinePointer Stars::_gridPipeline{};
|
||||
gpu::PipelinePointer Stars::_starsPipeline{};
|
||||
int32_t Stars::_timeSlot{ -1 };
|
||||
|
||||
void Stars::init() {
|
||||
if (!_gridPipeline) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(standardTransformPNTC_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(starsGrid_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
_timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME);
|
||||
if (_timeSlot == gpu::Shader::INVALID_LOCATION) {
|
||||
_timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME);
|
||||
}
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_gridPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
if (!_starsPipeline) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(stars_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(stars_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setAntialiasedLineEnable(true); // line smoothing also smooth points
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_starsPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
unsigned limit = STARFIELD_NUM_STARS;
|
||||
std::vector<StarVertex> points;
|
||||
points.resize(limit);
|
||||
|
||||
{ // generate stars
|
||||
QElapsedTimer startTime;
|
||||
startTime.start();
|
||||
|
||||
vertexBuffer.reset(new gpu::Buffer);
|
||||
|
||||
srand(STARFIELD_SEED);
|
||||
for (size_t star = 0; star < limit; ++star) {
|
||||
points[star].position = vec4(fromPolar(randPolar()), 1);
|
||||
float size = frand() * 2.5f + 0.5f;
|
||||
if (frand() < STAR_COLORIZATION) {
|
||||
vec3 color(frand() / 2.0f + 0.5f, frand() / 2.0f + 0.5f, frand() / 2.0f + 0.5f);
|
||||
points[star].colorAndSize = vec4(color, size);
|
||||
} else {
|
||||
vec3 color(frand() / 2.0f + 0.5f);
|
||||
points[star].colorAndSize = vec4(color, size);
|
||||
}
|
||||
}
|
||||
|
||||
double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms
|
||||
qDebug() << "Total time to generate stars: " << timeDiff << " msec";
|
||||
}
|
||||
|
||||
gpu::Element positionElement, colorElement;
|
||||
const size_t VERTEX_STRIDE = sizeof(StarVertex);
|
||||
|
||||
vertexBuffer->append(VERTEX_STRIDE * limit, (const gpu::Byte*)&points[0]);
|
||||
streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, STARS_VERTICES_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, STARS_COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA));
|
||||
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
|
||||
colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
|
||||
|
||||
size_t offset = offsetof(StarVertex, position);
|
||||
positionView = gpu::BufferView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement);
|
||||
|
||||
offset = offsetof(StarVertex, colorAndSize);
|
||||
colorView = gpu::BufferView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, colorElement);
|
||||
}
|
||||
|
||||
// FIXME star colors
|
||||
void Stars::render(RenderArgs* renderArgs, float alpha) {
|
||||
std::call_once(once, [&]{ init(); });
|
||||
|
||||
|
||||
auto modelCache = DependencyManager::get<ModelCache>();
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
batch.setViewTransform(Transform());
|
||||
batch.setProjectionTransform(renderArgs->getViewFrustum().getProjection());
|
||||
batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->getViewFrustum().getOrientation()) *
|
||||
quat(vec3(TILT, 0, 0))));
|
||||
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
||||
|
||||
// Render the world lines
|
||||
batch.setPipeline(_gridPipeline);
|
||||
static auto start = usecTimestampNow();
|
||||
float msecs = (float)(usecTimestampNow() - start) / (float)USECS_PER_MSEC;
|
||||
float secs = msecs / (float)MSECS_PER_SECOND;
|
||||
batch._glUniform1f(_timeSlot, secs);
|
||||
geometryCache->renderCube(batch);
|
||||
|
||||
// Render the stars
|
||||
batch.setPipeline(_starsPipeline);
|
||||
batch.setInputFormat(streamFormat);
|
||||
batch.setInputBuffer(STARS_VERTICES_SLOT, positionView);
|
||||
batch.setInputBuffer(STARS_COLOR_SLOT, colorView);
|
||||
batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS);
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
//
|
||||
// Stars.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Tobias Schwinger on 3/22/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_Stars_h
|
||||
#define hifi_Stars_h
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
class RenderArgs;
|
||||
|
||||
// Starfield rendering component.
|
||||
class Stars {
|
||||
public:
|
||||
Stars() = default;
|
||||
~Stars() = default;
|
||||
|
||||
Stars(Stars const&) = delete;
|
||||
Stars& operator=(Stars const&) = delete;
|
||||
|
||||
// Renders the starfield from a local viewer's perspective.
|
||||
// The parameters specifiy the field of view.
|
||||
void render(RenderArgs* args, float alpha);
|
||||
|
||||
private:
|
||||
// Pipelines
|
||||
static gpu::PipelinePointer _gridPipeline;
|
||||
static gpu::PipelinePointer _starsPipeline;
|
||||
static int32_t _timeSlot;
|
||||
|
||||
// Buffers
|
||||
gpu::BufferPointer vertexBuffer;
|
||||
gpu::Stream::FormatPointer streamFormat;
|
||||
gpu::BufferView positionView;
|
||||
gpu::BufferView colorView;
|
||||
std::once_flag once;
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Stars_h
|
|
@ -780,7 +780,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
|||
|
||||
{
|
||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, true, true, true);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true);
|
||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||
bevelDistance, backgroundColor);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "Util.h"
|
||||
#include "ui/Stats.h"
|
||||
#include "ui/AvatarInputs.h"
|
||||
#include "OffscreenUi.h"
|
||||
#include <QQmlContext>
|
||||
|
||||
const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f };
|
||||
static const float ORTHO_NEAR_CLIP = -1000.0f;
|
||||
|
@ -177,13 +179,11 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) {
|
|||
glm::vec2 texCoordMinCorner(0.0f, 0.0f);
|
||||
glm::vec2 texCoordMaxCorner(viewport.width() * renderRatio / float(selfieTexture->getWidth()), viewport.height() * renderRatio / float(selfieTexture->getHeight()));
|
||||
|
||||
|
||||
geometryCache->useSimpleDrawPipeline(batch, true);
|
||||
batch.setResourceTexture(0, selfieTexture);
|
||||
geometryCache->renderQuad(batch, bottomLeft, topRight, texCoordMinCorner, texCoordMaxCorner, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
float alpha = DependencyManager::get<OffscreenUi>()->getDesktop()->property("unpinnedAlpha").toFloat();
|
||||
geometryCache->renderQuad(batch, bottomLeft, topRight, texCoordMinCorner, texCoordMaxCorner, glm::vec4(1.0f, 1.0f, 1.0f, alpha));
|
||||
|
||||
batch.setResourceTexture(0, renderArgs->_whiteTexture);
|
||||
geometryCache->useSimpleDrawPipeline(batch, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
|||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = args->_pipeline;
|
||||
if (!pipeline) {
|
||||
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
if (_isSolid) {
|
||||
|
@ -55,7 +55,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
|||
batch->setModelTransform(transform);
|
||||
geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline);
|
||||
} else {
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
if (getIsDashedLine()) {
|
||||
transform.setScale(1.0f);
|
||||
batch->setModelTransform(transform);
|
||||
|
|
|
@ -57,12 +57,12 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (getIsDashedLine()) {
|
||||
// TODO: add support for color to renderDashedLine()
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
geometryCache->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||
} else if (_glow > 0.0f) {
|
||||
geometryCache->renderGlowLine(*batch, _start, _end, colorv4, _glow, _glowWidth, _geometryCacheID);
|
||||
} else {
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
geometryCache->renderLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public slots:
|
|||
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
||||
bool editOverlays(const QVariant& propertiesById);
|
||||
|
||||
/// deletes a particle
|
||||
/// deletes an overlay
|
||||
void deleteOverlay(unsigned int id);
|
||||
|
||||
/// get the string type of the overlay used in addOverlay
|
||||
|
|
|
@ -61,7 +61,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
|||
geometryCache->bindSimpleProgram(*batch);
|
||||
geometryCache->renderQuad(*batch, topLeft, bottomRight, rectangleColor);
|
||||
} else {
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
if (getIsDashedLine()) {
|
||||
glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
|
|
|
@ -47,7 +47,7 @@ void Shape3DOverlay::render(RenderArgs* args) {
|
|||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = args->_pipeline;
|
||||
if (!pipeline) {
|
||||
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
transform.setScale(dimensions);
|
||||
|
|
|
@ -46,7 +46,7 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
|||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = args->_pipeline;
|
||||
if (!pipeline) {
|
||||
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
if (_isSolid) {
|
||||
|
|
|
@ -1638,7 +1638,9 @@ void AvatarData::setAttachmentsVariant(const QVariantList& variant) {
|
|||
for (const auto& attachmentVar : variant) {
|
||||
AttachmentData attachment;
|
||||
attachment.fromVariant(attachmentVar);
|
||||
newAttachments.append(attachment);
|
||||
if (!attachment.modelURL.isEmpty()) {
|
||||
newAttachments.append(attachment);
|
||||
}
|
||||
}
|
||||
setAttachmentData(newAttachments);
|
||||
}
|
||||
|
|
|
@ -375,7 +375,6 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
|||
}
|
||||
|
||||
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application background through
|
||||
|
||||
return; // Early exit
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace render {
|
|||
if (payload->entity->getType() == EntityTypes::Light) {
|
||||
return ItemKey::Builder::light();
|
||||
}
|
||||
if (payload && payload->entity->getType() == EntityTypes::PolyLine) {
|
||||
if (payload && payload->entity->isTransparent()) {
|
||||
return ItemKey::Builder::transparentShape();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,17 @@ public: \
|
|||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
|
||||
virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); _renderHelper.notifyChanged(); } \
|
||||
virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); _renderHelper.notifyChanged(); } \
|
||||
void checkFading() { \
|
||||
bool transparent = isTransparent(); \
|
||||
if (transparent != _prevIsTransparent) { \
|
||||
_renderHelper.notifyChanged(); \
|
||||
_isFading = false; \
|
||||
_prevIsTransparent = transparent; \
|
||||
} \
|
||||
} \
|
||||
private: \
|
||||
SimpleRenderableEntityItem _renderHelper;
|
||||
SimpleRenderableEntityItem _renderHelper; \
|
||||
bool _prevIsTransparent { isTransparent() };
|
||||
|
||||
|
||||
#endif // hifi_RenderableEntityItem_h
|
||||
|
|
|
@ -28,6 +28,8 @@ EntityItemPointer RenderableLightEntityItem::factory(const EntityItemID& entityI
|
|||
void RenderableLightEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableLightEntityItem::render");
|
||||
assert(getType() == EntityTypes::Light);
|
||||
checkFading();
|
||||
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::quat rotation = getRotation();
|
||||
|
@ -35,7 +37,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
|
|||
|
||||
glm::vec3 color = toGlm(getXColor());
|
||||
|
||||
float intensity = getIntensity();
|
||||
float intensity = getIntensity() * (_isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f);
|
||||
float falloffRadius = getFalloffRadius();
|
||||
float exponent = getExponent();
|
||||
float cutoff = glm::radians(getCutoff());
|
||||
|
|
|
@ -176,25 +176,6 @@ void RenderableModelEntityItem::doInitialModelSimulation() {
|
|||
_needsInitialSimulation = false;
|
||||
}
|
||||
|
||||
|
||||
// TODO: we need a solution for changes to the postion/rotation/etc of a model...
|
||||
// this current code path only addresses that in this setup case... not the changing/moving case
|
||||
bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) {
|
||||
if (!_model && renderArgs) {
|
||||
// TODO: this getModel() appears to be about 3% of model render time. We should optimize
|
||||
PerformanceTimer perfTimer("getModel");
|
||||
EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(renderArgs->_renderer);
|
||||
getModel(renderer);
|
||||
}
|
||||
if (renderArgs && _model && _needsInitialSimulation && _model->isActive() && _model->isLoaded()) {
|
||||
// make sure to simulate so everything gets set up correctly for rendering
|
||||
doInitialModelSimulation();
|
||||
_model->renderSetup(renderArgs);
|
||||
}
|
||||
bool ready = !_needsInitialSimulation && _model && _model->readyToAddToScene(renderArgs);
|
||||
return ready;
|
||||
}
|
||||
|
||||
class RenderableModelEntityItemMeta {
|
||||
public:
|
||||
RenderableModelEntityItemMeta(EntityItemPointer entity) : entity(entity){ }
|
||||
|
@ -371,6 +352,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
PerformanceTimer perfTimer("RMEIrender");
|
||||
assert(getType() == EntityTypes::Model);
|
||||
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
// we will watch for that and ask the model to update it's render items
|
||||
if (_model && _model->getRenderItemsNeedUpdate()) {
|
||||
_model->updateRenderItems();
|
||||
}
|
||||
|
||||
if (hasModel()) {
|
||||
// Prepare the current frame
|
||||
{
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
|
||||
void doInitialModelSimulation();
|
||||
|
||||
virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr);
|
||||
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override;
|
||||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override;
|
||||
|
||||
|
@ -92,6 +91,9 @@ public:
|
|||
|
||||
render::ItemID getMetaRenderItem() { return _myMetaItem; }
|
||||
|
||||
// Transparency is handled in ModelMeshPartPayload
|
||||
bool isTransparent() override { return false; }
|
||||
|
||||
private:
|
||||
QVariantMap parseTexturesToMap(QString textures);
|
||||
void remapTextures();
|
||||
|
|
|
@ -167,6 +167,8 @@ void RenderablePolyLineEntityItem::update(const quint64& now) {
|
|||
}
|
||||
|
||||
void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
||||
checkFading();
|
||||
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
if (_points.size() < 2 || _normals.size () < 2 || _strokeWidths.size() < 2) {
|
||||
return;
|
||||
|
@ -204,5 +206,9 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
|||
batch.setInputFormat(_format);
|
||||
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||
|
||||
if (_isFading) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime));
|
||||
}
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
||||
};
|
||||
|
|
|
@ -30,7 +30,9 @@ public:
|
|||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual void update(const quint64& now) override;
|
||||
virtual bool needsToCallUpdate() const override { return true; };
|
||||
virtual bool needsToCallUpdate() const override { return true; }
|
||||
|
||||
bool isTransparent() override { return true; }
|
||||
|
||||
SIMPLE_RENDERABLE();
|
||||
|
||||
|
@ -47,7 +49,6 @@ protected:
|
|||
gpu::BufferView _uniformBuffer;
|
||||
unsigned int _numVertices;
|
||||
QVector<glm::vec3> _vertices;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
|
||||
void initializePolyVox();
|
||||
|
||||
virtual void somethingChangedNotification() {
|
||||
virtual void somethingChangedNotification() override {
|
||||
// This gets called from EnityItem::readEntityDataFromBuffer every time a packet describing
|
||||
// this entity comes from the entity-server. It gets called even if nothing has actually changed
|
||||
// (see the comment in EntityItem.cpp). If that gets fixed, this could be used to know if we
|
||||
|
@ -58,19 +58,19 @@ public:
|
|||
// _needsModelReload = true;
|
||||
}
|
||||
|
||||
virtual uint8_t getVoxel(int x, int y, int z);
|
||||
virtual bool setVoxel(int x, int y, int z, uint8_t toValue);
|
||||
virtual uint8_t getVoxel(int x, int y, int z) override;
|
||||
virtual bool setVoxel(int x, int y, int z, uint8_t toValue) override;
|
||||
|
||||
void render(RenderArgs* args);
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
void render(RenderArgs* args) override;
|
||||
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
void** intersectedObject, bool precisionPicking) const;
|
||||
void** intersectedObject, bool precisionPicking) const override;
|
||||
|
||||
virtual void setVoxelData(QByteArray voxelData);
|
||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
||||
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
|
||||
virtual void setVoxelData(QByteArray voxelData) override;
|
||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize) override;
|
||||
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) override;
|
||||
|
||||
glm::vec3 getSurfacePositionAdjustment() const;
|
||||
glm::mat4 voxelToWorldMatrix() const;
|
||||
|
@ -78,45 +78,45 @@ public:
|
|||
glm::mat4 voxelToLocalMatrix() const;
|
||||
glm::mat4 localToVoxelMatrix() const;
|
||||
|
||||
virtual ShapeType getShapeType() const;
|
||||
virtual bool shouldBePhysical() const { return !isDead(); }
|
||||
virtual bool isReadyToComputeShape();
|
||||
virtual void computeShapeInfo(ShapeInfo& info);
|
||||
virtual ShapeType getShapeType() const override;
|
||||
virtual bool shouldBePhysical() const override { return !isDead(); }
|
||||
virtual bool isReadyToComputeShape() override;
|
||||
virtual void computeShapeInfo(ShapeInfo& info) override;
|
||||
|
||||
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const;
|
||||
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const;
|
||||
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const;
|
||||
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const;
|
||||
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const override;
|
||||
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const override;
|
||||
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const override;
|
||||
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const override;
|
||||
|
||||
// coords are in voxel-volume space
|
||||
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
|
||||
virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue);
|
||||
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) override;
|
||||
virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue) override;
|
||||
|
||||
// coords are in world-space
|
||||
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue);
|
||||
virtual bool setAll(uint8_t toValue);
|
||||
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue);
|
||||
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) override;
|
||||
virtual bool setAll(uint8_t toValue) override;
|
||||
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
|
||||
|
||||
virtual void setXTextureURL(QString xTextureURL);
|
||||
virtual void setYTextureURL(QString yTextureURL);
|
||||
virtual void setZTextureURL(QString zTextureURL);
|
||||
virtual void setXTextureURL(QString xTextureURL) override;
|
||||
virtual void setYTextureURL(QString yTextureURL) override;
|
||||
virtual void setZTextureURL(QString zTextureURL) override;
|
||||
|
||||
virtual bool addToScene(EntityItemPointer self,
|
||||
std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges);
|
||||
render::PendingChanges& pendingChanges) override;
|
||||
virtual void removeFromScene(EntityItemPointer self,
|
||||
std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges);
|
||||
render::PendingChanges& pendingChanges) override;
|
||||
|
||||
virtual void setXNNeighborID(const EntityItemID& xNNeighborID);
|
||||
virtual void setYNNeighborID(const EntityItemID& yNNeighborID);
|
||||
virtual void setZNNeighborID(const EntityItemID& zNNeighborID);
|
||||
virtual void setXNNeighborID(const EntityItemID& xNNeighborID) override;
|
||||
virtual void setYNNeighborID(const EntityItemID& yNNeighborID) override;
|
||||
virtual void setZNNeighborID(const EntityItemID& zNNeighborID) override;
|
||||
|
||||
virtual void setXPNeighborID(const EntityItemID& xPNeighborID);
|
||||
virtual void setYPNeighborID(const EntityItemID& yPNeighborID);
|
||||
virtual void setZPNeighborID(const EntityItemID& zPNeighborID);
|
||||
virtual void setXPNeighborID(const EntityItemID& xPNeighborID) override;
|
||||
virtual void setYPNeighborID(const EntityItemID& yPNeighborID) override;
|
||||
virtual void setZPNeighborID(const EntityItemID& zPNeighborID) override;
|
||||
|
||||
virtual void updateRegistrationPoint(const glm::vec3& value);
|
||||
virtual void updateRegistrationPoint(const glm::vec3& value) override;
|
||||
|
||||
void setVoxelsFromData(QByteArray uncompressedData, quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize);
|
||||
void forEachVoxelValue(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize,
|
||||
|
@ -131,6 +131,9 @@ public:
|
|||
|
||||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; }); }
|
||||
|
||||
// Transparent polyvox didn't seem to be working so disable for now
|
||||
bool isTransparent() override { return false; }
|
||||
|
||||
private:
|
||||
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
|
||||
// may not match _voxelVolumeSize.
|
||||
|
@ -161,7 +164,7 @@ private:
|
|||
// these are run off the main thread
|
||||
void decompressVolumeData();
|
||||
void compressVolumeDataAndSendEditPacket();
|
||||
virtual void getMesh(); // recompute mesh
|
||||
virtual void getMesh() override; // recompute mesh
|
||||
void computeShapeInfoWorker();
|
||||
|
||||
// these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID
|
||||
|
|
|
@ -40,7 +40,6 @@ static std::array<GeometryCache::Shape, entity::NUM_SHAPES> MAPPING { {
|
|||
GeometryCache::Cylinder,
|
||||
} };
|
||||
|
||||
|
||||
RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity = std::make_shared<RenderableShapeEntityItem>(entityID);
|
||||
entity->setProperties(properties);
|
||||
|
@ -72,20 +71,26 @@ void RenderableShapeEntityItem::setUserData(const QString& value) {
|
|||
}
|
||||
}
|
||||
|
||||
bool RenderableShapeEntityItem::isTransparent() {
|
||||
if (_procedural && _procedural->isFading()) {
|
||||
float isFading = Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f;
|
||||
_procedural->setIsFading(isFading);
|
||||
return isFading;
|
||||
} else {
|
||||
return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableShapeEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||
//Q_ASSERT(getType() == EntityTypes::Shape);
|
||||
Q_ASSERT(args->_batch);
|
||||
checkFading();
|
||||
|
||||
if (!_procedural) {
|
||||
_procedural.reset(new Procedural(getUserData()));
|
||||
_procedural->_vertexSource = simple_vert;
|
||||
_procedural->_fragmentSource = simple_frag;
|
||||
_procedural->_state->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural->_state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
_procedural->_state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
}
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
@ -102,14 +107,17 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
|
|||
if (_procedural->ready()) {
|
||||
_procedural->prepare(batch, getPosition(), getDimensions(), getOrientation());
|
||||
auto outColor = _procedural->getColor(color);
|
||||
outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f;
|
||||
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
||||
DependencyManager::get<GeometryCache>()->renderShape(batch, MAPPING[_shape]);
|
||||
} else {
|
||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
DependencyManager::get<GeometryCache>()->renderSolidShapeInstance(batch, MAPPING[_shape], color);
|
||||
color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
|
||||
geometryCache->renderSolidShapeInstance(batch, MAPPING[_shape], color, pipeline);
|
||||
}
|
||||
|
||||
|
||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getShapeTriangleCount(MAPPING[_shape]);
|
||||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
||||
|
|
|
@ -26,10 +26,12 @@ public:
|
|||
void render(RenderArgs* args) override;
|
||||
void setUserData(const QString& value) override;
|
||||
|
||||
SIMPLE_RENDERABLE();
|
||||
bool isTransparent() override;
|
||||
|
||||
private:
|
||||
QSharedPointer<Procedural> _procedural;
|
||||
std::unique_ptr<Procedural> _procedural { nullptr };
|
||||
|
||||
SIMPLE_RENDERABLE();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include <PerfStat.h>
|
||||
#include <Transform.h>
|
||||
|
||||
|
||||
|
||||
#include "RenderableTextEntityItem.h"
|
||||
#include "GLMHelpers.h"
|
||||
|
||||
|
@ -29,10 +27,13 @@ EntityItemPointer RenderableTextEntityItem::factory(const EntityItemID& entityID
|
|||
void RenderableTextEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
||||
Q_ASSERT(getType() == EntityTypes::Text);
|
||||
checkFading();
|
||||
|
||||
static const float SLIGHTLY_BEHIND = -0.005f;
|
||||
glm::vec4 textColor = glm::vec4(toGlm(getTextColorX()), 1.0f);
|
||||
glm::vec4 backgroundColor = glm::vec4(toGlm(getBackgroundColorX()), 1.0f);
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
bool transparent = fadeRatio < 1.0f;
|
||||
glm::vec4 textColor = glm::vec4(toGlm(getTextColorX()), fadeRatio);
|
||||
glm::vec4 backgroundColor = glm::vec4(toGlm(getBackgroundColorX()), fadeRatio);
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
|
||||
// Render background
|
||||
|
@ -62,7 +63,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, transparent, false, false, true);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, minCorner, maxCorner, backgroundColor);
|
||||
|
||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
||||
|
|
|
@ -164,6 +164,8 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) {
|
|||
}
|
||||
|
||||
void RenderableWebEntityItem::render(RenderArgs* args) {
|
||||
checkFading();
|
||||
|
||||
#ifdef WANT_EXTRA_DEBUGGING
|
||||
{
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
@ -181,6 +183,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
|||
if (!buildWebSurface(static_cast<EntityTreeRenderer*>(args->_renderer))) {
|
||||
return;
|
||||
}
|
||||
_fadeStartTime = usecTimestampNow();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -207,8 +210,11 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
|||
batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture);
|
||||
}
|
||||
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(batch);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio));
|
||||
}
|
||||
|
||||
void RenderableWebEntityItem::setSourceUrl(const QString& value) {
|
||||
|
|
|
@ -39,7 +39,7 @@ void main(void) {
|
|||
vec3 color = varColor.rgb;
|
||||
packDeferredFragmentTranslucent(
|
||||
interpolatedNormal * frontCondition,
|
||||
texel.a,
|
||||
texel.a * varColor.a,
|
||||
polyline.color * texel.rgb,
|
||||
vec3(0.01, 0.01, 0.01),
|
||||
10.0);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// model.frag
|
||||
// polyvox.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Seth Alves on 2015-8-3
|
||||
|
@ -41,5 +41,13 @@ void main(void) {
|
|||
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
|
||||
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
|
||||
|
||||
packDeferredFragment(_normal, 1.0, vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
|
||||
packDeferredFragment(
|
||||
_normal,
|
||||
1.0,
|
||||
vec3(diffuse),
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ out vec4 varColor;
|
|||
out vec2 varTexcoord;
|
||||
|
||||
const int NUM_VERTICES_PER_PARTICLE = 4;
|
||||
// This ordering ensures that un-rotated particles render upright in the wiewer.
|
||||
// This ordering ensures that un-rotated particles render upright in the viewer.
|
||||
const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE](
|
||||
vec4(-1.0, 1.0, 0.0, 0.0),
|
||||
vec4(-1.0, -1.0, 0.0, 0.0),
|
||||
|
|
|
@ -2212,4 +2212,4 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt
|
|||
}
|
||||
QUuid empty;
|
||||
properties.setParentID(empty);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
#include <Transform.h>
|
||||
#include <Sound.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
#include <Interpolate.h>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include "EntityItemPropertiesDefaults.h"
|
||||
|
@ -431,6 +432,7 @@ public:
|
|||
QUuid getOwningAvatarID() const { return _owningAvatarID; }
|
||||
void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; }
|
||||
|
||||
virtual bool isTransparent() { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -561,7 +563,8 @@ protected:
|
|||
quint64 _lastUpdatedAngularVelocityTimestamp { 0 };
|
||||
quint64 _lastUpdatedAccelerationTimestamp { 0 };
|
||||
|
||||
|
||||
quint64 _fadeStartTime { usecTimestampNow() };
|
||||
bool _isFading { true };
|
||||
};
|
||||
|
||||
#endif // hifi_EntityItem_h
|
||||
|
|
|
@ -634,8 +634,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
|||
}
|
||||
} else {
|
||||
// if the entity type doesn't support a detailed intersection, then just return the non-AABox results
|
||||
// Never intersect with particle effect entities
|
||||
if (localDistance < distance && EntityTypes::getEntityTypeName(entity->getType()) != "ParticleEffect") {
|
||||
// Never intersect with particle entities
|
||||
if (localDistance < distance && entity->getType() != EntityTypes::ParticleEffect) {
|
||||
distance = localDistance;
|
||||
face = localFace;
|
||||
surfaceNormal = localSurfaceNormal;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <NumericalConstants.h>
|
||||
#include <Finally.h>
|
||||
#include <PathUtils.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
|
||||
#include "OffscreenGLCanvas.h"
|
||||
#include "GLEscrow.h"
|
||||
|
@ -55,6 +56,22 @@ private:
|
|||
friend class OffscreenQmlSurface;
|
||||
};
|
||||
|
||||
class QmlNetworkAccessManager : public NetworkAccessManager {
|
||||
public:
|
||||
friend class QmlNetworkAccessManagerFactory;
|
||||
protected:
|
||||
QmlNetworkAccessManager(QObject* parent) : NetworkAccessManager(parent) { }
|
||||
};
|
||||
|
||||
class QmlNetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory {
|
||||
public:
|
||||
QNetworkAccessManager* create(QObject* parent);
|
||||
};
|
||||
|
||||
QNetworkAccessManager* QmlNetworkAccessManagerFactory::create(QObject* parent) {
|
||||
return new QmlNetworkAccessManager(parent);
|
||||
}
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(offscreenFocus)
|
||||
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
|
||||
|
||||
|
@ -402,6 +419,8 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
// Create a QML engine.
|
||||
_qmlEngine = new QQmlEngine;
|
||||
|
||||
_qmlEngine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory);
|
||||
|
||||
auto importList = _qmlEngine->importPathList();
|
||||
importList.insert(importList.begin(), PathUtils::resourcesPath());
|
||||
_qmlEngine->setImportPathList(importList);
|
||||
|
|
|
@ -596,7 +596,7 @@ int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindin
|
|||
}
|
||||
|
||||
Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER);
|
||||
buffers.insert(Shader::Slot(name, binding, element, Resource::BUFFER));
|
||||
buffers.insert(Shader::Slot(name, binding, element, Resource::BUFFER, size));
|
||||
}
|
||||
return buffersCount;
|
||||
}
|
||||
|
|
|
@ -53,19 +53,22 @@ public:
|
|||
int32 _location{INVALID_LOCATION};
|
||||
Element _element;
|
||||
uint16 _resourceType{Resource::BUFFER};
|
||||
uint32 _size { 0 };
|
||||
|
||||
Slot(const Slot& s) : _name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType) {}
|
||||
Slot(Slot&& s) : _name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType) {}
|
||||
Slot(const std::string& name, int32 location, const Element& element, uint16 resourceType = Resource::BUFFER) :
|
||||
_name(name), _location(location), _element(element), _resourceType(resourceType) {}
|
||||
Slot(const Slot& s) : _name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(Slot&& s) : _name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(const std::string& name, int32 location, const Element& element, uint16 resourceType = Resource::BUFFER, uint32 size = 0) :
|
||||
_name(name), _location(location), _element(element), _resourceType(resourceType), _size(size) {}
|
||||
Slot(const std::string& name) : _name(name) {}
|
||||
|
||||
|
||||
Slot& operator= (const Slot& s) {
|
||||
_name = s._name;
|
||||
_location = s._location;
|
||||
_element = s._element;
|
||||
_resourceType = s._resourceType;
|
||||
return (*this); }
|
||||
_size = s._size;
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
class Binding {
|
||||
|
|
|
@ -700,8 +700,6 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
|
|||
return false;
|
||||
}
|
||||
|
||||
const float UCHAR_TO_FLOAT = 1.0f / float(std::numeric_limits<unsigned char>::max());
|
||||
|
||||
// for each face of cube texture
|
||||
for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
|
||||
|
||||
|
@ -788,12 +786,9 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
|
|||
uint pixOffsetIndex = (x + y * width) * numComponents;
|
||||
|
||||
// get color from texture and map to range [0, 1]
|
||||
glm::vec3 clr(float(data[pixOffsetIndex]) * UCHAR_TO_FLOAT,
|
||||
float(data[pixOffsetIndex+1]) * UCHAR_TO_FLOAT,
|
||||
float(data[pixOffsetIndex+2]) * UCHAR_TO_FLOAT);
|
||||
|
||||
// Gamma correct
|
||||
clr = ColorUtils::sRGBToLinearVec3(clr);
|
||||
glm::vec3 clr(ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex]),
|
||||
ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex + 1]),
|
||||
ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex + 2]));
|
||||
|
||||
// scale color and add to previously accumulated coefficients
|
||||
sphericalHarmonicsScale(shBuffB.data(), order,
|
||||
|
|
|
@ -171,7 +171,8 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const
|
|||
}
|
||||
|
||||
|
||||
NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type) {
|
||||
NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type,
|
||||
const QVariantMap& options = QVariantMap()) {
|
||||
using Type = NetworkTexture;
|
||||
|
||||
switch (type) {
|
||||
|
@ -188,7 +189,11 @@ NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type t
|
|||
break;
|
||||
}
|
||||
case Type::CUBE_TEXTURE: {
|
||||
return model::TextureUsage::createCubeTextureFromImage;
|
||||
if (options.value("generateIrradiance", true).toBool()) {
|
||||
return model::TextureUsage::createCubeTextureFromImage;
|
||||
} else {
|
||||
return model::TextureUsage::createCubeTextureFromImageWithoutIrradiance;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type::BUMP_TEXTURE: {
|
||||
|
@ -225,9 +230,9 @@ NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type t
|
|||
}
|
||||
|
||||
/// Returns a texture version of an image file
|
||||
gpu::TexturePointer TextureCache::getImageTexture(const QString& path, Type type) {
|
||||
gpu::TexturePointer TextureCache::getImageTexture(const QString& path, Type type, QVariantMap options) {
|
||||
QImage image = QImage(path);
|
||||
auto loader = getTextureLoaderForType(type);
|
||||
auto loader = getTextureLoaderForType(type, options);
|
||||
return gpu::TexturePointer(loader(image, QUrl::fromLocalFile(path).fileName().toStdString()));
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ public:
|
|||
const gpu::TexturePointer& getNormalFittingTexture();
|
||||
|
||||
/// Returns a texture version of an image file
|
||||
static gpu::TexturePointer getImageTexture(const QString& path, Type type = Type::DEFAULT_TEXTURE);
|
||||
static gpu::TexturePointer getImageTexture(const QString& path, Type type = Type::DEFAULT_TEXTURE, QVariantMap options = QVariantMap());
|
||||
|
||||
/// Loads a texture from the specified URL.
|
||||
NetworkTexturePointer getTexture(const QUrl& url, Type type = Type::DEFAULT_TEXTURE,
|
||||
|
|
|
@ -59,31 +59,28 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val
|
|||
const uint8 OPAQUE_ALPHA = 255;
|
||||
const uint8 TRANSPARENT_ALPHA = 0;
|
||||
if (image.hasAlphaChannel()) {
|
||||
std::map<uint8, uint32> alphaHistogram;
|
||||
|
||||
if (image.format() != QImage::Format_ARGB32) {
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
||||
// Actual alpha channel? create the histogram
|
||||
for (int y = 0; y < image.height(); ++y) {
|
||||
const QRgb* data = reinterpret_cast<const QRgb*>(image.constScanLine(y));
|
||||
for (int x = 0; x < image.width(); ++x) {
|
||||
auto alpha = qAlpha(data[x]);
|
||||
alphaHistogram[alpha] ++;
|
||||
validAlpha = validAlpha || (alpha != OPAQUE_ALPHA);
|
||||
// Figure out if we can use a mask for alpha or not
|
||||
int numOpaques = 0;
|
||||
int numTranslucents = 0;
|
||||
const int NUM_PIXELS = image.width() * image.height();
|
||||
const int MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(NUM_PIXELS));
|
||||
const QRgb* data = reinterpret_cast<const QRgb*>(image.constBits());
|
||||
for (int i = 0; i < NUM_PIXELS; ++i) {
|
||||
auto alpha = qAlpha(data[i]);
|
||||
if (alpha == OPAQUE_ALPHA) {
|
||||
numOpaques++;
|
||||
} else if (alpha != TRANSPARENT_ALPHA) {
|
||||
if (++numTranslucents > MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK) {
|
||||
alphaAsMask = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If alpha was meaningfull refine
|
||||
if (validAlpha && (alphaHistogram.size() > 1)) {
|
||||
auto totalNumPixels = image.height() * image.width();
|
||||
auto numOpaques = alphaHistogram[OPAQUE_ALPHA];
|
||||
auto numTransparents = alphaHistogram[TRANSPARENT_ALPHA];
|
||||
auto numTranslucents = totalNumPixels - numOpaques - numTransparents;
|
||||
|
||||
alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05);
|
||||
}
|
||||
validAlpha = (numOpaques != NUM_PIXELS);
|
||||
}
|
||||
|
||||
if (!validAlpha && image.format() != QImage::Format_RGB888) {
|
||||
|
@ -660,13 +657,12 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = {
|
|||
const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout);
|
||||
|
||||
gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) {
|
||||
|
||||
bool validAlpha = false;
|
||||
bool alphaAsMask = true;
|
||||
QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask);
|
||||
|
||||
gpu::Texture* theTexture = nullptr;
|
||||
if ((image.width() > 0) && (image.height() > 0)) {
|
||||
if ((srcImage.width() > 0) && (srcImage.height() > 0)) {
|
||||
QImage image = srcImage;
|
||||
if (image.format() != QImage::Format_RGB888) {
|
||||
image = image.convertToFormat(QImage::Format_RGB888);
|
||||
}
|
||||
|
||||
gpu::Element formatGPU;
|
||||
gpu::Element formatMip;
|
||||
|
@ -674,7 +670,7 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm
|
|||
|
||||
// Find the layout of the cubemap in the 2D image
|
||||
int foundLayout = CubeLayout::findLayout(image.width(), image.height());
|
||||
|
||||
|
||||
std::vector<QImage> faces;
|
||||
// If found, go extract the faces as separate images
|
||||
if (foundLayout >= 0) {
|
||||
|
@ -729,3 +725,7 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm
|
|||
gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) {
|
||||
return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, true);
|
||||
}
|
||||
|
||||
gpu::Texture* TextureUsage::createCubeTextureFromImageWithoutIrradiance(const QImage& srcImage, const std::string& srcImageName) {
|
||||
return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, false);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
static gpu::Texture* createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName);
|
||||
static gpu::Texture* createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName);
|
||||
static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName);
|
||||
static gpu::Texture* createCubeTextureFromImageWithoutIrradiance(const QImage& image, const std::string& srcImageName);
|
||||
static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName);
|
||||
|
||||
|
||||
|
|
|
@ -33,12 +33,7 @@ bool AssetResourceRequest::urlIsAssetHash() const {
|
|||
}
|
||||
|
||||
void AssetResourceRequest::doSend() {
|
||||
auto parts = _url.path().split(".", QString::SkipEmptyParts);
|
||||
auto hash = parts.length() > 0 ? parts[0] : "";
|
||||
auto extension = parts.length() > 1 ? parts[1] : "";
|
||||
|
||||
// We'll either have a hash or an ATP path to a file (that maps to a hash)
|
||||
|
||||
if (urlIsAssetHash()) {
|
||||
// We've detected that this is a hash - simply use AssetClient to request that asset
|
||||
auto parts = _url.path().split(".", QString::SkipEmptyParts);
|
||||
|
|
88
libraries/networking/src/AtpReply.cpp
Normal file
88
libraries/networking/src/AtpReply.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// AtpReply.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Zander Otavka on 8/4/16.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ResourceManager.h"
|
||||
#include "AtpReply.h"
|
||||
|
||||
AtpReply::AtpReply(const QUrl& url, QObject* parent) :
|
||||
_resourceRequest(ResourceManager::createResourceRequest(parent, url)) {
|
||||
setOperation(QNetworkAccessManager::GetOperation);
|
||||
|
||||
connect(_resourceRequest, &AssetResourceRequest::progress, this, &AtpReply::downloadProgress);
|
||||
connect(_resourceRequest, &AssetResourceRequest::finished, this, &AtpReply::handleRequestFinish);
|
||||
|
||||
_resourceRequest->send();
|
||||
}
|
||||
|
||||
AtpReply::~AtpReply() {
|
||||
if (_resourceRequest) {
|
||||
_resourceRequest->deleteLater();
|
||||
_resourceRequest = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 AtpReply::bytesAvailable() const {
|
||||
return _content.size() - _readOffset + QIODevice::bytesAvailable();
|
||||
}
|
||||
|
||||
qint64 AtpReply::readData(char* data, qint64 maxSize) {
|
||||
if (_readOffset < _content.size()) {
|
||||
qint64 readSize = qMin(maxSize, _content.size() - _readOffset);
|
||||
memcpy(data, _content.constData() + _readOffset, readSize);
|
||||
_readOffset += readSize;
|
||||
return readSize;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void AtpReply::handleRequestFinish() {
|
||||
Q_ASSERT(_resourceRequest->getState() == ResourceRequest::State::Finished);
|
||||
|
||||
switch (_resourceRequest->getResult()) {
|
||||
case ResourceRequest::Result::Success:
|
||||
setError(NoError, "Success");
|
||||
_content = _resourceRequest->getData();
|
||||
break;
|
||||
case ResourceRequest::Result::InvalidURL:
|
||||
setError(ContentNotFoundError, "Invalid URL");
|
||||
break;
|
||||
case ResourceRequest::Result::NotFound:
|
||||
setError(ContentNotFoundError, "Not found");
|
||||
break;
|
||||
case ResourceRequest::Result::ServerUnavailable:
|
||||
setError(ServiceUnavailableError, "Service unavailable");
|
||||
break;
|
||||
case ResourceRequest::Result::AccessDenied:
|
||||
setError(ContentAccessDenied, "Access denied");
|
||||
break;
|
||||
case ResourceRequest::Result::Timeout:
|
||||
setError(TimeoutError, "Timeout");
|
||||
break;
|
||||
default:
|
||||
setError(UnknownNetworkError, "Unknown error");
|
||||
break;
|
||||
}
|
||||
|
||||
open(ReadOnly | Unbuffered);
|
||||
setHeader(QNetworkRequest::ContentLengthHeader, QVariant(_content.size()));
|
||||
|
||||
if (error() != NoError) {
|
||||
emit error(error());
|
||||
}
|
||||
|
||||
setFinished(true);
|
||||
emit readyRead();
|
||||
emit finished();
|
||||
|
||||
_resourceRequest->deleteLater();
|
||||
_resourceRequest = nullptr;
|
||||
}
|
40
libraries/networking/src/AtpReply.h
Normal file
40
libraries/networking/src/AtpReply.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// AtpReply.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Zander Otavka on 8/4/16.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AtpReply_h
|
||||
#define hifi_AtpReply_h
|
||||
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QUrl>
|
||||
|
||||
#include "AssetResourceRequest.h"
|
||||
|
||||
class AtpReply : public QNetworkReply {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AtpReply(const QUrl& url, QObject* parent = Q_NULLPTR);
|
||||
~AtpReply();
|
||||
qint64 bytesAvailable() const override;
|
||||
void abort() override { }
|
||||
bool isSequential() const override { return true; }
|
||||
|
||||
protected:
|
||||
qint64 readData(char* data, qint64 maxSize) override;
|
||||
|
||||
private:
|
||||
void handleRequestFinish();
|
||||
|
||||
ResourceRequest* _resourceRequest { nullptr };
|
||||
QByteArray _content;
|
||||
qint64 _readOffset { 0 };
|
||||
};
|
||||
|
||||
#endif // hifi_AtpReply_h
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// NetworkAccessManager.cpp
|
||||
//
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Clement on 7/1/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <QThreadStorage>
|
||||
|
||||
#include "AtpReply.h"
|
||||
#include "NetworkAccessManager.h"
|
||||
|
||||
QThreadStorage<QNetworkAccessManager*> networkAccessManagers;
|
||||
|
@ -23,3 +24,13 @@ QNetworkAccessManager& NetworkAccessManager::getInstance() {
|
|||
|
||||
return *networkAccessManagers.localData();
|
||||
}
|
||||
|
||||
QNetworkReply* NetworkAccessManager::createRequest(Operation operation, const QNetworkRequest& request, QIODevice* device) {
|
||||
if (request.url().scheme() == "atp" && operation == GetOperation) {
|
||||
return new AtpReply(request.url());
|
||||
//auto url = request.url().toString();
|
||||
//return QNetworkAccessManager::createRequest(operation, request, device);
|
||||
} else {
|
||||
return QNetworkAccessManager::createRequest(operation, request, device);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// NetworkAccessManager.h
|
||||
//
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Clement on 7/1/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
|
@ -13,12 +13,17 @@
|
|||
#define hifi_NetworkAccessManager_h
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtQml/QQmlNetworkAccessManagerFactory>
|
||||
|
||||
/// Wrapper around QNetworkAccessManager to restrict at one instance by thread
|
||||
class NetworkAccessManager : public QObject {
|
||||
class NetworkAccessManager : public QNetworkAccessManager {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static QNetworkAccessManager& getInstance();
|
||||
protected:
|
||||
NetworkAccessManager(QObject* parent = Q_NULLPTR) : QNetworkAccessManager(parent) {}
|
||||
virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* device = Q_NULLPTR) override;
|
||||
};
|
||||
|
||||
#endif // hifi_NetworkAccessManager_h
|
|
@ -12,12 +12,13 @@
|
|||
#ifndef hifi_OAuthNetworkAccessManager_h
|
||||
#define hifi_OAuthNetworkAccessManager_h
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include "NetworkAccessManager.h"
|
||||
|
||||
class OAuthNetworkAccessManager : public QNetworkAccessManager {
|
||||
class OAuthNetworkAccessManager : public NetworkAccessManager {
|
||||
public:
|
||||
static OAuthNetworkAccessManager* getInstance();
|
||||
protected:
|
||||
OAuthNetworkAccessManager(QObject* parent = Q_NULLPTR) : NetworkAccessManager(parent) { }
|
||||
virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData = 0);
|
||||
};
|
||||
|
||||
|
|
|
@ -462,6 +462,7 @@ int ResourceCache::getPendingRequestCount() {
|
|||
}
|
||||
|
||||
bool ResourceCache::attemptRequest(QSharedPointer<Resource> resource) {
|
||||
Q_ASSERT(!resource.isNull());
|
||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||
|
||||
if (_requestsActive >= _requestLimit) {
|
||||
|
|
|
@ -63,7 +63,19 @@ QJsonValue Procedural::getProceduralData(const QString& proceduralJson) {
|
|||
return doc.object()[PROCEDURAL_USER_DATA_KEY];
|
||||
}
|
||||
|
||||
Procedural::Procedural() : _state { std::make_shared<gpu::State>() } {
|
||||
Procedural::Procedural() {
|
||||
_opaqueState->setCullMode(gpu::State::CULL_NONE);
|
||||
_opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
_opaqueState->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
_transparentState->setCullMode(gpu::State::CULL_NONE);
|
||||
_transparentState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
_transparentState->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
_proceduralDataDirty = false;
|
||||
}
|
||||
|
||||
|
@ -175,6 +187,10 @@ void Procedural::parse(const QJsonObject& proceduralData) {
|
|||
}
|
||||
|
||||
bool Procedural::ready() {
|
||||
if (!_hasStartedFade) {
|
||||
_fadeStartTime = usecTimestampNow();
|
||||
}
|
||||
|
||||
// Load any changes to the procedural
|
||||
// Check for changes atomically, in case they are currently being made
|
||||
if (_proceduralDataDirty) {
|
||||
|
@ -202,6 +218,10 @@ bool Procedural::ready() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!_hasStartedFade) {
|
||||
_hasStartedFade = true;
|
||||
_isFading = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -222,7 +242,7 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
|
|||
_shaderSource = _networkShader->_source;
|
||||
}
|
||||
|
||||
if (!_pipeline || _shaderDirty) {
|
||||
if (!_opaquePipeline || !_transparentPipeline || _shaderDirty) {
|
||||
if (!_vertexShader) {
|
||||
_vertexShader = gpu::Shader::createVertex(_vertexSource);
|
||||
}
|
||||
|
@ -260,7 +280,8 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
|
|||
slotBindings.insert(gpu::Shader::Binding(std::string("iChannel3"), 3));
|
||||
gpu::Shader::makeProgram(*_shader, slotBindings);
|
||||
|
||||
_pipeline = gpu::Pipeline::create(_shader, _state);
|
||||
_opaquePipeline = gpu::Pipeline::create(_shader, _opaqueState);
|
||||
_transparentPipeline = gpu::Pipeline::create(_shader, _transparentState);
|
||||
for (size_t i = 0; i < NUM_STANDARD_UNIFORMS; ++i) {
|
||||
const std::string& name = STANDARD_UNIFORM_NAMES[i];
|
||||
_standardUniformSlots[i] = _shader->getUniforms().findLocation(name);
|
||||
|
@ -269,7 +290,7 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
|
|||
_frameCount = 0;
|
||||
}
|
||||
|
||||
batch.setPipeline(_pipeline);
|
||||
batch.setPipeline(isFading() ? _transparentPipeline : _opaquePipeline);
|
||||
|
||||
if (_shaderDirty || _uniformsDirty) {
|
||||
setupUniforms();
|
||||
|
|
|
@ -42,13 +42,18 @@ public:
|
|||
const gpu::ShaderPointer& getShader() const { return _shader; }
|
||||
|
||||
glm::vec4 getColor(const glm::vec4& entityColor);
|
||||
quint64 getFadeStartTime() { return _fadeStartTime; }
|
||||
bool isFading() { return _doesFade && _isFading; }
|
||||
void setIsFading(bool isFading) { _isFading = isFading; }
|
||||
void setDoesFade(bool doesFade) { _doesFade = doesFade; }
|
||||
|
||||
uint8_t _version { 1 };
|
||||
|
||||
std::string _vertexSource;
|
||||
std::string _fragmentSource;
|
||||
|
||||
gpu::StatePointer _state;
|
||||
gpu::StatePointer _opaqueState { std::make_shared<gpu::State>() };
|
||||
gpu::StatePointer _transparentState { std::make_shared<gpu::State>() };
|
||||
|
||||
enum StandardUniforms {
|
||||
DATE,
|
||||
|
@ -86,7 +91,8 @@ protected:
|
|||
UniformLambdas _uniforms;
|
||||
int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS];
|
||||
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
|
||||
gpu::PipelinePointer _pipeline;
|
||||
gpu::PipelinePointer _opaquePipeline;
|
||||
gpu::PipelinePointer _transparentPipeline;
|
||||
gpu::ShaderPointer _vertexShader;
|
||||
gpu::ShaderPointer _fragmentShader;
|
||||
gpu::ShaderPointer _shader;
|
||||
|
@ -106,6 +112,11 @@ private:
|
|||
|
||||
void setupUniforms();
|
||||
void setupChannels(bool shouldCreate);
|
||||
|
||||
quint64 _fadeStartTime;
|
||||
bool _hasStartedFade { false };
|
||||
bool _isFading { false };
|
||||
bool _doesFade { true };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,7 +22,8 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
|
|||
_procedural._vertexSource = skybox_vert;
|
||||
_procedural._fragmentSource = skybox_frag;
|
||||
// Adjust the pipeline state for background using the stencil test
|
||||
_procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
_procedural.setDoesFade(false);
|
||||
_procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
}
|
||||
|
||||
void ProceduralSkybox::clear() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
set(TARGET_NAME render-utils)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu model render procedural)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu model render)
|
||||
# pull in the resources.qrc file
|
||||
qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc")
|
||||
setup_hifi_library(Widgets OpenGL Network Qml Quick Script)
|
||||
link_hifi_libraries(shared gpu procedural model model-networking render animation fbx)
|
||||
link_hifi_libraries(shared gpu model model-networking render animation fbx)
|
||||
|
||||
target_nsight()
|
||||
target_oglplus()
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <qmath.h>
|
||||
|
||||
#include "animdebugdraw_vert.h"
|
||||
#include "animdebugdraw_frag.h"
|
||||
#include <gpu/Batch.h>
|
||||
|
|
|
@ -73,6 +73,8 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3
|
|||
discard;
|
||||
}
|
||||
_fragColor0 = vec4(albedo.rgb, alpha);
|
||||
_fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0));
|
||||
|
||||
}
|
||||
|
||||
<@endif@>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "GeometryCache.h"
|
||||
|
||||
|
||||
#include <qmath.h>
|
||||
#include <cmath>
|
||||
|
||||
#include <QtCore/QThreadPool>
|
||||
|
@ -398,26 +398,36 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
|
|||
return INSTANCED_SOLID_STREAM_FORMAT;
|
||||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::_simplePipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;
|
||||
render::ShapePipelinePointer GeometryCache::_simpleWirePipeline;
|
||||
|
||||
GeometryCache::GeometryCache() :
|
||||
_nextID(0) {
|
||||
buildShapes();
|
||||
GeometryCache::_simplePipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch) {
|
||||
// Set the defaults needed for a simple program
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
);
|
||||
GeometryCache::_simpleOpaquePipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, false), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch) {
|
||||
// Set the defaults needed for a simple program
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
);
|
||||
GeometryCache::_simpleTransparentPipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, true, true, false), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch) {
|
||||
// Set the defaults needed for a simple program
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
);
|
||||
GeometryCache::_simpleWirePipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, true), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch) {}
|
||||
);
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch) {});
|
||||
}
|
||||
|
||||
GeometryCache::~GeometryCache() {
|
||||
|
@ -1704,6 +1714,7 @@ class SimpleProgramKey {
|
|||
public:
|
||||
enum FlagBit {
|
||||
IS_TEXTURED_FLAG = 0,
|
||||
IS_TRANSPARENT_FLAG,
|
||||
IS_CULLED_FLAG,
|
||||
IS_UNLIT_FLAG,
|
||||
HAS_DEPTH_BIAS_FLAG,
|
||||
|
@ -1713,6 +1724,7 @@ public:
|
|||
|
||||
enum Flag {
|
||||
IS_TEXTURED = (1 << IS_TEXTURED_FLAG),
|
||||
IS_TRANSPARENT = (1 << IS_TRANSPARENT_FLAG),
|
||||
IS_CULLED = (1 << IS_CULLED_FLAG),
|
||||
IS_UNLIT = (1 << IS_UNLIT_FLAG),
|
||||
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),
|
||||
|
@ -1722,6 +1734,7 @@ public:
|
|||
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
|
||||
|
||||
bool isTextured() const { return isFlag(IS_TEXTURED); }
|
||||
bool isTransparent() const { return isFlag(IS_TRANSPARENT); }
|
||||
bool isCulled() const { return isFlag(IS_CULLED); }
|
||||
bool isUnlit() const { return isFlag(IS_UNLIT); }
|
||||
bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }
|
||||
|
@ -1732,9 +1745,9 @@ public:
|
|||
int getRaw() const { return *reinterpret_cast<const int*>(this); }
|
||||
|
||||
|
||||
SimpleProgramKey(bool textured = false, bool culled = true,
|
||||
SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false) {
|
||||
_flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) |
|
||||
_flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) |
|
||||
(unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0);
|
||||
}
|
||||
|
||||
|
@ -1771,7 +1784,7 @@ gpu::PipelinePointer GeometryCache::getSimpleSRGBTexturedUnlitNoTexAlphaPipeline
|
|||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(false,
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
|
@ -1781,8 +1794,8 @@ gpu::PipelinePointer GeometryCache::getSimpleSRGBTexturedUnlitNoTexAlphaPipeline
|
|||
return _simpleSRGBTexturedUnlitNoTexAlphaPipeline;
|
||||
}
|
||||
|
||||
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool unlit, bool depthBiased) {
|
||||
batch.setPipeline(getSimplePipeline(textured, culled, unlit, depthBiased));
|
||||
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) {
|
||||
batch.setPipeline(getSimplePipeline(textured, transparent, culled, unlit, depthBiased));
|
||||
|
||||
// If not textured, set a default albedo map
|
||||
if (!textured) {
|
||||
|
@ -1794,8 +1807,8 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool cul
|
|||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
|
||||
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool unlit, bool depthBiased) {
|
||||
SimpleProgramKey config { textured, culled, unlit, depthBiased };
|
||||
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) {
|
||||
SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased };
|
||||
|
||||
// Compile the shaders
|
||||
static std::once_flag once;
|
||||
|
@ -1831,7 +1844,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled
|
|||
state->setDepthBias(1.0f);
|
||||
state->setDepthBiasSlopeScale(1.0f);
|
||||
}
|
||||
state->setBlendFunction(false,
|
||||
state->setBlendFunction(config.isTransparent(),
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
|
|
|
@ -152,16 +152,17 @@ public:
|
|||
|
||||
|
||||
// Bind the pipeline and get the state to render static geometry
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
// Get the pipeline to render static geometry
|
||||
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true,
|
||||
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
||||
bool unlit = false, bool depthBias = false);
|
||||
|
||||
void bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(gpu::Batch& batch);
|
||||
gpu::PipelinePointer getSimpleSRGBTexturedUnlitNoTexAlphaPipeline();
|
||||
|
||||
render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; }
|
||||
render::ShapePipelinePointer getOpaqueShapePipeline() { return GeometryCache::_simpleOpaquePipeline; }
|
||||
render::ShapePipelinePointer getTransparentShapePipeline() { return GeometryCache::_simpleTransparentPipeline; }
|
||||
render::ShapePipelinePointer getWireShapePipeline() { return GeometryCache::_simpleWirePipeline; }
|
||||
|
||||
// Static (instanced) geometry
|
||||
|
@ -169,42 +170,42 @@ public:
|
|||
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
|
||||
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
|
||||
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
|
||||
renderSolidShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
|
||||
void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
|
||||
renderWireShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
|
||||
renderSolidSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline);
|
||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
|
||||
renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline);
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) {
|
||||
renderSolidCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline);
|
||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
|
||||
renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||
|
@ -416,7 +417,8 @@ private:
|
|||
|
||||
gpu::ShaderPointer _simpleShader;
|
||||
gpu::ShaderPointer _unlitShader;
|
||||
static render::ShapePipelinePointer _simplePipeline;
|
||||
static render::ShapePipelinePointer _simpleOpaquePipeline;
|
||||
static render::ShapePipelinePointer _simpleTransparentPipeline;
|
||||
static render::ShapePipelinePointer _simpleWirePipeline;
|
||||
gpu::PipelinePointer _glowLinePipeline;
|
||||
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||
|
|
|
@ -352,7 +352,6 @@ void ModelMeshPartPayload::initCache() {
|
|||
|
||||
}
|
||||
|
||||
|
||||
void ModelMeshPartPayload::notifyLocationChanged() {
|
||||
|
||||
}
|
||||
|
@ -392,6 +391,10 @@ ItemKey ModelMeshPartPayload::getKey() const {
|
|||
}
|
||||
}
|
||||
|
||||
if (!_hasFinishedFade) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -443,7 +446,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
|
|||
}
|
||||
|
||||
ShapeKey::Builder builder;
|
||||
if (isTranslucent) {
|
||||
if (isTranslucent || !_hasFinishedFade) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (hasTangents) {
|
||||
|
@ -484,9 +487,9 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
|
|||
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
|
||||
}
|
||||
|
||||
// TODO: Get rid of that extra call
|
||||
if (!_hasColorAttrib) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
if (!_hasColorAttrib || fadeRatio < 1.0f) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,14 +516,30 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
|
|||
batch.setModelTransform(transform);
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::startFade() {
|
||||
_fadeStartTime = usecTimestampNow();
|
||||
_hasStartedFade = true;
|
||||
_prevHasStartedFade = false;
|
||||
_hasFinishedFade = false;
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||
PerformanceTimer perfTimer("ModelMeshPartPayload::render");
|
||||
|
||||
if (!_model->_readyWhenAdded || !_model->_isVisible) {
|
||||
if (!_model->_readyWhenAdded || !_model->_isVisible || !_hasStartedFade) {
|
||||
return; // bail asap
|
||||
}
|
||||
|
||||
// When an individual mesh parts like this finishes its fade, we will mark the Model as
|
||||
// having render items that need updating
|
||||
bool nextIsFading = _isFading ? isStillFading() : false;
|
||||
if (_isFading != nextIsFading || _prevHasStartedFade != _hasStartedFade) {
|
||||
_isFading = nextIsFading || _prevHasStartedFade != _hasStartedFade;
|
||||
_hasFinishedFade = _prevHasStartedFade == _hasStartedFade && !_isFading;
|
||||
_prevHasStartedFade = _hasStartedFade;
|
||||
_model->setRenderItemsNeedUpdate();
|
||||
}
|
||||
|
||||
gpu::Batch& batch = *(args->_batch);
|
||||
|
||||
if (!getShapeKey().isValid()) {
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_MeshPartPayload_h
|
||||
#define hifi_MeshPartPayload_h
|
||||
|
||||
#include <Interpolate.h>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
#include <render/Scene.h>
|
||||
|
@ -81,6 +83,11 @@ public:
|
|||
void notifyLocationChanged() override;
|
||||
void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector<glm::mat4>& clusterMatrices);
|
||||
|
||||
// Entity fade in
|
||||
void startFade();
|
||||
bool hasStartedFade() { return _hasStartedFade; }
|
||||
bool isStillFading() const { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; }
|
||||
|
||||
// Render Item interface
|
||||
render::ItemKey getKey() const override;
|
||||
render::ShapeKey getShapeKey() const override; // shape interface
|
||||
|
@ -99,6 +106,13 @@ public:
|
|||
|
||||
bool _isSkinned{ false };
|
||||
bool _isBlendShaped{ false };
|
||||
|
||||
private:
|
||||
quint64 _fadeStartTime { 0 };
|
||||
bool _hasStartedFade { false };
|
||||
mutable bool _prevHasStartedFade{ false };
|
||||
mutable bool _hasFinishedFade { false };
|
||||
mutable bool _isFading { false };
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -174,6 +174,7 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
void Model::updateRenderItems() {
|
||||
|
||||
_needsUpdateClusterMatrices = true;
|
||||
_renderItemsNeedUpdate = false;
|
||||
|
||||
// queue up this work for later processing, at the end of update and just before rendering.
|
||||
// the application will ensure only the last lambda is actually invoked.
|
||||
|
@ -211,6 +212,9 @@ void Model::updateRenderItems() {
|
|||
render::PendingChanges pendingChanges;
|
||||
foreach (auto itemID, self->_modelMeshRenderItems.keys()) {
|
||||
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) {
|
||||
if (!data.hasStartedFade() && data._model && data._model->isLoaded() && data._model->getGeometry()->areTexturesLoaded()) {
|
||||
data.startFade();
|
||||
}
|
||||
// Ensure the model geometry was not reset between frames
|
||||
if (data._model && data._model->isLoaded() && deleteGeometryCounter == data._model->_deleteGeometryCounter) {
|
||||
// lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box.
|
||||
|
|
|
@ -103,6 +103,8 @@ public:
|
|||
bool isVisible() const { return _isVisible; }
|
||||
|
||||
void updateRenderItems();
|
||||
void setRenderItemsNeedUpdate() { _renderItemsNeedUpdate = true; }
|
||||
bool getRenderItemsNeedUpdate() { return _renderItemsNeedUpdate; }
|
||||
AABox getRenderableMeshBound() const;
|
||||
|
||||
bool maybeStartBlender();
|
||||
|
@ -408,6 +410,8 @@ protected:
|
|||
bool _visualGeometryRequestFailed { false };
|
||||
bool _collisionGeometryRequestFailed { false };
|
||||
|
||||
bool _renderItemsNeedUpdate { false };
|
||||
|
||||
private:
|
||||
float _loadingPriority { 0.0f };
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ void main() {
|
|||
|
||||
packDeferredFragmentTranslucent(
|
||||
normalize(_normal),
|
||||
a,
|
||||
a * Color.a,
|
||||
Color.rgb,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
|
|
|
@ -49,11 +49,43 @@ void main(void) {
|
|||
|
||||
#endif
|
||||
|
||||
if (emissiveAmount > 0.0) {
|
||||
packDeferredFragmentLightmap(
|
||||
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular);
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (_color.a < ALPHA_THRESHOLD) {
|
||||
if (emissiveAmount > 0.0) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normal,
|
||||
_color.a,
|
||||
specular,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragmentTranslucent(
|
||||
normal,
|
||||
_color.a,
|
||||
diffuse,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
}
|
||||
} else {
|
||||
packDeferredFragment(
|
||||
normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
|
||||
if (emissiveAmount > 0.0) {
|
||||
packDeferredFragmentLightmap(
|
||||
normal,
|
||||
1.0,
|
||||
diffuse,
|
||||
max(0, 1.0 - shininess / 128.0),
|
||||
DEFAULT_METALLIC,
|
||||
specular,
|
||||
specular);
|
||||
} else {
|
||||
packDeferredFragment(
|
||||
normal,
|
||||
1.0,
|
||||
diffuse,
|
||||
max(0, 1.0 - shininess / 128.0),
|
||||
length(specular),
|
||||
DEFAULT_EMISSIVE,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,18 @@ void main(void) {
|
|||
vec4 texel = texture(originalTexture, _texCoord0.st);
|
||||
texel = colorToLinearRGBA(texel);
|
||||
|
||||
packDeferredFragmentUnlit(
|
||||
normalize(_normal),
|
||||
1.0,
|
||||
_color.rgb * texel.rgb);
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (_color.a < ALPHA_THRESHOLD) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normalize(_normal),
|
||||
_color.a,
|
||||
_color.rgb * texel.rgb,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragmentUnlit(
|
||||
normalize(_normal),
|
||||
1.0,
|
||||
_color.rgb * texel.rgb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,24 @@ void main(void) {
|
|||
if (_color.a <= 0.0) {
|
||||
texel = colorToLinearRGBA(texel);
|
||||
}
|
||||
packDeferredFragment(
|
||||
normalize(_normal.xyz),
|
||||
texel.a,
|
||||
_color.rgb * texel.rgb,
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (_color.a * texel.a < ALPHA_THRESHOLD) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normalize(_normal),
|
||||
_color.a * texel.a,
|
||||
_color.rgb * texel.rgb,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragment(
|
||||
normalize(_normal),
|
||||
1.0,
|
||||
_color.rgb * texel.rgb,
|
||||
DEFAULT_ROUGHNESS,
|
||||
DEFAULT_METALLIC,
|
||||
DEFAULT_EMISSIVE,
|
||||
DEFAULT_OCCLUSION,
|
||||
DEFAULT_SCATTERING);
|
||||
}
|
||||
}
|
|
@ -29,8 +29,18 @@ void main(void) {
|
|||
texel = colorToLinearRGBA(texel);
|
||||
}
|
||||
|
||||
packDeferredFragmentUnlit(
|
||||
normalize(_normal),
|
||||
texel.a,
|
||||
_color.rgb * texel.rgb);
|
||||
const float ALPHA_THRESHOLD = 0.999;
|
||||
if (_color.a * texel.a < ALPHA_THRESHOLD) {
|
||||
packDeferredFragmentTranslucent(
|
||||
normalize(_normal),
|
||||
_color.a * texel.a,
|
||||
_color.rgb * texel.rgb,
|
||||
DEFAULT_FRESNEL,
|
||||
DEFAULT_ROUGHNESS);
|
||||
} else {
|
||||
packDeferredFragmentUnlit(
|
||||
normalize(_normal),
|
||||
1.0,
|
||||
_color.rgb * texel.rgb);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Bradley Austin Davis on 6/10/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
in vec4 varColor;
|
||||
in float varSize;
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
const float EDGE_SIZE = 0.25;
|
||||
const float ALPHA_BOUNDARY = 1.0 - EDGE_SIZE;
|
||||
|
||||
void main(void) {
|
||||
vec2 coord = gl_PointCoord * vec2(2.0) - vec2(1.0);
|
||||
coord = coord * coord;
|
||||
|
||||
float l = coord.x + coord.y;
|
||||
if (l > 1.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
outFragColor = varColor;
|
||||
if (l >= ALPHA_BOUNDARY) {
|
||||
outFragColor.a = smoothstep(1.0, ALPHA_BOUNDARY, l);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// standardTransformPNTC.slv
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Sam Gateau on 6/10/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
// TODO we need to get the viewport resolution and FOV passed to us so we can modify the point size
|
||||
// and effectively producing a points that take up a constant angular size regardless of the display resolution
|
||||
// or projection matrix
|
||||
|
||||
out vec4 varColor;
|
||||
out float varSize;
|
||||
|
||||
void main(void) {
|
||||
varColor = colorToLinearRGBA(inColor);
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
varSize = inColor.a;
|
||||
gl_PointSize = varSize;
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// stars.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2015/06/19
|
||||
|
||||
in vec2 varTexcoord;
|
||||
in vec3 varNomral;
|
||||
in vec3 varPosition;
|
||||
|
||||
uniform float iGlobalTime;
|
||||
|
||||
const float PI = 3.14159;
|
||||
const float TAU = 3.14159 * 2.0;
|
||||
const int latitudeCount = 5;
|
||||
const float latitudeDist = PI / 2.0 / float(latitudeCount);
|
||||
const int meridianCount = 4;
|
||||
const float merdianDist = PI / float(meridianCount);
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
float clampLine(float val, float target) {
|
||||
return clamp((1.0 - abs((val - target)) - 0.998) * 500.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float latitude(vec2 pos, float angle) {
|
||||
float result = clampLine(pos.y, angle);
|
||||
if (angle != 0.0) {
|
||||
result += clampLine(pos.y, -angle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float meridian(vec2 pos, float angle) {
|
||||
return clampLine(pos.x, angle) + clampLine(pos.x + PI, angle);
|
||||
}
|
||||
|
||||
vec2 toPolar(in vec3 dir) {
|
||||
vec2 polar = vec2(atan(dir.z, dir.x), asin(dir.y));
|
||||
return polar;
|
||||
}
|
||||
|
||||
void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir )
|
||||
{
|
||||
vec2 polar = toPolar(fragRayDir);
|
||||
//polar.x += mod(iGlobalTime / 12.0, PI / 4.0) - PI / 4.0;
|
||||
float c = 0.0;
|
||||
for (int i = 0; i < latitudeCount - 1; ++i) {
|
||||
c += latitude(polar, float(i) * latitudeDist);
|
||||
}
|
||||
for (int i = 0; i < meridianCount; ++i) {
|
||||
c += meridian(polar, float(i) * merdianDist);
|
||||
}
|
||||
const vec3 col_lines = vec3(102.0 / 255.0, 136.0 / 255.0, 221.0 / 255.0);
|
||||
fragColor = vec4(c * col_lines, 0.2);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
mainVR(outFragColor, gl_FragCoord.xy, vec3(0.0), normalize(varPosition));
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
set(TARGET_NAME render)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu model procedural)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu model)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared gpu model)
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ void ScriptCache::scriptContentAvailable() {
|
|||
Lock lock(_containerLock);
|
||||
allCallbacks = _contentCallbacks.values(url);
|
||||
_contentCallbacks.remove(url);
|
||||
Q_ASSERT(req->getState() == ResourceRequest::Finished);
|
||||
success = req->getResult() == ResourceRequest::Success;
|
||||
|
||||
if (success) {
|
||||
|
|
59
libraries/shared/src/ColorUtils.cpp
Normal file
59
libraries/shared/src/ColorUtils.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// ColorUtils.cpp
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Ryan Huffman on 8/8/16.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ColorUtils.h"
|
||||
|
||||
// Generated from python script in repository at `tools/srgb_gen.py`
|
||||
const float srgbToLinearLookupTable[256] = {
|
||||
0.0f, 0.000303526983549f, 0.000607053967098f, 0.000910580950647f, 0.0012141079342f, 0.00151763491774f, 0.00182116190129f,
|
||||
0.00212468888484f, 0.00242821586839f, 0.00273174285194f, 0.00303526983549f, 0.0033465357639f, 0.00367650732405f,
|
||||
0.0040247170185f, 0.00439144203741f, 0.00477695348069f, 0.00518151670234f, 0.0056053916242f, 0.00604883302286f,
|
||||
0.00651209079259f, 0.00699541018727f, 0.00749903204323f, 0.00802319298538f, 0.00856812561807f, 0.00913405870222f,
|
||||
0.00972121732024f, 0.0103298230296f, 0.0109600940065f, 0.0116122451797f, 0.0122864883569f, 0.0129830323422f,
|
||||
0.0137020830473f, 0.0144438435961f, 0.0152085144229f, 0.0159962933655f, 0.0168073757529f, 0.0176419544884f,
|
||||
0.0185002201284f, 0.0193823609569f, 0.0202885630567f, 0.021219010376f, 0.0221738847934f, 0.0231533661781f,
|
||||
0.0241576324485f, 0.0251868596274f, 0.0262412218948f, 0.0273208916391f, 0.0284260395044f, 0.0295568344378f,
|
||||
0.030713443733f, 0.031896033073f, 0.0331047665709f, 0.0343398068087f, 0.035601314875f, 0.0368894504011f,
|
||||
0.0382043715953f, 0.0395462352767f, 0.0409151969069f, 0.0423114106208f, 0.043735029257f, 0.0451862043857f,
|
||||
0.0466650863369f, 0.0481718242269f, 0.0497065659841f, 0.051269458374f, 0.0528606470232f, 0.0544802764424f,
|
||||
0.0561284900496f, 0.0578054301911f, 0.059511238163f, 0.0612460542316f, 0.0630100176532f, 0.0648032666929f,
|
||||
0.0666259386438f, 0.0684781698444f, 0.0703600956966f, 0.0722718506823f, 0.0742135683801f, 0.0761853814813f,
|
||||
0.0781874218052f, 0.0802198203145f, 0.0822827071298f, 0.0843762115441f, 0.0865004620365f, 0.0886555862858f,
|
||||
0.0908417111834f, 0.0930589628467f, 0.095307466631f, 0.0975873471419f, 0.0998987282471f, 0.102241733088f,
|
||||
0.104616484091f, 0.107023102978f, 0.109461710778f, 0.111932427837f, 0.114435373827f, 0.116970667759f,
|
||||
0.119538427988f, 0.12213877223f, 0.124771817561f, 0.127437680436f, 0.13013647669f, 0.132868321554f,
|
||||
0.135633329655f, 0.138431615032f, 0.14126329114f, 0.144128470858f, 0.147027266498f, 0.149959789811f,
|
||||
0.152926151996f, 0.155926463708f, 0.158960835061f, 0.162029375639f, 0.165132194502f, 0.16826940019f,
|
||||
0.171441100733f, 0.174647403656f, 0.177888415984f, 0.18116424425f, 0.1844749945f, 0.187820772301f,
|
||||
0.191201682741f, 0.194617830442f, 0.19806931956f, 0.201556253794f, 0.20507873639f, 0.208636870145f,
|
||||
0.212230757414f, 0.215860500114f, 0.219526199729f, 0.223227957317f, 0.22696587351f, 0.230740048524f,
|
||||
0.234550582161f, 0.238397573812f, 0.242281122466f, 0.246201326708f, 0.25015828473f, 0.254152094331f,
|
||||
0.258182852922f, 0.26225065753f, 0.266355604803f, 0.270497791013f, 0.27467731206f, 0.278894263477f,
|
||||
0.28314874043f, 0.287440837727f, 0.291770649818f, 0.296138270798f, 0.300543794416f, 0.30498731407f,
|
||||
0.309468922818f, 0.313988713376f, 0.318546778125f, 0.323143209113f, 0.327778098057f, 0.332451536346f,
|
||||
0.337163615048f, 0.341914424909f, 0.346704056355f, 0.3515325995f, 0.356400144146f, 0.361306779784f,
|
||||
0.366252595599f, 0.371237680474f, 0.376262122991f, 0.381326011433f, 0.386429433787f, 0.39157247775f,
|
||||
0.396755230726f, 0.401977779832f, 0.407240211902f, 0.412542613484f, 0.417885070848f, 0.423267669986f,
|
||||
0.428690496614f, 0.434153636175f, 0.439657173841f, 0.445201194516f, 0.450785782838f, 0.45641102318f,
|
||||
0.462076999654f, 0.467783796112f, 0.473531496148f, 0.479320183101f, 0.485149940056f, 0.491020849848f,
|
||||
0.496932995061f, 0.502886458033f, 0.508881320855f, 0.514917665377f, 0.520995573204f, 0.527115125706f,
|
||||
0.533276404011f, 0.539479489012f, 0.54572446137f, 0.552011401512f, 0.558340389634f, 0.564711505705f,
|
||||
0.571124829465f, 0.57758044043f, 0.584078417891f, 0.590618840919f, 0.597201788364f, 0.603827338855f,
|
||||
0.610495570808f, 0.61720656242f, 0.623960391675f, 0.630757136346f, 0.637596873994f, 0.644479681971f,
|
||||
0.65140563742f, 0.658374817279f, 0.665387298282f, 0.672443156958f, 0.679542469633f, 0.686685312435f,
|
||||
0.693871761292f, 0.701101891933f, 0.708375779892f, 0.715693500506f, 0.723055128922f, 0.73046074009f,
|
||||
0.737910408773f, 0.74540420954f, 0.752942216776f, 0.760524504675f, 0.768151147248f, 0.775822218317f,
|
||||
0.783537791526f, 0.791297940333f, 0.799102738014f, 0.806952257669f, 0.814846572216f, 0.822785754396f,
|
||||
0.830769876775f, 0.838799011741f, 0.84687323151f, 0.854992608124f, 0.863157213454f, 0.871367119199f,
|
||||
0.879622396888f, 0.887923117882f, 0.896269353374f, 0.904661174391f, 0.913098651793f, 0.921581856277f,
|
||||
0.930110858375f, 0.938685728458f, 0.947306536733f, 0.955973353249f, 0.964686247894f, 0.973445290398f,
|
||||
0.982250550333f, 0.991102097114f, 1.0f
|
||||
};
|
|
@ -13,10 +13,13 @@
|
|||
#define hifi_ColorUtils_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "SharedUtil.h"
|
||||
|
||||
#include "DependencyManager.h"
|
||||
|
||||
extern const float srgbToLinearLookupTable[256];
|
||||
|
||||
class ColorUtils {
|
||||
public:
|
||||
inline static glm::vec3 toVec3(const xColor& color);
|
||||
|
@ -33,6 +36,7 @@ public:
|
|||
inline static glm::vec4 tosRGBVec4(const glm::vec4& srgb);
|
||||
|
||||
inline static float sRGBToLinearFloat(const float& srgb);
|
||||
inline static float sRGB8ToLinearFloat(const uint8_t srgb);
|
||||
inline static float tosRGBFloat(const float& linear);
|
||||
};
|
||||
|
||||
|
@ -82,6 +86,9 @@ inline float ColorUtils::sRGBToLinearFloat(const float &srgb) {
|
|||
|
||||
return linearValue;
|
||||
}
|
||||
inline float ColorUtils::sRGB8ToLinearFloat(const uint8_t srgb) {
|
||||
return srgbToLinearLookupTable[srgb];
|
||||
}
|
||||
|
||||
// This is based upon the conversions found in section 17.3.9 of the OpenGL 4.4 specification.
|
||||
// glm::pow(color, 1.0f/2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers.
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "NumericalConstants.h"
|
||||
|
||||
float Interpolate::bezierInterpolate(float y1, float y2, float y3, float u) {
|
||||
// https://en.wikipedia.org/wiki/Bezier_curve
|
||||
assert(0.0f <= u && u <= 1.0f);
|
||||
|
@ -58,3 +60,13 @@ float Interpolate::interpolate3Points(float y1, float y2, float y3, float u) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Interpolate::calculateFadeRatio(quint64 start) {
|
||||
const float FADE_TIME = 1.0f;
|
||||
float t = 2.0f * std::min(((float)(usecTimestampNow() - start)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f);
|
||||
float fadeRatio = (t < 1.0f) ? 0.5f * powf(2.0f, 10.0f * (t - 1.0f)) : 0.5f * (-powf(2.0f, -10.0f * (t - 1.0f)) + 2.0f);
|
||||
|
||||
// The easing function isn't exactly 1 at t = 2, so we need to scale the whole function up slightly
|
||||
const float EASING_SCALE = 1.001f;
|
||||
return std::min(EASING_SCALE * fadeRatio, 1.0f);
|
||||
}
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_Interpolate_h
|
||||
#define hifi_Interpolate_h
|
||||
|
||||
#include "SharedUtil.h"
|
||||
|
||||
class Interpolate {
|
||||
|
||||
public:
|
||||
|
@ -22,6 +24,8 @@ public:
|
|||
// Interpolate at position u [0.0 - 1.0] between y values equally spaced along the x-axis such that the interpolated values
|
||||
// pass through all three y values. Return value lies wholly within the range of y values passed in.
|
||||
static float interpolate3Points(float y1, float y2, float y3, float u);
|
||||
|
||||
static float calculateFadeRatio(quint64 start);
|
||||
};
|
||||
|
||||
#endif // hifi_Interpolate_h
|
||||
|
|
|
@ -59,9 +59,10 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) {
|
|||
properties = context->argument(0).toVariant().toMap();
|
||||
}
|
||||
|
||||
QString url = properties[SOURCE_PROPERTY].toString();
|
||||
if (!url.startsWith("http") && !url.startsWith("file://") && !url.startsWith("about:")) {
|
||||
properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url).toString();
|
||||
QUrl url { properties[SOURCE_PROPERTY].toString() };
|
||||
if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" &&
|
||||
url.scheme() != "atp") {
|
||||
properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString();
|
||||
}
|
||||
|
||||
return properties;
|
||||
|
|
|
@ -232,18 +232,10 @@ function Teleporter() {
|
|||
};
|
||||
|
||||
this.rightRay = function() {
|
||||
|
||||
var rightPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getPoseValue(Controller.Standard.RightHand).translation), MyAvatar.position);
|
||||
|
||||
var rightControllerRotation = Controller.getPoseValue(Controller.Standard.RightHand).rotation;
|
||||
|
||||
var rightRotation = Quat.multiply(MyAvatar.orientation, rightControllerRotation);
|
||||
|
||||
var rightFinal = Quat.multiply(rightRotation, Quat.angleAxis(90, {
|
||||
x: 1,
|
||||
y: 0,
|
||||
z: 0
|
||||
}));
|
||||
var pose = Controller.getPoseValue(Controller.Standard.RightHand);
|
||||
var rightPosition = pose.valid ? Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position) : MyAvatar.getHeadPosition();
|
||||
var rightRotation = pose.valid ? Quat.multiply(MyAvatar.orientation, pose.rotation) :
|
||||
Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, {x: 1, y: 0, z: 0}));
|
||||
|
||||
var rightPickRay = {
|
||||
origin: rightPosition,
|
||||
|
@ -288,15 +280,10 @@ function Teleporter() {
|
|||
|
||||
|
||||
this.leftRay = function() {
|
||||
var leftPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getPoseValue(Controller.Standard.LeftHand).translation), MyAvatar.position);
|
||||
|
||||
var leftRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(Controller.Standard.LeftHand).rotation)
|
||||
|
||||
var leftFinal = Quat.multiply(leftRotation, Quat.angleAxis(90, {
|
||||
x: 1,
|
||||
y: 0,
|
||||
z: 0
|
||||
}));
|
||||
var pose = Controller.getPoseValue(Controller.Standard.LeftHand);
|
||||
var leftPosition = pose.valid ? Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position) : MyAvatar.getHeadPosition();
|
||||
var leftRotation = pose.valid ? Quat.multiply(MyAvatar.orientation, pose.rotation) :
|
||||
Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, {x: 1, y: 0, z: 0}));
|
||||
|
||||
var leftPickRay = {
|
||||
origin: leftPosition,
|
||||
|
|
|
@ -10,51 +10,51 @@
|
|||
|
||||
@font-face {
|
||||
font-family: Raleway-Regular;
|
||||
src: url(../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */
|
||||
url(../../../fonts/Raleway-Regular.ttf), /* OSX production */
|
||||
url(../../../interface/resources/fonts/Raleway-Regular.ttf); /* Development, running script in /HiFi/examples */
|
||||
src: url(../../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */
|
||||
url(../../../../fonts/Raleway-Regular.ttf), /* OSX production */
|
||||
url(../../../../interface/resources/fonts/Raleway-Regular.ttf); /* Development, running script in /HiFi/examples */
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Raleway-Light;
|
||||
src: url(../../../resources/fonts/Raleway-Light.ttf),
|
||||
url(../../../fonts/Raleway-Light.ttf),
|
||||
url(../../../interface/resources/fonts/Raleway-Light.ttf);
|
||||
src: url(../../../../resources/fonts/Raleway-Light.ttf),
|
||||
url(../../../../fonts/Raleway-Light.ttf),
|
||||
url(../../../../interface/resources/fonts/Raleway-Light.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Raleway-Bold;
|
||||
src: url(../../../resources/fonts/Raleway-Bold.ttf),
|
||||
url(../../../fonts/Raleway-Bold.ttf),
|
||||
url(../../../interface/resources/fonts/Raleway-Bold.ttf);
|
||||
src: url(../../../../resources/fonts/Raleway-Bold.ttf),
|
||||
url(../../../../fonts/Raleway-Bold.ttf),
|
||||
url(../../../../interface/resources/fonts/Raleway-Bold.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Raleway-SemiBold;
|
||||
src: url(../../../resources/fonts/Raleway-SemiBold.ttf),
|
||||
url(../../../fonts/Raleway-SemiBold.ttf),
|
||||
url(../../../interface/resources/fonts/Raleway-SemiBold.ttf);
|
||||
src: url(../../../../resources/fonts/Raleway-SemiBold.ttf),
|
||||
url(../../../../fonts/Raleway-SemiBold.ttf),
|
||||
url(../../../../interface/resources/fonts/Raleway-SemiBold.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: FiraSans-SemiBold;
|
||||
src: url(../../../resources/fonts/FiraSans-SemiBold.ttf),
|
||||
url(../../../fonts/FiraSans-SemiBold.ttf),
|
||||
url(../../../interface/resources/fonts/FiraSans-SemiBold.ttf);
|
||||
src: url(../../../../resources/fonts/FiraSans-SemiBold.ttf),
|
||||
url(../../../../fonts/FiraSans-SemiBold.ttf),
|
||||
url(../../../../interface/resources/fonts/FiraSans-SemiBold.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: AnonymousPro-Regular;
|
||||
src: url(../../../resources/fonts/AnonymousPro-Regular.ttf),
|
||||
url(../../../fonts/AnonymousPro-Regular.ttf),
|
||||
url(../../../interface/resources/fonts/AnonymousPro-Regular.ttf);
|
||||
src: url(../../../../resources/fonts/AnonymousPro-Regular.ttf),
|
||||
url(../../../../fonts/AnonymousPro-Regular.ttf),
|
||||
url(../../../../interface/resources/fonts/AnonymousPro-Regular.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: HiFi-Glyphs;
|
||||
src: url(../../../resources/fonts/hifi-glyphs.ttf),
|
||||
url(../../../fonts/hifi-glyphs.ttf),
|
||||
url(../../../interface/resources/fonts/hifi-glyphs.ttf);
|
||||
src: url(../../../../resources/fonts/hifi-glyphs.ttf),
|
||||
url(../../../../fonts/hifi-glyphs.ttf),
|
||||
url(../../../../interface/resources/fonts/hifi-glyphs.ttf);
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -1077,10 +1077,6 @@ input#dimension-rescale-button {
|
|||
input#reset-to-natural-dimensions {
|
||||
margin-right: 0;
|
||||
}
|
||||
input#preview-camera-button {
|
||||
margin-left: 1px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#animation-fps {
|
||||
margin-top: 48px;
|
|
@ -10,314 +10,12 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="edit-style.css">
|
||||
<script src="list.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
|
||||
<script src="js/list.min.js"></script>
|
||||
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||
<script type="text/javascript" src="eventBridgeLoader.js"></script>
|
||||
<script type="text/javascript" src="spinButtons.js"></script>
|
||||
<script>
|
||||
var entities = {};
|
||||
var selectedEntities = [];
|
||||
var currentSortColumn = 'type';
|
||||
var currentSortOrder = 'des';
|
||||
var entityList = null;
|
||||
var refreshEntityListTimer = null;
|
||||
const ASCENDING_STRING = '▾';
|
||||
const DESCENDING_STRING = '▴';
|
||||
const LOCKED_GLYPH = "";
|
||||
const VISIBLE_GLYPH = "";
|
||||
const DELETE = 46; // Key code for the delete key.
|
||||
const MAX_ITEMS = Number.MAX_VALUE; // Used to set the max length of the list of discovered entities.
|
||||
|
||||
debugPrint = function (message) {
|
||||
console.log(message);
|
||||
};
|
||||
|
||||
function loaded() {
|
||||
openEventBridge(function() {
|
||||
entityList = new List('entity-list', { valueNames: ['name', 'type', 'url', 'locked', 'visible'], page: MAX_ITEMS});
|
||||
entityList.clear();
|
||||
elEntityTable = document.getElementById("entity-table");
|
||||
elEntityTableBody = document.getElementById("entity-table-body");
|
||||
elRefresh = document.getElementById("refresh");
|
||||
elToggleLocked = document.getElementById("locked");
|
||||
elToggleVisible = document.getElementById("visible");
|
||||
elDelete = document.getElementById("delete");
|
||||
elTeleport = document.getElementById("teleport");
|
||||
elRadius = document.getElementById("radius");
|
||||
elFooter = document.getElementById("footer-text");
|
||||
elNoEntitiesMessage = document.getElementById("no-entities");
|
||||
elNoEntitiesRadius = document.getElementById("no-entities-radius");
|
||||
elEntityTableScroll = document.getElementById("entity-table-scroll");
|
||||
|
||||
document.getElementById("entity-name").onclick = function() {
|
||||
setSortColumn('name');
|
||||
};
|
||||
document.getElementById("entity-type").onclick = function() {
|
||||
setSortColumn('type');
|
||||
};
|
||||
document.getElementById("entity-url").onclick = function() {
|
||||
setSortColumn('url');
|
||||
};
|
||||
document.getElementById("entity-locked").onclick = function () {
|
||||
setSortColumn('locked');
|
||||
};
|
||||
document.getElementById("entity-visible").onclick = function () {
|
||||
setSortColumn('visible');
|
||||
};
|
||||
|
||||
function onRowClicked(clickEvent) {
|
||||
var id = this.dataset.entityId;
|
||||
var selection = [this.dataset.entityId];
|
||||
if (clickEvent.ctrlKey) {
|
||||
selection = selection.concat(selectedEntities);
|
||||
} else if (clickEvent.shiftKey && selectedEntities.length > 0) {
|
||||
var previousItemFound = -1;
|
||||
var clickedItemFound = -1;
|
||||
for (var entity in entityList.visibleItems) {
|
||||
if (clickedItemFound === -1 && this.dataset.entityId == entityList.visibleItems[entity].values().id) {
|
||||
clickedItemFound = entity;
|
||||
} else if(previousItemFound === -1 && selectedEntities[0] == entityList.visibleItems[entity].values().id) {
|
||||
previousItemFound = entity;
|
||||
}
|
||||
}
|
||||
if (previousItemFound !== -1 && clickedItemFound !== -1) {
|
||||
var betweenItems = [];
|
||||
var toItem = Math.max(previousItemFound, clickedItemFound);
|
||||
// skip first and last item in this loop, we add them to selection after the loop
|
||||
for (var i = (Math.min(previousItemFound, clickedItemFound) + 1); i < toItem; i++) {
|
||||
entityList.visibleItems[i].elm.className = 'selected';
|
||||
betweenItems.push(entityList.visibleItems[i].values().id);
|
||||
}
|
||||
if (previousItemFound > clickedItemFound) {
|
||||
// always make sure that we add the items in the right order
|
||||
betweenItems.reverse();
|
||||
}
|
||||
selection = selection.concat(betweenItems, selectedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
selectedEntities = selection;
|
||||
|
||||
this.className = 'selected';
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "selectionUpdate",
|
||||
focus: false,
|
||||
entityIds: selection,
|
||||
}));
|
||||
}
|
||||
|
||||
function onRowDoubleClicked() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "selectionUpdate",
|
||||
focus: true,
|
||||
entityIds: [this.dataset.entityId],
|
||||
}));
|
||||
}
|
||||
|
||||
function addEntity(id, name, type, url, locked, visible) {
|
||||
var urlParts = url.split('/');
|
||||
var filename = urlParts[urlParts.length - 1];
|
||||
|
||||
if (entities[id] === undefined) {
|
||||
entityList.add([{ id: id, name: name, type: type, url: filename, locked: locked, visible: visible }],
|
||||
function (items) {
|
||||
var currentElement = items[0].elm;
|
||||
var id = items[0]._values.id;
|
||||
entities[id] = {
|
||||
id: id,
|
||||
name: name,
|
||||
el: currentElement,
|
||||
item: items[0]
|
||||
};
|
||||
currentElement.setAttribute('id', 'entity_' + id);
|
||||
currentElement.setAttribute('title', url);
|
||||
currentElement.dataset.entityId = id;
|
||||
currentElement.onclick = onRowClicked;
|
||||
currentElement.ondblclick = onRowDoubleClicked;
|
||||
});
|
||||
|
||||
if (refreshEntityListTimer) {
|
||||
clearTimeout(refreshEntityListTimer);
|
||||
}
|
||||
refreshEntityListTimer = setTimeout(refreshEntityListObject, 50);
|
||||
} else {
|
||||
var item = entities[id].item;
|
||||
item.values({ name: name, url: filename, locked: locked, visible: visible });
|
||||
}
|
||||
}
|
||||
|
||||
function clearEntities() {
|
||||
entities = {};
|
||||
entityList.clear();
|
||||
}
|
||||
|
||||
var elSortOrder = {
|
||||
name: document.querySelector('#entity-name .sort-order'),
|
||||
type: document.querySelector('#entity-type .sort-order'),
|
||||
url: document.querySelector('#entity-url .sort-order'),
|
||||
locked: document.querySelector('#entity-locked .sort-order'),
|
||||
visible: document.querySelector('#entity-visible .sort-order')
|
||||
}
|
||||
function setSortColumn(column) {
|
||||
if (currentSortColumn == column) {
|
||||
currentSortOrder = currentSortOrder == "asc" ? "desc" : "asc";
|
||||
} else {
|
||||
elSortOrder[currentSortColumn].innerHTML = "";
|
||||
currentSortColumn = column;
|
||||
currentSortOrder = "asc";
|
||||
}
|
||||
elSortOrder[column].innerHTML = currentSortOrder == "asc" ? ASCENDING_STRING : DESCENDING_STRING;
|
||||
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||
}
|
||||
setSortColumn('type');
|
||||
|
||||
function refreshEntities() {
|
||||
clearEntities();
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
||||
}
|
||||
|
||||
function refreshEntityListObject() {
|
||||
refreshEntityListTimer = null;
|
||||
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||
entityList.search(document.getElementById("filter").value);
|
||||
}
|
||||
|
||||
function updateSelectedEntities(selectedEntities) {
|
||||
var notFound = false;
|
||||
for (var id in entities) {
|
||||
entities[id].el.className = '';
|
||||
}
|
||||
for (var i = 0; i < selectedEntities.length; i++) {
|
||||
var id = selectedEntities[i];
|
||||
if (id in entities) {
|
||||
var entity = entities[id];
|
||||
entity.el.className = 'selected';
|
||||
} else {
|
||||
notFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedEntities.length > 1) {
|
||||
elFooter.firstChild.nodeValue = selectedEntities.length + " entities selected";
|
||||
} else if (selectedEntities.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity selected";
|
||||
} else if (entityList.visibleItems.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity found";
|
||||
} else {
|
||||
elFooter.firstChild.nodeValue = entityList.visibleItems.length + " entities found";
|
||||
}
|
||||
|
||||
// HACK: Fixes the footer and header text sometimes not displaying after adding or deleting entities.
|
||||
// The problem appears to be a bug in the Qt HTML/CSS rendering (Qt 5.5).
|
||||
document.getElementById("radius").focus();
|
||||
document.getElementById("radius").blur();
|
||||
|
||||
return notFound;
|
||||
}
|
||||
|
||||
elRefresh.onclick = function() {
|
||||
refreshEntities();
|
||||
}
|
||||
elToggleLocked.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleLocked' }));
|
||||
}
|
||||
elToggleVisible.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleVisible' }));
|
||||
}
|
||||
elTeleport.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
|
||||
}
|
||||
elDelete.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
refreshEntities();
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", function (keyDownEvent) {
|
||||
if (keyDownEvent.target.nodeName === "INPUT") {
|
||||
return;
|
||||
}
|
||||
var keyCode = keyDownEvent.keyCode;
|
||||
if (keyCode === DELETE) {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
refreshEntities();
|
||||
}
|
||||
}, false);
|
||||
|
||||
elRadius.onchange = function () {
|
||||
elRadius.value = Math.max(elRadius.value, 0);
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'radius', radius: elRadius.value }));
|
||||
refreshEntities();
|
||||
elNoEntitiesRadius.firstChild.nodeValue = elRadius.value;
|
||||
}
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.type === "clearEntityList") {
|
||||
clearEntities();
|
||||
} else if (data.type == "selectionUpdate") {
|
||||
var notFound = updateSelectedEntities(data.selectedIDs);
|
||||
if (notFound) {
|
||||
refreshEntities();
|
||||
}
|
||||
} else if (data.type == "update") {
|
||||
var newEntities = data.entities;
|
||||
if (newEntities.length == 0) {
|
||||
elNoEntitiesMessage.style.display = "block";
|
||||
elFooter.firstChild.nodeValue = "0 entities found";
|
||||
} else {
|
||||
elNoEntitiesMessage.style.display = "none";
|
||||
for (var i = 0; i < newEntities.length; i++) {
|
||||
var id = newEntities[i].id;
|
||||
addEntity(id, newEntities[i].name, newEntities[i].type, newEntities[i].url,
|
||||
newEntities[i].locked ? LOCKED_GLYPH : null,
|
||||
newEntities[i].visible ? VISIBLE_GLYPH : null);
|
||||
}
|
||||
updateSelectedEntities(data.selectedIDs);
|
||||
resize();
|
||||
}
|
||||
}
|
||||
});
|
||||
setTimeout(refreshEntities, 1000);
|
||||
}
|
||||
|
||||
function resize() {
|
||||
// Take up available window space
|
||||
elEntityTableScroll.style.height = window.innerHeight - 207;
|
||||
|
||||
var tds = document.querySelectorAll("#entity-table-body tr:first-child td");
|
||||
var ths = document.querySelectorAll("#entity-table thead th");
|
||||
if (tds.length >= ths.length) {
|
||||
// Update the widths of the header cells to match the body
|
||||
for (var i = 0; i < ths.length; i++) {
|
||||
ths[i].width = tds[i].offsetWidth;
|
||||
}
|
||||
} else {
|
||||
// Reasonable widths if nothing is displayed
|
||||
var tableWidth = document.getElementById("entity-table").offsetWidth;
|
||||
ths[0].width = 0.16 * tableWidth;
|
||||
ths[1].width = 0.34 * tableWidth;
|
||||
ths[2].width = 0.34 * tableWidth;
|
||||
ths[3].width = 0.08 * tableWidth;
|
||||
ths[4].width = 0.08 * tableWidth;
|
||||
}
|
||||
};
|
||||
|
||||
window.onresize = resize;
|
||||
resize();
|
||||
});
|
||||
|
||||
augmentSpinButtons();
|
||||
|
||||
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
||||
document.addEventListener("contextmenu", function (event) {
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
||||
<script type="text/javascript" src="js/spinButtons.js"></script>
|
||||
<script type="text/javascript" src="js/entityList.js"></script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div id="entity-list-header">
|
||||
|
@ -378,4 +76,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,144 +10,14 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="edit-style.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/colpick.css">
|
||||
<script src="jquery-2.1.4.min.js"></script>
|
||||
<script src="colpick.js"></script>
|
||||
<script src="js/jquery-2.1.4.min.js"></script>
|
||||
<script src="js/colpick.js"></script>
|
||||
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||
<script type="text/javascript" src="eventBridgeLoader.js"></script>
|
||||
<script type="text/javascript" src="spinButtons.js"></script>
|
||||
<script>
|
||||
function loaded() {
|
||||
openEventBridge(function() {
|
||||
elPosY = document.getElementById("horiz-y");
|
||||
elMinorSpacing = document.getElementById("minor-spacing");
|
||||
elMajorSpacing = document.getElementById("major-spacing");
|
||||
elSnapToGrid = document.getElementById("snap-to-grid");
|
||||
elHorizontalGridVisible = document.getElementById("horiz-grid-visible");
|
||||
elMoveToSelection = document.getElementById("move-to-selection");
|
||||
elMoveToAvatar = document.getElementById("move-to-avatar");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.origin) {
|
||||
var origin = data.origin;
|
||||
elPosY.value = origin.y;
|
||||
}
|
||||
|
||||
if (data.minorGridEvery !== undefined) {
|
||||
elMinorSpacing.value = data.minorGridEvery;
|
||||
}
|
||||
|
||||
if (data.majorGridEvery !== undefined) {
|
||||
elMajorSpacing.value = data.majorGridEvery;
|
||||
}
|
||||
|
||||
if (data.gridColor) {
|
||||
gridColor = data.gridColor;
|
||||
}
|
||||
|
||||
if (data.snapToGrid !== undefined) {
|
||||
elSnapToGrid.checked = data.snapToGrid == true;
|
||||
}
|
||||
|
||||
if (data.visible !== undefined) {
|
||||
elHorizontalGridVisible.checked = data.visible == true;
|
||||
}
|
||||
});
|
||||
|
||||
function emitUpdate() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "update",
|
||||
origin: {
|
||||
y: elPosY.value,
|
||||
},
|
||||
minorGridEvery: elMinorSpacing.value,
|
||||
majorGridEvery: elMajorSpacing.value,
|
||||
gridColor: gridColor,
|
||||
snapToGrid: elSnapToGrid.checked,
|
||||
visible: elHorizontalGridVisible.checked,
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elPosY.addEventListener("change", emitUpdate);
|
||||
elMinorSpacing.addEventListener("change", emitUpdate);
|
||||
elMajorSpacing.addEventListener("change", emitUpdate);
|
||||
elSnapToGrid.addEventListener("change", emitUpdate);
|
||||
elHorizontalGridVisible.addEventListener("change", emitUpdate);
|
||||
|
||||
elMoveToAvatar.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToAvatar",
|
||||
}));
|
||||
});
|
||||
elMoveToSelection.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToSelection",
|
||||
}));
|
||||
});
|
||||
|
||||
var gridColor = { red: 255, green: 255, blue: 255 };
|
||||
var elColor = document.getElementById("grid-color");
|
||||
var elColorRed = document.getElementById("grid-color-red");
|
||||
var elColorGreen = document.getElementById("grid-color-green");
|
||||
var elColorBlue = document.getElementById("grid-color-blue");
|
||||
elColor.style.backgroundColor = "rgb(" + gridColor.red + "," + gridColor.green + "," + gridColor.blue + ")";
|
||||
elColorRed.value = gridColor.red;
|
||||
elColorGreen.value = gridColor.green;
|
||||
elColorBlue.value = gridColor.blue;
|
||||
|
||||
var colorChangeFunction = function () {
|
||||
gridColor = { red: elColorRed.value, green: elColorGreen.value, blue: elColorBlue.value };
|
||||
elColor.style.backgroundColor = "rgb(" + gridColor.red + "," + gridColor.green + "," + gridColor.blue + ")";
|
||||
emitUpdate();
|
||||
};
|
||||
|
||||
var colorPickFunction = function (red, green, blue) {
|
||||
elColorRed.value = red;
|
||||
elColorGreen.value = green;
|
||||
elColorBlue.value = blue;
|
||||
gridColor = { red: red, green: green, blue: blue };
|
||||
emitUpdate();
|
||||
}
|
||||
|
||||
elColorRed.addEventListener('change', colorChangeFunction);
|
||||
elColorGreen.addEventListener('change', colorChangeFunction);
|
||||
elColorBlue.addEventListener('change', colorChangeFunction);
|
||||
$('#grid-color').colpick({
|
||||
colorScheme: 'dark',
|
||||
layout: 'hex',
|
||||
color: { r: gridColor.red, g: gridColor.green, b: gridColor.blue },
|
||||
onShow: function (colpick) {
|
||||
$('#grid-color').attr('active', 'true');
|
||||
},
|
||||
onHide: function (colpick) {
|
||||
$('#grid-color').attr('active', 'false');
|
||||
},
|
||||
onSubmit: function (hsb, hex, rgb, el) {
|
||||
$(el).css('background-color', '#' + hex);
|
||||
$(el).colpickHide();
|
||||
colorPickFunction(rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
});
|
||||
|
||||
augmentSpinButtons();
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
||||
});
|
||||
|
||||
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
||||
document.addEventListener("contextmenu", function (event) {
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
|
||||
<script type="text/javascript" src="js/spinButtons.js"></script>
|
||||
<script type="text/javascript" src="js/gridControls.js"></script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div id="grid-section">
|
||||
|
|
310
scripts/system/html/js/entityList.js
Normal file
310
scripts/system/html/js/entityList.js
Normal file
|
@ -0,0 +1,310 @@
|
|||
// entityList.js
|
||||
//
|
||||
// Created by Ryan Huffman on 19 Nov 2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
var entities = {};
|
||||
var selectedEntities = [];
|
||||
var currentSortColumn = 'type';
|
||||
var currentSortOrder = 'des';
|
||||
var entityList = null;
|
||||
var refreshEntityListTimer = null;
|
||||
const ASCENDING_STRING = '▾';
|
||||
const DESCENDING_STRING = '▴';
|
||||
const LOCKED_GLYPH = "";
|
||||
const VISIBLE_GLYPH = "";
|
||||
const DELETE = 46; // Key code for the delete key.
|
||||
const MAX_ITEMS = Number.MAX_VALUE; // Used to set the max length of the list of discovered entities.
|
||||
|
||||
debugPrint = function (message) {
|
||||
console.log(message);
|
||||
};
|
||||
|
||||
function loaded() {
|
||||
openEventBridge(function() {
|
||||
entityList = new List('entity-list', { valueNames: ['name', 'type', 'url', 'locked', 'visible'], page: MAX_ITEMS});
|
||||
entityList.clear();
|
||||
elEntityTable = document.getElementById("entity-table");
|
||||
elEntityTableBody = document.getElementById("entity-table-body");
|
||||
elRefresh = document.getElementById("refresh");
|
||||
elToggleLocked = document.getElementById("locked");
|
||||
elToggleVisible = document.getElementById("visible");
|
||||
elDelete = document.getElementById("delete");
|
||||
elTeleport = document.getElementById("teleport");
|
||||
elRadius = document.getElementById("radius");
|
||||
elFooter = document.getElementById("footer-text");
|
||||
elNoEntitiesMessage = document.getElementById("no-entities");
|
||||
elNoEntitiesRadius = document.getElementById("no-entities-radius");
|
||||
elEntityTableScroll = document.getElementById("entity-table-scroll");
|
||||
|
||||
document.getElementById("entity-name").onclick = function() {
|
||||
setSortColumn('name');
|
||||
};
|
||||
document.getElementById("entity-type").onclick = function() {
|
||||
setSortColumn('type');
|
||||
};
|
||||
document.getElementById("entity-url").onclick = function() {
|
||||
setSortColumn('url');
|
||||
};
|
||||
document.getElementById("entity-locked").onclick = function () {
|
||||
setSortColumn('locked');
|
||||
};
|
||||
document.getElementById("entity-visible").onclick = function () {
|
||||
setSortColumn('visible');
|
||||
};
|
||||
|
||||
function onRowClicked(clickEvent) {
|
||||
var id = this.dataset.entityId;
|
||||
var selection = [this.dataset.entityId];
|
||||
if (clickEvent.ctrlKey) {
|
||||
selection = selection.concat(selectedEntities);
|
||||
} else if (clickEvent.shiftKey && selectedEntities.length > 0) {
|
||||
var previousItemFound = -1;
|
||||
var clickedItemFound = -1;
|
||||
for (var entity in entityList.visibleItems) {
|
||||
if (clickedItemFound === -1 && this.dataset.entityId == entityList.visibleItems[entity].values().id) {
|
||||
clickedItemFound = entity;
|
||||
} else if(previousItemFound === -1 && selectedEntities[0] == entityList.visibleItems[entity].values().id) {
|
||||
previousItemFound = entity;
|
||||
}
|
||||
}
|
||||
if (previousItemFound !== -1 && clickedItemFound !== -1) {
|
||||
var betweenItems = [];
|
||||
var toItem = Math.max(previousItemFound, clickedItemFound);
|
||||
// skip first and last item in this loop, we add them to selection after the loop
|
||||
for (var i = (Math.min(previousItemFound, clickedItemFound) + 1); i < toItem; i++) {
|
||||
entityList.visibleItems[i].elm.className = 'selected';
|
||||
betweenItems.push(entityList.visibleItems[i].values().id);
|
||||
}
|
||||
if (previousItemFound > clickedItemFound) {
|
||||
// always make sure that we add the items in the right order
|
||||
betweenItems.reverse();
|
||||
}
|
||||
selection = selection.concat(betweenItems, selectedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
selectedEntities = selection;
|
||||
|
||||
this.className = 'selected';
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "selectionUpdate",
|
||||
focus: false,
|
||||
entityIds: selection,
|
||||
}));
|
||||
}
|
||||
|
||||
function onRowDoubleClicked() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "selectionUpdate",
|
||||
focus: true,
|
||||
entityIds: [this.dataset.entityId],
|
||||
}));
|
||||
}
|
||||
|
||||
function addEntity(id, name, type, url, locked, visible) {
|
||||
var urlParts = url.split('/');
|
||||
var filename = urlParts[urlParts.length - 1];
|
||||
|
||||
if (entities[id] === undefined) {
|
||||
entityList.add([{ id: id, name: name, type: type, url: filename, locked: locked, visible: visible }],
|
||||
function (items) {
|
||||
var currentElement = items[0].elm;
|
||||
var id = items[0]._values.id;
|
||||
entities[id] = {
|
||||
id: id,
|
||||
name: name,
|
||||
el: currentElement,
|
||||
item: items[0]
|
||||
};
|
||||
currentElement.setAttribute('id', 'entity_' + id);
|
||||
currentElement.setAttribute('title', url);
|
||||
currentElement.dataset.entityId = id;
|
||||
currentElement.onclick = onRowClicked;
|
||||
currentElement.ondblclick = onRowDoubleClicked;
|
||||
});
|
||||
|
||||
if (refreshEntityListTimer) {
|
||||
clearTimeout(refreshEntityListTimer);
|
||||
}
|
||||
refreshEntityListTimer = setTimeout(refreshEntityListObject, 50);
|
||||
} else {
|
||||
var item = entities[id].item;
|
||||
item.values({ name: name, url: filename, locked: locked, visible: visible });
|
||||
}
|
||||
}
|
||||
|
||||
function clearEntities() {
|
||||
entities = {};
|
||||
entityList.clear();
|
||||
}
|
||||
|
||||
var elSortOrder = {
|
||||
name: document.querySelector('#entity-name .sort-order'),
|
||||
type: document.querySelector('#entity-type .sort-order'),
|
||||
url: document.querySelector('#entity-url .sort-order'),
|
||||
locked: document.querySelector('#entity-locked .sort-order'),
|
||||
visible: document.querySelector('#entity-visible .sort-order')
|
||||
}
|
||||
function setSortColumn(column) {
|
||||
if (currentSortColumn == column) {
|
||||
currentSortOrder = currentSortOrder == "asc" ? "desc" : "asc";
|
||||
} else {
|
||||
elSortOrder[currentSortColumn].innerHTML = "";
|
||||
currentSortColumn = column;
|
||||
currentSortOrder = "asc";
|
||||
}
|
||||
elSortOrder[column].innerHTML = currentSortOrder == "asc" ? ASCENDING_STRING : DESCENDING_STRING;
|
||||
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||
}
|
||||
setSortColumn('type');
|
||||
|
||||
function refreshEntities() {
|
||||
clearEntities();
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
||||
}
|
||||
|
||||
function refreshEntityListObject() {
|
||||
refreshEntityListTimer = null;
|
||||
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||
entityList.search(document.getElementById("filter").value);
|
||||
}
|
||||
|
||||
function updateSelectedEntities(selectedEntities) {
|
||||
var notFound = false;
|
||||
for (var id in entities) {
|
||||
entities[id].el.className = '';
|
||||
}
|
||||
for (var i = 0; i < selectedEntities.length; i++) {
|
||||
var id = selectedEntities[i];
|
||||
if (id in entities) {
|
||||
var entity = entities[id];
|
||||
entity.el.className = 'selected';
|
||||
} else {
|
||||
notFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedEntities.length > 1) {
|
||||
elFooter.firstChild.nodeValue = selectedEntities.length + " entities selected";
|
||||
} else if (selectedEntities.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity selected";
|
||||
} else if (entityList.visibleItems.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity found";
|
||||
} else {
|
||||
elFooter.firstChild.nodeValue = entityList.visibleItems.length + " entities found";
|
||||
}
|
||||
|
||||
// HACK: Fixes the footer and header text sometimes not displaying after adding or deleting entities.
|
||||
// The problem appears to be a bug in the Qt HTML/CSS rendering (Qt 5.5).
|
||||
document.getElementById("radius").focus();
|
||||
document.getElementById("radius").blur();
|
||||
|
||||
return notFound;
|
||||
}
|
||||
|
||||
elRefresh.onclick = function() {
|
||||
refreshEntities();
|
||||
}
|
||||
elToggleLocked.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleLocked' }));
|
||||
}
|
||||
elToggleVisible.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleVisible' }));
|
||||
}
|
||||
elTeleport.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
|
||||
}
|
||||
elDelete.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
refreshEntities();
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", function (keyDownEvent) {
|
||||
if (keyDownEvent.target.nodeName === "INPUT") {
|
||||
return;
|
||||
}
|
||||
var keyCode = keyDownEvent.keyCode;
|
||||
if (keyCode === DELETE) {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
refreshEntities();
|
||||
}
|
||||
}, false);
|
||||
|
||||
elRadius.onchange = function () {
|
||||
elRadius.value = Math.max(elRadius.value, 0);
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'radius', radius: elRadius.value }));
|
||||
refreshEntities();
|
||||
elNoEntitiesRadius.firstChild.nodeValue = elRadius.value;
|
||||
}
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.type === "clearEntityList") {
|
||||
clearEntities();
|
||||
} else if (data.type == "selectionUpdate") {
|
||||
var notFound = updateSelectedEntities(data.selectedIDs);
|
||||
if (notFound) {
|
||||
refreshEntities();
|
||||
}
|
||||
} else if (data.type == "update") {
|
||||
var newEntities = data.entities;
|
||||
if (newEntities.length == 0) {
|
||||
elNoEntitiesMessage.style.display = "block";
|
||||
elFooter.firstChild.nodeValue = "0 entities found";
|
||||
} else {
|
||||
elNoEntitiesMessage.style.display = "none";
|
||||
for (var i = 0; i < newEntities.length; i++) {
|
||||
var id = newEntities[i].id;
|
||||
addEntity(id, newEntities[i].name, newEntities[i].type, newEntities[i].url,
|
||||
newEntities[i].locked ? LOCKED_GLYPH : null,
|
||||
newEntities[i].visible ? VISIBLE_GLYPH : null);
|
||||
}
|
||||
updateSelectedEntities(data.selectedIDs);
|
||||
resize();
|
||||
}
|
||||
}
|
||||
});
|
||||
setTimeout(refreshEntities, 1000);
|
||||
}
|
||||
|
||||
function resize() {
|
||||
// Take up available window space
|
||||
elEntityTableScroll.style.height = window.innerHeight - 207;
|
||||
|
||||
var tds = document.querySelectorAll("#entity-table-body tr:first-child td");
|
||||
var ths = document.querySelectorAll("#entity-table thead th");
|
||||
if (tds.length >= ths.length) {
|
||||
// Update the widths of the header cells to match the body
|
||||
for (var i = 0; i < ths.length; i++) {
|
||||
ths[i].width = tds[i].offsetWidth;
|
||||
}
|
||||
} else {
|
||||
// Reasonable widths if nothing is displayed
|
||||
var tableWidth = document.getElementById("entity-table").offsetWidth;
|
||||
ths[0].width = 0.16 * tableWidth;
|
||||
ths[1].width = 0.34 * tableWidth;
|
||||
ths[2].width = 0.34 * tableWidth;
|
||||
ths[3].width = 0.08 * tableWidth;
|
||||
ths[4].width = 0.08 * tableWidth;
|
||||
}
|
||||
};
|
||||
|
||||
window.onresize = resize;
|
||||
resize();
|
||||
});
|
||||
|
||||
augmentSpinButtons();
|
||||
|
||||
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
||||
document.addEventListener("contextmenu", function (event) {
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
|
1309
scripts/system/html/js/entityProperties.js
Normal file
1309
scripts/system/html/js/entityProperties.js
Normal file
File diff suppressed because it is too large
Load diff
138
scripts/system/html/js/gridControls.js
Normal file
138
scripts/system/html/js/gridControls.js
Normal file
|
@ -0,0 +1,138 @@
|
|||
// gridControls.js
|
||||
//
|
||||
// Created by Ryan Huffman on 6 Nov 2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
function loaded() {
|
||||
openEventBridge(function() {
|
||||
elPosY = document.getElementById("horiz-y");
|
||||
elMinorSpacing = document.getElementById("minor-spacing");
|
||||
elMajorSpacing = document.getElementById("major-spacing");
|
||||
elSnapToGrid = document.getElementById("snap-to-grid");
|
||||
elHorizontalGridVisible = document.getElementById("horiz-grid-visible");
|
||||
elMoveToSelection = document.getElementById("move-to-selection");
|
||||
elMoveToAvatar = document.getElementById("move-to-avatar");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.origin) {
|
||||
var origin = data.origin;
|
||||
elPosY.value = origin.y;
|
||||
}
|
||||
|
||||
if (data.minorGridEvery !== undefined) {
|
||||
elMinorSpacing.value = data.minorGridEvery;
|
||||
}
|
||||
|
||||
if (data.majorGridEvery !== undefined) {
|
||||
elMajorSpacing.value = data.majorGridEvery;
|
||||
}
|
||||
|
||||
if (data.gridColor) {
|
||||
gridColor = data.gridColor;
|
||||
}
|
||||
|
||||
if (data.snapToGrid !== undefined) {
|
||||
elSnapToGrid.checked = data.snapToGrid == true;
|
||||
}
|
||||
|
||||
if (data.visible !== undefined) {
|
||||
elHorizontalGridVisible.checked = data.visible == true;
|
||||
}
|
||||
});
|
||||
|
||||
function emitUpdate() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "update",
|
||||
origin: {
|
||||
y: elPosY.value,
|
||||
},
|
||||
minorGridEvery: elMinorSpacing.value,
|
||||
majorGridEvery: elMajorSpacing.value,
|
||||
gridColor: gridColor,
|
||||
snapToGrid: elSnapToGrid.checked,
|
||||
visible: elHorizontalGridVisible.checked,
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elPosY.addEventListener("change", emitUpdate);
|
||||
elMinorSpacing.addEventListener("change", emitUpdate);
|
||||
elMajorSpacing.addEventListener("change", emitUpdate);
|
||||
elSnapToGrid.addEventListener("change", emitUpdate);
|
||||
elHorizontalGridVisible.addEventListener("change", emitUpdate);
|
||||
|
||||
elMoveToAvatar.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToAvatar",
|
||||
}));
|
||||
});
|
||||
elMoveToSelection.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToSelection",
|
||||
}));
|
||||
});
|
||||
|
||||
var gridColor = { red: 255, green: 255, blue: 255 };
|
||||
var elColor = document.getElementById("grid-color");
|
||||
var elColorRed = document.getElementById("grid-color-red");
|
||||
var elColorGreen = document.getElementById("grid-color-green");
|
||||
var elColorBlue = document.getElementById("grid-color-blue");
|
||||
elColor.style.backgroundColor = "rgb(" + gridColor.red + "," + gridColor.green + "," + gridColor.blue + ")";
|
||||
elColorRed.value = gridColor.red;
|
||||
elColorGreen.value = gridColor.green;
|
||||
elColorBlue.value = gridColor.blue;
|
||||
|
||||
var colorChangeFunction = function () {
|
||||
gridColor = { red: elColorRed.value, green: elColorGreen.value, blue: elColorBlue.value };
|
||||
elColor.style.backgroundColor = "rgb(" + gridColor.red + "," + gridColor.green + "," + gridColor.blue + ")";
|
||||
emitUpdate();
|
||||
};
|
||||
|
||||
var colorPickFunction = function (red, green, blue) {
|
||||
elColorRed.value = red;
|
||||
elColorGreen.value = green;
|
||||
elColorBlue.value = blue;
|
||||
gridColor = { red: red, green: green, blue: blue };
|
||||
emitUpdate();
|
||||
}
|
||||
|
||||
elColorRed.addEventListener('change', colorChangeFunction);
|
||||
elColorGreen.addEventListener('change', colorChangeFunction);
|
||||
elColorBlue.addEventListener('change', colorChangeFunction);
|
||||
$('#grid-color').colpick({
|
||||
colorScheme: 'dark',
|
||||
layout: 'hex',
|
||||
color: { r: gridColor.red, g: gridColor.green, b: gridColor.blue },
|
||||
onShow: function (colpick) {
|
||||
$('#grid-color').attr('active', 'true');
|
||||
},
|
||||
onHide: function (colpick) {
|
||||
$('#grid-color').attr('active', 'false');
|
||||
},
|
||||
onSubmit: function (hsb, hex, rgb, el) {
|
||||
$(el).css('background-color', '#' + hex);
|
||||
$(el).colpickHide();
|
||||
colorPickFunction(rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
});
|
||||
|
||||
augmentSpinButtons();
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
||||
});
|
||||
|
||||
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
|
||||
document.addEventListener("contextmenu", function (event) {
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue