From 611779b58b0f92461fc97a1ed78c9228238a0ecb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 8 Jul 2016 16:25:50 -0700 Subject: [PATCH 01/78] Improve gamma correction implementation in cube map processing --- libraries/gpu/src/gpu/Texture.cpp | 9 +++------ libraries/shared/src/ColorUtils.h | 7 +++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index f9a8f3b26b..bd0ad0ce7b 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -788,12 +788,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]) * UCHAR_TO_FLOAT, + ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex+1]) * UCHAR_TO_FLOAT, + ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex+2]) * UCHAR_TO_FLOAT); // scale color and add to previously accumulated coefficients sphericalHarmonicsScale(shBuffB.data(), order, diff --git a/libraries/shared/src/ColorUtils.h b/libraries/shared/src/ColorUtils.h index 5ee9254bc9..42d36ebd4b 100644 --- a/libraries/shared/src/ColorUtils.h +++ b/libraries/shared/src/ColorUtils.h @@ -17,6 +17,9 @@ #include "DependencyManager.h" +static 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.00251584218443f, 0.00279619194822f, 0.00309396642819f, 0.00340946205345f, 0.00374296799396f, 0.00409476661624f, 0.00446513389425f, 0.00485433978143f, 0.00526264854875f, 0.00569031909303f, 0.00613760521883f, 0.00660475589722f, 0.00709201550367f, 0.00759962403765f, 0.00812781732551f, 0.00867682720861f, 0.00924688171802f, 0.00983820523704f, 0.0104510186528f, 0.0110855394981f, 0.0117419820834f, 0.0124205576216f, 0.0131214743443f, 0.0138449376117f, 0.0145911500156f, 0.0153603114768f, 0.0161526193372f, 0.0169682684465f, 0.0178074512441f, 0.0186703578377f, 0.0195571760767f, 0.0204680916222f, 0.0214032880141f, 0.0223629467344f, 0.0233472472675f, 0.0243563671578f, 0.0253904820647f, 0.026449765815f, 0.0275343904531f, 0.0286445262888f, 0.0297803419432f, 0.0309420043928f, 0.0321296790111f, 0.0333435296099f, 0.0345837184768f, 0.0358504064137f, 0.0371437527716f, 0.0384639154854f, 0.0398110511069f, 0.0411853148367f, 0.0425868605546f, 0.0440158408496f, 0.045472407048f, 0.046956709241f, 0.0484688963113f, 0.0500091159586f, 0.0515775147244f, 0.0531742380159f, 0.0547994301291f, 0.0564532342711f, 0.058135792582f, 0.0598472461555f, 0.0615877350593f, 0.063357398355f, 0.0651563741167f, 0.0669847994499f, 0.0688428105093f, 0.0707305425158f, 0.0726481297741f, 0.0745957056885f, 0.0765734027789f, 0.0785813526965f, 0.0806196862387f, 0.0826885333636f, 0.0847880232044f, 0.086918284083f, 0.0890794435236f, 0.0912716282659f, 0.0934949642776f, 0.0957495767668f, 0.0980355901944f, 0.100353128286f, 0.102702314041f, 0.10508326975f, 0.107496116997f, 0.109940976678f, 0.112417969007f, 0.114927213525f, 0.117468829116f, 0.120042934009f, 0.122649645793f, 0.125289081424f, 0.127961357236f, 0.130666588944f, 0.13340489166f, 0.136176379898f, 0.138981167581f, 0.141819368051f, 0.144691094076f, 0.147596457859f, 0.150535571041f, 0.153508544716f, 0.156515489432f, 0.1595565152f, 0.1626317315f, 0.16574124729f, 0.168885171012f, 0.172063610595f, 0.175276673468f, 0.178524466557f, 0.181807096302f, 0.185124668654f, 0.188477289086f, 0.191865062595f, 0.195288093712f, 0.198746486503f, 0.202240344578f, 0.205769771096f, 0.209334868766f, 0.212935739858f, 0.216572486205f, 0.220245209207f, 0.223954009837f, 0.227698988648f, 0.231480245773f, 0.235297880934f, 0.239151993444f, 0.243042682212f, 0.246970045747f, 0.250934182163f, 0.254935189183f, 0.258973164144f, 0.263048203998f, 0.267160405319f, 0.271309864307f, 0.27549667679f, 0.279720938228f, 0.283982743718f, 0.288282187998f, 0.292619365448f, 0.296994370096f, 0.30140729562f, 0.305858235354f, 0.310347282289f, 0.314874529074f, 0.319440068025f, 0.324043991126f, 0.32868639003f, 0.333367356062f, 0.338086980228f, 0.34284535321f, 0.347642565374f, 0.352478706774f, 0.357353867148f, 0.36226813593f, 0.367221602246f, 0.372214354918f, 0.37724648247f, 0.382318073128f, 0.387429214822f, 0.392579995191f, 0.397770501584f, 0.403000821062f, 0.408271040402f, 0.413581246099f, 0.418931524369f, 0.424321961148f, 0.4297526421f, 0.435223652615f, 0.440735077813f, 0.446287002544f, 0.451879511396f, 0.45751268869f, 0.463186618488f, 0.46890138459f, 0.474657070542f, 0.480453759632f, 0.486291534897f, 0.492170479122f, 0.498090674843f, 0.50405220435f, 0.510055149687f, 0.516099592656f, 0.522185614816f, 0.528313297489f, 0.534482721758f, 0.54069396847f, 0.546947118241f, 0.553242251452f, 0.559579448254f, 0.565958788573f, 0.572380352104f, 0.578844218319f, 0.585350466467f, 0.591899175574f, 0.598490424448f, 0.605124291677f, 0.611800855632f, 0.61852019447f, 0.625282386134f, 0.632087508355f, 0.638935638652f, 0.645826854338f, 0.652761232515f, 0.659738850081f, 0.66675978373f, 0.673824109951f, 0.680931905032f, 0.688083245062f, 0.695278205929f, 0.702516863324f, 0.709799292744f, 0.717125569488f, 0.724495768663f, 0.731909965185f, 0.739368233777f, 0.746870648974f, 0.754417285121f, 0.762008216379f, 0.76964351672f, 0.777323259932f, 0.785047519623f, 0.792816369214f, 0.800629881949f, 0.80848813089f, 0.816391188922f, 0.824339128751f, 0.832332022907f, 0.840369943747f, 0.848452963452f, 0.856581154031f, 0.864754587319f, 0.872973334984f, 0.881237468522f, 0.889547059261f, 0.897902178361f, 0.906302896816f, 0.914749285456f, 0.923241414944f, 0.931779355781f, 0.940363178305f, 0.948992952695f, 0.957668748966f, 0.966390636975f, 0.975158686423f }; + 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. From 676f4bdfcfdbbe0e2b1d11559d458dc98d11e86a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 29 Jul 2016 15:36:32 -0700 Subject: [PATCH 02/78] misc fixes from particles branch --- cmake/macros/AutoScribeShader.cmake | 16 +++++++++------- cmake/macros/SetupHifiLibrary.cmake | 3 ++- interface/src/ui/overlays/Overlays.h | 2 +- .../src/RenderableModelEntityItem.cpp | 19 ------------------- .../src/RenderableModelEntityItem.h | 1 - .../src/textured_particle.slv | 2 +- libraries/entities/src/EntityTreeElement.cpp | 4 ++-- libraries/gpu-gl/src/gpu/gl/GLShared.cpp | 2 +- libraries/gpu/src/gpu/Shader.h | 15 +++++++++------ libraries/render-utils/CMakeLists.txt | 4 ++-- libraries/render-utils/src/AnimDebugDraw.cpp | 2 ++ libraries/render-utils/src/GeometryCache.cpp | 2 +- libraries/render/CMakeLists.txt | 2 +- 13 files changed, 31 insertions(+), 43 deletions(-) diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index dfa59943d6..e586304503 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -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() \ No newline at end of file diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index 26c769c6e6..a10c7c11e6 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -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() diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 99f74fa0f9..e19a6b36a9 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -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 diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 4e8ecf3054..b0207358d2 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -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(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){ } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 339c907532..cced8df6ab 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -40,7 +40,6 @@ public: void doInitialModelSimulation(); - virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr); virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 79f75187c5..cab76227c4 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -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), diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 0523933ee6..657e0b286b 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -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; diff --git a/libraries/gpu-gl/src/gpu/gl/GLShared.cpp b/libraries/gpu-gl/src/gpu/gl/GLShared.cpp index 8f234ca6b4..35cf9b83ba 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShared.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShared.cpp @@ -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; } diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 9072bf23a9..a741eafd40 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -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 { diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 2a7d33e33a..7b272f7b7d 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -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() diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 11c43eaee4..f1443f7e4d 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -15,6 +15,8 @@ #include "GLMHelpers.h" #include "DebugDraw.h" +#include + #include "AnimDebugDraw.h" struct Vertex { diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index cebd8ad37f..bead7549db 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -11,7 +11,7 @@ #include "GeometryCache.h" - +#include #include #include diff --git a/libraries/render/CMakeLists.txt b/libraries/render/CMakeLists.txt index c5cfdf3668..76fc8303ce 100644 --- a/libraries/render/CMakeLists.txt +++ b/libraries/render/CMakeLists.txt @@ -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) From 217a102926c39e732437559a60a87f1a8938864a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 1 Aug 2016 13:15:55 -0700 Subject: [PATCH 03/78] working on loading fade --- libraries/render-utils/src/MeshPartPayload.cpp | 16 +++++++++++++++- libraries/render-utils/src/MeshPartPayload.h | 7 +++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index cb6c73f414..da9ba50271 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -329,6 +329,8 @@ ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int par updateTransform(transform, offsetTransform); initCache(); + + _fadeStartTime = usecTimestampNow(); } void ModelMeshPartPayload::initCache() { @@ -352,6 +354,11 @@ void ModelMeshPartPayload::initCache() { } +float ModelMeshPartPayload::calcFadeRatio() const { + const float FADE_TIME = 0.5f; + float t = std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f); + return -0.5f * (cosf(M_PI*t) - 1.0f); +} void ModelMeshPartPayload::notifyLocationChanged() { @@ -392,6 +399,10 @@ ItemKey ModelMeshPartPayload::getKey() const { } } + if (calcFadeRatio() < 1.0f) { + builder.withTransparent(); + } + return builder.build(); } @@ -429,7 +440,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { drawMaterialKey = _drawMaterial->getKey(); } - bool isTranslucent = drawMaterialKey.isTranslucent(); + bool isTranslucent = drawMaterialKey.isTranslucent() || calcFadeRatio() < 1.0f; bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); @@ -541,6 +552,9 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { // apply material properties bindMaterial(batch, locations); + // model fading + batch._glColor4f(1.0f, 1.0f, 1.0f, calcFadeRatio()); + if (args) { args->_details._materialSwitches++; } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 41869ec7e3..d5c59a7967 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -81,6 +81,9 @@ public: void notifyLocationChanged() override; void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector& clusterMatrices); + // Entity fade in + float calcFadeRatio() const; + // Render Item interface render::ItemKey getKey() const override; render::ShapeKey getShapeKey() const override; // shape interface @@ -99,6 +102,10 @@ public: bool _isSkinned{ false }; bool _isBlendShaped{ false }; + +private: + quint64 _fadeStartTime { usecTimestampNow() }; + bool _hasFadeStarted { false }; }; namespace render { From 313ba87fce2788ed441c3d3d377f828564e7b91c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 1 Aug 2016 14:47:20 -0700 Subject: [PATCH 04/78] fade on texture load --- libraries/render-utils/src/MeshPartPayload.cpp | 15 +++++---------- libraries/render-utils/src/MeshPartPayload.h | 7 +++++-- libraries/render-utils/src/Model.cpp | 4 ++++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index da9ba50271..99fedefc99 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -329,8 +329,6 @@ ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int par updateTransform(transform, offsetTransform); initCache(); - - _fadeStartTime = usecTimestampNow(); } void ModelMeshPartPayload::initCache() { @@ -357,7 +355,7 @@ void ModelMeshPartPayload::initCache() { float ModelMeshPartPayload::calcFadeRatio() const { const float FADE_TIME = 0.5f; float t = std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f); - return -0.5f * (cosf(M_PI*t) - 1.0f); + return -(cosf(M_PI_2*t) - 1.0f); } void ModelMeshPartPayload::notifyLocationChanged() { @@ -495,9 +493,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 = calcFadeRatio(); + if (!_hasColorAttrib || fadeRatio < 1.0f) { + batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); } } @@ -528,7 +526,7 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: void ModelMeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); - if (!_model->_readyWhenAdded || !_model->_isVisible) { + if (!_model->_readyWhenAdded || !_model->_isVisible || !_hasStartedFade) { return; // bail asap } @@ -552,9 +550,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { // apply material properties bindMaterial(batch, locations); - // model fading - batch._glColor4f(1.0f, 1.0f, 1.0f, calcFadeRatio()); - if (args) { args->_details._materialSwitches++; } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index d5c59a7967..4be6132122 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -83,6 +83,9 @@ public: // Entity fade in float calcFadeRatio() const; + void startFade() { _fadeStartTime = usecTimestampNow(); } + bool hasStartedFade() { return _hasStartedFade; } + void setHasStartedFade(bool hasStartedFade) { _hasStartedFade = hasStartedFade; } // Render Item interface render::ItemKey getKey() const override; @@ -104,8 +107,8 @@ public: bool _isBlendShaped{ false }; private: - quint64 _fadeStartTime { usecTimestampNow() }; - bool _hasFadeStarted { false }; + quint64 _fadeStartTime { 0 }; + bool _hasStartedFade { false }; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b04a1d8023..cc7178587f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -207,6 +207,10 @@ void Model::updateRenderItems() { render::PendingChanges pendingChanges; foreach (auto itemID, self->_modelMeshRenderItems.keys()) { pendingChanges.updateItem(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) { + if (!data.hasStartedFade() && data._model && data._model->isLoaded() && data._model->getGeometry()->areTexturesLoaded()) { + data.startFade(); + data.setHasStartedFade(true); + } // 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. From ae0b9ea9a32ea85b4a73df33d37ec8e0404128cc Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 1 Aug 2016 15:26:04 -0700 Subject: [PATCH 05/78] fade wireframes --- libraries/render-utils/src/MeshPartPayload.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 99fedefc99..030b5699aa 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -438,7 +438,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { drawMaterialKey = _drawMaterial->getKey(); } - bool isTranslucent = drawMaterialKey.isTranslucent() || calcFadeRatio() < 1.0f; + bool isTranslucent = drawMaterialKey.isTranslucent(); bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); @@ -452,7 +452,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (isTranslucent) { + if (isTranslucent || calcFadeRatio() < 0.9f) { builder.withTranslucent(); } if (hasTangents) { From 6154aaddda9c911a202e4a8a2b058fe3005cfa77 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 1 Aug 2016 16:19:03 -0700 Subject: [PATCH 06/78] try to fix linux build --- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 030b5699aa..48c1c88757 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -355,7 +355,7 @@ void ModelMeshPartPayload::initCache() { float ModelMeshPartPayload::calcFadeRatio() const { const float FADE_TIME = 0.5f; float t = std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f); - return -(cosf(M_PI_2*t) - 1.0f); + return -(cosf((float)M_PI_2 * t) - 1.0f); } void ModelMeshPartPayload::notifyLocationChanged() { From 0b5c7909b829f48dc61954b62fef61d1ad8e9a38 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 1 Aug 2016 18:45:25 -0700 Subject: [PATCH 07/78] a calculated change --- libraries/render-utils/src/MeshPartPayload.cpp | 8 ++++---- libraries/render-utils/src/MeshPartPayload.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 48c1c88757..9f107bd3e1 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -352,7 +352,7 @@ void ModelMeshPartPayload::initCache() { } -float ModelMeshPartPayload::calcFadeRatio() const { +float ModelMeshPartPayload::calculateFadeRatio() const { const float FADE_TIME = 0.5f; float t = std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f); return -(cosf((float)M_PI_2 * t) - 1.0f); @@ -397,7 +397,7 @@ ItemKey ModelMeshPartPayload::getKey() const { } } - if (calcFadeRatio() < 1.0f) { + if (calculateFadeRatio() < 1.0f) { builder.withTransparent(); } @@ -452,7 +452,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (isTranslucent || calcFadeRatio() < 0.9f) { + if (isTranslucent || calculateFadeRatio() < 0.9f) { builder.withTranslucent(); } if (hasTangents) { @@ -493,7 +493,7 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); } - float fadeRatio = calcFadeRatio(); + float fadeRatio = calculateFadeRatio(); if (!_hasColorAttrib || fadeRatio < 1.0f) { batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 4be6132122..e0181a366d 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -82,7 +82,7 @@ public: void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector& clusterMatrices); // Entity fade in - float calcFadeRatio() const; + float calculateFadeRatio() const; void startFade() { _fadeStartTime = usecTimestampNow(); } bool hasStartedFade() { return _hasStartedFade; } void setHasStartedFade(bool hasStartedFade) { _hasStartedFade = hasStartedFade; } From 74f11eb70b5692eb1b0bca523cf709ab39250747 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Aug 2016 10:50:31 -0700 Subject: [PATCH 08/78] try a different easing function --- libraries/render-utils/src/MeshPartPayload.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 9f107bd3e1..63068f7796 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -353,9 +353,13 @@ void ModelMeshPartPayload::initCache() { } float ModelMeshPartPayload::calculateFadeRatio() const { - const float FADE_TIME = 0.5f; - float t = std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f); - return -(cosf((float)M_PI_2 * t) - 1.0f); + const float FADE_TIME = 1.0f; + float t = 2.0f * std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((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 * (-pow(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); } void ModelMeshPartPayload::notifyLocationChanged() { From 3d08502080f40477a42d9b885216432a29fe0983 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Aug 2016 10:50:57 -0700 Subject: [PATCH 09/78] space --- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 63068f7796..0616ae20f7 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -354,7 +354,7 @@ void ModelMeshPartPayload::initCache() { float ModelMeshPartPayload::calculateFadeRatio() const { const float FADE_TIME = 1.0f; - float t = 2.0f * std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f); + float t = 2.0f * std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((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 * (-pow(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 From ad5dec829c22695afd40a69406900d4e3e968129 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Aug 2016 10:52:51 -0700 Subject: [PATCH 10/78] why did I change that --- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 0616ae20f7..83b25a49e3 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -456,7 +456,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (isTranslucent || calculateFadeRatio() < 0.9f) { + if (isTranslucent || calculateFadeRatio() < 1.0f) { builder.withTranslucent(); } if (hasTangents) { From 5de21982be4b1e587a6bd6ece6c9c1bc96137ffd Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Aug 2016 11:44:17 -0700 Subject: [PATCH 11/78] fix linux build --- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 83b25a49e3..f599e9df67 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -355,7 +355,7 @@ void ModelMeshPartPayload::initCache() { float ModelMeshPartPayload::calculateFadeRatio() const { const float FADE_TIME = 1.0f; float t = 2.0f * std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((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 * (-pow(2.0f, -10.0f * (t - 1.0f)) + 2.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; From d63a0ef08f36be368dc61448a4c8507b5c9b3942 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 2 Aug 2016 18:09:42 -0700 Subject: [PATCH 12/78] working on making other entities transparent --- .../src/RenderableEntityItem.cpp | 4 ++-- .../src/RenderableShapeEntityItem.cpp | 9 +++++++-- .../src/RenderableShapeEntityItem.h | 6 +++++- libraries/entities/src/EntityItem.h | 1 + libraries/render-utils/src/MeshPartPayload.cpp | 18 +++++------------- libraries/render-utils/src/MeshPartPayload.h | 1 - libraries/shared/src/Interpolate.cpp | 12 ++++++++++++ libraries/shared/src/Interpolate.h | 4 ++++ 8 files changed, 36 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 011675fc82..d49eacdf7b 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -1,4 +1,4 @@ -// + // // RenderableEntityItem.cpp // interface/src // @@ -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->getType() == EntityTypes::PolyLine || payload->entity->isTransparent())) { return ItemKey::Builder::transparentShape(); } } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 48ad05a714..61e152f5ac 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -40,7 +40,6 @@ static std::array MAPPING { { GeometryCache::Cylinder, } }; - RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { Pointer entity = std::make_shared(entityID); entity->setProperties(properties); @@ -106,7 +105,13 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { DependencyManager::get()->renderShape(batch, MAPPING[_shape]); } else { // FIXME, support instanced multi-shape rendering using multidraw indirect - DependencyManager::get()->renderSolidShapeInstance(batch, MAPPING[_shape], color); + float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); + if (fadeRatio < 1.0f) { + color = glm::vec4(0.0f, 0.0f, 1.0f, 0.5f); + DependencyManager::get()->renderSolidShapeInstance(batch, MAPPING[_shape], color); + } else { + DependencyManager::get()->renderSolidShapeInstance(batch, MAPPING[_shape], color); + } } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index b18370b13c..7bfb411874 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -11,6 +11,7 @@ #include #include +#include #include "RenderableEntityItem.h" @@ -21,15 +22,18 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties); - RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {} + RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID), _fadeStartTime(usecTimestampNow()) {} void render(RenderArgs* args) override; void setUserData(const QString& value) override; + bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } + SIMPLE_RENDERABLE(); private: QSharedPointer _procedural; + quint64 _fadeStartTime { 0 }; }; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 9fa13690f1..f1715a2525 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -435,6 +435,7 @@ public: QUuid getOwningAvatarID() const { return _owningAvatarID; } void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; } + virtual bool isTransparent() { return false; } protected: diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index f599e9df67..fe914f4d1a 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -13,6 +13,8 @@ #include +#include + #include "DeferredLightingEffect.h" #include "Model.h" @@ -352,16 +354,6 @@ void ModelMeshPartPayload::initCache() { } -float ModelMeshPartPayload::calculateFadeRatio() const { - const float FADE_TIME = 1.0f; - float t = 2.0f * std::min(((float)(usecTimestampNow() - _fadeStartTime)) / ((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); -} - void ModelMeshPartPayload::notifyLocationChanged() { } @@ -401,7 +393,7 @@ ItemKey ModelMeshPartPayload::getKey() const { } } - if (calculateFadeRatio() < 1.0f) { + if (Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f) { builder.withTransparent(); } @@ -456,7 +448,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (isTranslucent || calculateFadeRatio() < 1.0f) { + if (isTranslucent || Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f) { builder.withTranslucent(); } if (hasTangents) { @@ -497,7 +489,7 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); } - float fadeRatio = calculateFadeRatio(); + float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); if (!_hasColorAttrib || fadeRatio < 1.0f) { batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index e0181a366d..54878f3352 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -82,7 +82,6 @@ public: void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector& clusterMatrices); // Entity fade in - float calculateFadeRatio() const; void startFade() { _fadeStartTime = usecTimestampNow(); } bool hasStartedFade() { return _hasStartedFade; } void setHasStartedFade(bool hasStartedFade) { _hasStartedFade = hasStartedFade; } diff --git a/libraries/shared/src/Interpolate.cpp b/libraries/shared/src/Interpolate.cpp index bef69c9a33..b20c7b8fac 100644 --- a/libraries/shared/src/Interpolate.cpp +++ b/libraries/shared/src/Interpolate.cpp @@ -14,6 +14,8 @@ #include #include +#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); +} \ No newline at end of file diff --git a/libraries/shared/src/Interpolate.h b/libraries/shared/src/Interpolate.h index 316bee1339..a9fa5baad2 100644 --- a/libraries/shared/src/Interpolate.h +++ b/libraries/shared/src/Interpolate.h @@ -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 From 2eb0c7735f7a52bd1c6acb12fbd42ff4398028b9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Aug 2016 13:30:05 -0700 Subject: [PATCH 13/78] working on fading shape entities --- interface/src/avatar/Avatar.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 4 +-- interface/src/ui/overlays/Line3DOverlay.cpp | 4 +-- .../src/ui/overlays/Rectangle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 12 +++---- .../src/RenderableShapeEntityItem.h | 4 +-- .../src/RenderableTextEntityItem.cpp | 2 +- .../src/RenderableWebEntityItem.cpp | 5 +-- .../render-utils/src/DeferredBufferWrite.slh | 2 ++ libraries/render-utils/src/GeometryCache.cpp | 34 +++++++++++++------ libraries/render-utils/src/GeometryCache.h | 30 ++++++++-------- .../render-utils/src/simple_textured.slf | 28 ++++++++++----- tests/gpu-test/src/TestFloorTexture.cpp | 2 +- 16 files changed, 81 insertions(+), 56 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4d9481f002..018a9bb2fe 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -776,7 +776,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const { PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect"); - DependencyManager::get()->bindSimpleProgram(batch, false, true, true, true); + DependencyManager::get()->bindSimpleProgram(batch, false, false, true, true, true); DependencyManager::get()->renderBevelCornersRect(batch, left, bottom, width, height, bevelDistance, backgroundColor); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index f72fb8d920..a61e442436 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -47,7 +47,7 @@ void Cube3DOverlay::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); 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); diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index c9a8b19f6a..a05783fea2 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -57,12 +57,12 @@ void Line3DOverlay::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); 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); } } diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 75d7ec565c..35c479dce6 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -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); diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index cd07385aab..2556bc84aa 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -47,7 +47,7 @@ void Shape3DOverlay::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); auto pipeline = args->_pipeline; if (!pipeline) { - pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline(); + pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); } transform.setScale(dimensions); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index bbdd886d11..774237d334 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -46,7 +46,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); auto pipeline = args->_pipeline; if (!pipeline) { - pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline(); + pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); } if (_isSolid) { diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index c9c24d3ab6..769fab1acd 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -101,7 +101,7 @@ void Web3DOverlay::render(RenderArgs* args) { batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); - geometryCache->bindSimpleProgram(batch, true, false, true, false); + geometryCache->bindSimpleProgram(batch, true, false, false, true, false); geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color); batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 61e152f5ac..65c924080f 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -105,16 +105,12 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { DependencyManager::get()->renderShape(batch, MAPPING[_shape]); } else { // FIXME, support instanced multi-shape rendering using multidraw indirect - float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); - if (fadeRatio < 1.0f) { - color = glm::vec4(0.0f, 0.0f, 1.0f, 0.5f); - DependencyManager::get()->renderSolidShapeInstance(batch, MAPPING[_shape], color); - } else { - DependencyManager::get()->renderSolidShapeInstance(batch, MAPPING[_shape], color); - } + color.a *= Interpolate::calculateFadeRatio(_fadeStartTime); + auto geometryCache = DependencyManager::get(); + auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + geometryCache->renderSolidShapeInstance(batch, MAPPING[_shape], color, pipeline); } - static const auto triCount = DependencyManager::get()->getShapeTriangleCount(MAPPING[_shape]); args->_details._trianglesRendered += (int)triCount; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 7bfb411874..537052cdfd 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -22,7 +22,7 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties); - RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID), _fadeStartTime(usecTimestampNow()) {} + RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {} void render(RenderArgs* args) override; void setUserData(const QString& value) override; @@ -33,7 +33,7 @@ public: private: QSharedPointer _procedural; - quint64 _fadeStartTime { 0 }; + quint64 _fadeStartTime { usecTimestampNow() }; }; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 6773a906fe..7f2644a68e 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -62,7 +62,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { batch.setModelTransform(transformToTopLeft); - DependencyManager::get()->bindSimpleProgram(batch, false, false, false, true); + DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true); DependencyManager::get()->renderQuad(batch, minCorner, maxCorner, backgroundColor); float scale = _lineHeight / _textRenderer->getFontSize(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8298dbcec5..d86aa8e2f9 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -208,8 +208,9 @@ void RenderableWebEntityItem::render(RenderArgs* args) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); textured = emissive = true; } - - DependencyManager::get()->bindSimpleProgram(batch, textured, culled, emissive); + bool transparent = false; + + DependencyManager::get()->bindSimpleProgram(batch, textured, transparent, culled, emissive); DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)); } diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 3153a851fb..aa79781c25 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -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@> diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index cebd8ad37f..670881db80 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -397,14 +397,25 @@ 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(getSimplePipeline(), nullptr, + GeometryCache::_simpleOpaquePipeline = + std::make_shared(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()->getWhiteTexture()); + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, + DependencyManager::get()->getNormalFittingTexture()); + } + ); + GeometryCache::_simpleTransparentPipeline = + std::make_shared(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, @@ -1703,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, @@ -1712,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), @@ -1721,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); } @@ -1731,9 +1745,9 @@ public: int getRaw() const { return *reinterpret_cast(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); } @@ -1748,8 +1762,8 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { return a.getRaw() == b.getRaw(); } -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) { @@ -1761,8 +1775,8 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool cul DependencyManager::get()->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; @@ -1798,7 +1812,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); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index bab0942672..33fe8b1ef3 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -152,12 +152,13 @@ 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); - 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 @@ -165,42 +166,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); @@ -412,7 +413,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 _simplePrograms; diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index f045af2ce5..815d28310f 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -29,13 +29,23 @@ 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); + + if (_color.a * texel.a < 1.0) { + 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); + } } \ No newline at end of file diff --git a/tests/gpu-test/src/TestFloorTexture.cpp b/tests/gpu-test/src/TestFloorTexture.cpp index 884be5ec30..b7853fdbb4 100644 --- a/tests/gpu-test/src/TestFloorTexture.cpp +++ b/tests/gpu-test/src/TestFloorTexture.cpp @@ -78,7 +78,7 @@ void FloorTextureTest::renderTest(size_t testId, RenderArgs* args) { texture->incremementMinMip(); } - geometryCache->bindSimpleProgram(batch, true, true, true); + geometryCache->bindSimpleProgram(batch, true, false, true, true); batch.setInputBuffer(0, vertexBuffer, 0, sizeof(Vertex)); batch.setInputFormat(vertexFormat); batch.setIndexBuffer(gpu::UINT16, indexBuffer, 0); From 40a5e4abc892cb3ef0357cdc0b492a01327e40a4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 3 Aug 2016 13:54:25 -0700 Subject: [PATCH 14/78] in full-screen mirror camera mode, arrow keys move camera but don't make the avatar walk --- .../resources/controllers/keyboardMouse.json | 20 +++++++++++++--- interface/src/Application.cpp | 24 ++++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 0037e3741d..8baf56684a 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -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" }, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5d50a1c9fe..6fc294b8d7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -391,6 +391,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 +475,9 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - 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(); DependencyManager::set(); DependencyManager::set(); @@ -954,6 +961,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; }); From 27bacc9165152a5a8d161d378ccb806cbb13489a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Aug 2016 14:33:05 -0700 Subject: [PATCH 15/78] try to fade in procedural shapes --- .../src/RenderableShapeEntityItem.cpp | 9 ++++ .../src/RenderableShapeEntityItem.h | 2 +- .../procedural/src/procedural/Procedural.cpp | 1 + .../procedural/src/procedural/Procedural.h | 3 ++ libraries/render-utils/src/simple.slf | 42 ++++++++++++++++--- .../src/simple_textured_unlit.slf | 17 ++++++-- 6 files changed, 64 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 65c924080f..352777e958 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -71,6 +71,14 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } } +bool RenderableShapeEntityItem::isTransparent() { + if (_procedural && _procedural->ready()) { + return Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; + } else { + return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; + } +} + void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); @@ -101,6 +109,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation()); auto outColor = _procedural->getColor(color); + outColor.a *= Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()); batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); DependencyManager::get()->renderShape(batch, MAPPING[_shape]); } else { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 537052cdfd..716daf1d03 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -27,7 +27,7 @@ public: void render(RenderArgs* args) override; void setUserData(const QString& value) override; - bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } + bool isTransparent() override; SIMPLE_RENDERABLE(); diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 7dd729384c..1c7fcade18 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -184,6 +184,7 @@ bool Procedural::ready() { // Reset dirty flag after reading _proceduralData, but before releasing lock // to avoid resetting it after more data is set _proceduralDataDirty = false; + _fadeStartTime = usecTimestampNow(); } if (!_enabled) { diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 6991b47946..f8d0c963f4 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -42,6 +42,7 @@ public: const gpu::ShaderPointer& getShader() const { return _shader; } glm::vec4 getColor(const glm::vec4& entityColor); + quint64 getFadeStartTime() { return _fadeStartTime; } uint8_t _version { 1 }; @@ -106,6 +107,8 @@ private: void setupUniforms(); void setupChannels(bool shouldCreate); + + quint64 _fadeStartTime; }; #endif diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index dd5faf40db..fff91a9261 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -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); + if (_color.a < 1.0) { + if (emissiveAmount > 0.0) { + // TODO: transparent emissive? + packDeferredFragmentTranslucent( + normal, + _color.a, + diffuse, + 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); + } } } diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index cbfc7d7768..296f805902 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -29,8 +29,17 @@ void main(void) { texel = colorToLinearRGBA(texel); } - packDeferredFragmentUnlit( - normalize(_normal), - texel.a, - _color.rgb * texel.rgb); + if (_color.a * texel.a < 1.0) { + 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); + } } \ No newline at end of file From 7713c1f4bfb664cf9d3e322367e219fe049a24f8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Aug 2016 15:56:41 -0700 Subject: [PATCH 16/78] try to fade in web entities --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 2 +- .../entities-renderer/src/RenderablePolyLineEntityItem.h | 2 ++ .../entities-renderer/src/RenderableWebEntityItem.cpp | 8 ++++++-- libraries/entities-renderer/src/RenderableWebEntityItem.h | 5 +++++ libraries/render-utils/src/simple.slf | 3 ++- libraries/render-utils/src/simple_textured.slf | 3 ++- libraries/render-utils/src/simple_textured_unlit.slf | 3 ++- 7 files changed, 20 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index d49eacdf7b..bd34506250 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -19,7 +19,7 @@ namespace render { if (payload->entity->getType() == EntityTypes::Light) { return ItemKey::Builder::light(); } - if (payload && (payload->entity->getType() == EntityTypes::PolyLine || payload->entity->isTransparent())) { + if (payload && payload->entity->isTransparent()) { return ItemKey::Builder::transparentShape(); } } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index dfde97c407..46716e5bab 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -32,6 +32,8 @@ public: virtual void update(const quint64& now) override; virtual bool needsToCallUpdate() const override { return true; }; + bool isTransparent() override { return true; } + SIMPLE_RENDERABLE(); NetworkTexturePointer _texture; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index d86aa8e2f9..bb5cb7e2f8 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -181,6 +181,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { if (!buildWebSurface(static_cast(args->_renderer))) { return; } + _fadeStartTime = usecTimestampNow(); #endif } @@ -208,10 +209,13 @@ void RenderableWebEntityItem::render(RenderArgs* args) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); textured = emissive = true; } - bool transparent = false; + + float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); + bool transparent = fadeRatio < 1.0f; + batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); DependencyManager::get()->bindSimpleProgram(batch, textured, transparent, culled, emissive); - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); } void RenderableWebEntityItem::setSourceUrl(const QString& value) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 4125be61dd..049575ec95 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -12,6 +12,7 @@ #include #include +#include #include "RenderableEntityItem.h" @@ -35,6 +36,8 @@ public: void update(const quint64& now) override; bool needsToCallUpdate() const override { return _webSurface != nullptr; } + bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } + SIMPLE_RENDERABLE(); private: @@ -53,6 +56,8 @@ private: QMetaObject::Connection _mouseReleaseConnection; QMetaObject::Connection _mouseMoveConnection; QMetaObject::Connection _hoverLeaveConnection; + + quint64 _fadeStartTime; }; diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index fff91a9261..85d85b3db7 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -49,7 +49,8 @@ void main(void) { #endif - if (_color.a < 1.0) { + const float ALPHA_THRESHOLD = 0.999; + if (_color.a < ALPHA_THRESHOLD) { if (emissiveAmount > 0.0) { // TODO: transparent emissive? packDeferredFragmentTranslucent( diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 815d28310f..6067c81a1b 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -30,7 +30,8 @@ void main(void) { texel = colorToLinearRGBA(texel); } - if (_color.a * texel.a < 1.0) { + const float ALPHA_THRESHOLD = 0.999; + if (_color.a * texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normal), _color.a * texel.a, diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index 296f805902..4f02140825 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -29,7 +29,8 @@ void main(void) { texel = colorToLinearRGBA(texel); } - if (_color.a * texel.a < 1.0) { + const float ALPHA_THRESHOLD = 0.999; + if (_color.a * texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normal), _color.a * texel.a, From d7052f6250ec5f825b8656e4e3650f988b49b355 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Aug 2016 16:27:51 -0700 Subject: [PATCH 17/78] try to make text entities fade --- .../entities-renderer/src/RenderableTextEntityItem.cpp | 10 +++++----- .../entities-renderer/src/RenderableTextEntityItem.h | 4 ++++ libraries/render-utils/src/sdf_text3D.slf | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 7f2644a68e..11c5f21a59 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -15,8 +15,6 @@ #include #include - - #include "RenderableTextEntityItem.h" #include "GLMHelpers.h" @@ -31,8 +29,10 @@ void RenderableTextEntityItem::render(RenderArgs* args) { Q_ASSERT(getType() == EntityTypes::Text); 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 = Interpolate::calculateFadeRatio(_fadeStartTime); + 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 +62,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { batch.setModelTransform(transformToTopLeft); - DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true); + DependencyManager::get()->bindSimpleProgram(batch, false, transparent, false, false, true); DependencyManager::get()->renderQuad(batch, minCorner, maxCorner, backgroundColor); float scale = _lineHeight / _textRenderer->getFontSize(); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index cbe2b11c27..e0ddcad266 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -14,6 +14,7 @@ #include #include +#include #include "RenderableEntityItem.h" @@ -27,10 +28,13 @@ public: virtual void render(RenderArgs* args) override; + bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } + SIMPLE_RENDERABLE(); private: TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f); + quint64 _fadeStartTime { usecTimestampNow() }; }; diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index f5385c23b7..f578895c85 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -48,7 +48,7 @@ void main() { packDeferredFragmentTranslucent( normalize(_normal), - a, + a * Color.a, Color.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); From d521315475587075d7cd9b146ccfbd0d499aefb4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 3 Aug 2016 17:03:52 -0700 Subject: [PATCH 18/78] fade polylines (needs testing) --- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 2 ++ .../entities-renderer/src/RenderablePolyLineEntityItem.h | 7 ++++--- libraries/entities-renderer/src/paintStroke.slf | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 600b876d39..54a6edadd4 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -204,5 +204,7 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); + batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); + batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); }; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 46716e5bab..6d3dab4647 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -18,6 +18,7 @@ #include #include "RenderableEntityItem.h" #include +#include #include @@ -30,9 +31,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; } + bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } SIMPLE_RENDERABLE(); @@ -49,7 +50,7 @@ protected: gpu::BufferView _uniformBuffer; unsigned int _numVertices; QVector _vertices; - + quint64 _fadeStartTime { usecTimestampNow() }; }; diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 9b7193bbfc..bfbe6d7e5a 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -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); From 6604c27f232f61a842cc78ccf775a81cf858e200 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 4 Aug 2016 10:55:37 -0700 Subject: [PATCH 19/78] polyvox fade WIP --- .../src/RenderableEntityItem.cpp | 2 +- .../src/RenderablePolyLineEntityItem.h | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 6 +++++ .../src/RenderablePolyVoxEntityItem.h | 2 ++ libraries/entities-renderer/src/polyvox.slf | 23 +++++++++++++++++-- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index bd34506250..359b050803 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -1,4 +1,4 @@ - // +// // RenderableEntityItem.cpp // interface/src // diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 6d3dab4647..c06f4a721a 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -33,7 +33,7 @@ public: virtual void update(const quint64& now) override; virtual bool needsToCallUpdate() const override { return true; } - bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } + bool isTransparent() override { return true; } SIMPLE_RENDERABLE(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index eb6db2874f..769670b99c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -596,6 +596,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); + 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); _pipeline = gpu::Pipeline::create(program, state); } @@ -642,6 +645,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { int voxelVolumeSizeLocation = _pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z); + int alphaLocation = _pipeline->getProgram()->getUniforms().findLocation("alpha"); + batch._glUniform1f(alphaLocation, 0.5f); + batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)mesh->getNumIndices(), 0); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index c46a26deb5..cec6ddf7c5 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -131,6 +131,8 @@ public: void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; }); } + bool isTransparent() override { return true; } + private: // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index b7682913a7..a3c8315b62 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -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 @@ -23,6 +23,7 @@ uniform sampler2D xMap; uniform sampler2D yMap; uniform sampler2D zMap; uniform vec3 voxelVolumeSize; +uniform float alpha; void main(void) { vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); @@ -41,5 +42,23 @@ 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); + const float ALPHA_THRESHOLD = 0.999; + if (alpha < ALPHA_THRESHOLD) { + packDeferredFragmentTranslucent( + _normal, + alpha, + vec3(diffuse), + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } else { + packDeferredFragment( + _normal, + 1.0, + vec3(diffuse), + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + } } From ac9a80131a6780e5c223a970357e146bab90b7a2 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 4 Aug 2016 12:34:46 -0700 Subject: [PATCH 20/78] refactoring _fadeStartTime and isTransparent, make simple renderables switch to transparent when fade finishes --- libraries/entities-renderer/src/RenderableEntityItem.h | 10 +++++++++- .../entities-renderer/src/RenderableModelEntityItem.h | 3 +++ .../src/RenderablePolyLineEntityItem.cpp | 2 ++ .../src/RenderablePolyLineEntityItem.h | 2 -- .../src/RenderableShapeEntityItem.cpp | 7 ++++--- .../entities-renderer/src/RenderableShapeEntityItem.h | 6 ++---- .../entities-renderer/src/RenderableTextEntityItem.cpp | 1 + .../entities-renderer/src/RenderableTextEntityItem.h | 4 ---- .../entities-renderer/src/RenderableWebEntityItem.cpp | 2 ++ .../entities-renderer/src/RenderableWebEntityItem.h | 5 ----- libraries/entities/src/EntityItem.h | 5 +++-- 11 files changed, 26 insertions(+), 21 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 9840bf3150..09d6d88c6a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -96,8 +96,16 @@ public: \ virtual void removeFromScene(EntityItemPointer self, std::shared_ptr 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 checkTransparency() { \ + bool transparent = isTransparent(); \ + if (transparent != prevIsTransparent) { \ + _renderHelper.notifyChanged(); \ + prevIsTransparent = transparent; \ + } \ + } \ private: \ - SimpleRenderableEntityItem _renderHelper; + SimpleRenderableEntityItem _renderHelper; \ + bool prevIsTransparent { isTransparent() }; #endif // hifi_RenderableEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 339c907532..c50dcde62c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -91,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(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 54a6edadd4..ef4c9d6b5d 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -167,6 +167,8 @@ void RenderablePolyLineEntityItem::update(const quint64& now) { } void RenderablePolyLineEntityItem::render(RenderArgs* args) { + checkTransparency(); + QWriteLocker lock(&_quadReadWriteLock); if (_points.size() < 2 || _normals.size () < 2 || _strokeWidths.size() < 2) { return; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index c06f4a721a..75b2bcd58a 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -18,7 +18,6 @@ #include #include "RenderableEntityItem.h" #include -#include #include @@ -50,7 +49,6 @@ protected: gpu::BufferView _uniformBuffer; unsigned int _numVertices; QVector _vertices; - quint64 _fadeStartTime { usecTimestampNow() }; }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 352777e958..5bfd669a7c 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -71,18 +71,19 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } } -bool RenderableShapeEntityItem::isTransparent() { +/*bool RenderableShapeEntityItem::isTransparent() { if (_procedural && _procedural->ready()) { return Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; } else { - return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; + return EntityItem::isTransparent(); } -} +}*/ void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); Q_ASSERT(args->_batch); + checkTransparency(); if (!_procedural) { _procedural.reset(new Procedural(getUserData())); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 716daf1d03..68b36f7e45 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -11,7 +11,6 @@ #include #include -#include #include "RenderableEntityItem.h" @@ -22,18 +21,17 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties); - RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {} + RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) { _procedural.reset(nullptr); } void render(RenderArgs* args) override; void setUserData(const QString& value) override; - bool isTransparent() override; +// bool isTransparent() override; SIMPLE_RENDERABLE(); private: QSharedPointer _procedural; - quint64 _fadeStartTime { usecTimestampNow() }; }; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 11c5f21a59..ccdaa39bdd 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -27,6 +27,7 @@ EntityItemPointer RenderableTextEntityItem::factory(const EntityItemID& entityID void RenderableTextEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Text); + checkTransparency(); static const float SLIGHTLY_BEHIND = -0.005f; float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index e0ddcad266..cbe2b11c27 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -14,7 +14,6 @@ #include #include -#include #include "RenderableEntityItem.h" @@ -28,13 +27,10 @@ public: virtual void render(RenderArgs* args) override; - bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } - SIMPLE_RENDERABLE(); private: TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f); - quint64 _fadeStartTime { usecTimestampNow() }; }; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index bb5cb7e2f8..19388a28e4 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -164,6 +164,8 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { } void RenderableWebEntityItem::render(RenderArgs* args) { + checkTransparency(); + #ifdef WANT_EXTRA_DEBUGGING { gpu::Batch& batch = *args->_batch; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 049575ec95..4125be61dd 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -12,7 +12,6 @@ #include #include -#include #include "RenderableEntityItem.h" @@ -36,8 +35,6 @@ public: void update(const quint64& now) override; bool needsToCallUpdate() const override { return _webSurface != nullptr; } - bool isTransparent() override { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } - SIMPLE_RENDERABLE(); private: @@ -56,8 +53,6 @@ private: QMetaObject::Connection _mouseReleaseConnection; QMetaObject::Connection _mouseMoveConnection; QMetaObject::Connection _hoverLeaveConnection; - - quint64 _fadeStartTime; }; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index f1715a2525..198928da4e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "EntityItemID.h" #include "EntityItemPropertiesDefaults.h" @@ -435,7 +436,7 @@ public: QUuid getOwningAvatarID() const { return _owningAvatarID; } void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; } - virtual bool isTransparent() { return false; } + virtual bool isTransparent() { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } protected: @@ -566,7 +567,7 @@ protected: quint64 _lastUpdatedAngularVelocityTimestamp { 0 }; quint64 _lastUpdatedAccelerationTimestamp { 0 }; - + quint64 _fadeStartTime { usecTimestampNow() }; }; #endif // hifi_EntityItem_h From 004b0158a4683248f8c05c8fc470571cf0260425 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 4 Aug 2016 13:09:09 -0700 Subject: [PATCH 21/78] fix warnings on osx --- .../src/RenderablePolyVoxEntityItem.h | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index cec6ddf7c5..615451180a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -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 scene, - render::PendingChanges& pendingChanges); + render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr 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, @@ -163,7 +163,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 From 3107d63ad8db677c70afc23c9f8c91883ac380a0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 4 Aug 2016 14:31:44 -0700 Subject: [PATCH 22/78] one more warning --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 9cd55b7a75..b1370e72a7 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -211,7 +211,6 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); - bool transparent = fadeRatio < 1.0f; batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); DependencyManager::get()->bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(batch); From 8044910bf2bd8b35770cfc2872c5b5595089e31f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 14:39:53 -0700 Subject: [PATCH 23/78] Add show-address-bar when disconnected from domain --- interface/src/Application.cpp | 1 + interface/src/Application.h | 4 ++ interface/src/ConnectionMonitor.cpp | 58 +++++++++++++++++++++++++++++ interface/src/ConnectionMonitor.h | 34 +++++++++++++++++ interface/src/ui/DialogsManager.cpp | 4 ++ interface/src/ui/DialogsManager.h | 1 + 6 files changed, 102 insertions(+) create mode 100644 interface/src/ConnectionMonitor.cpp create mode 100644 interface/src/ConnectionMonitor.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5d50a1c9fe..544458f9b8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -811,6 +811,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : } UserActivityLogger::getInstance().logAction("launch", properties); + _connectionMonitor.init(); // Tell our entity edit sender about our known jurisdictions _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0af65f665f..c81d56e0aa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -47,6 +47,7 @@ #include "avatar/MyAvatar.h" #include "Bookmarks.h" #include "Camera.h" +#include "ConnectionMonitor.h" #include "FileLogger.h" #include "gpu/Context.h" #include "Menu.h" @@ -562,6 +563,9 @@ private: bool _recentlyClearedDomain { false }; QString _returnFromFullScreenMirrorTo; + + ConnectionMonitor _connectionMonitor; }; + #endif // hifi_Application_h diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp new file mode 100644 index 0000000000..462efc1bf9 --- /dev/null +++ b/interface/src/ConnectionMonitor.cpp @@ -0,0 +1,58 @@ +// +// ConnectionMonitor.cpp +// interface/src +// +// Created by Ryan Huffman on 8/4/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 +// + +#include "ConnectionMonitor.h" + +#include "ui/DialogsManager.h" + +#include +#include +#include +#include + +static const int DISPLAY_AFTER_DISCONNECTED_FOR_X_MS = 5000; + +void ConnectionMonitor::init() { + // Connect to domain disconnected message + auto nodeList = DependencyManager::get(); + const DomainHandler& domainHandler = nodeList->getDomainHandler(); + connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &ConnectionMonitor::disconnectedFromDomain); + connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::connectedToDomain); + + // Connect to AddressManager::hostChanged + auto addressManager = DependencyManager::get(); + connect(addressManager.data(), &AddressManager::hostChanged, this, &ConnectionMonitor::hostChanged); + + _timer.setSingleShot(true); + _timer.setInterval(DISPLAY_AFTER_DISCONNECTED_FOR_X_MS); + _timer.start(); + + connect(&_timer, &QTimer::timeout, this, []() { + qDebug() << "CM: Showing address bar!"; + DependencyManager::get()->showAddressBar(); + }); +} + +void ConnectionMonitor::disconnectedFromDomain() { + qDebug() << "CM: DISCONNECTED FROM DOMAIN!"; + _timer.start(); +} + +void ConnectionMonitor::connectedToDomain(const QString& name) { + qDebug() << "CM: CONNECTED FROM DOMAIN! - " << name; + _timer.stop(); +} + +void ConnectionMonitor::hostChanged(const QString& name) { + qDebug() << "CM: host changed: " << name; + _timer.start(); + +} diff --git a/interface/src/ConnectionMonitor.h b/interface/src/ConnectionMonitor.h new file mode 100644 index 0000000000..bba420715e --- /dev/null +++ b/interface/src/ConnectionMonitor.h @@ -0,0 +1,34 @@ +// +// ConnectionMonitor.h +// interface/src +// +// Created by Ryan Huffman on 8/4/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 +// + +#ifndef hifi_ConnectionMonitor_h +#define hifi_ConnectionMonitor_h + +#include +#include + +class QString; + +class ConnectionMonitor : public QObject { + Q_OBJECT +public: + void init(); + +private slots: + void disconnectedFromDomain(); + void connectedToDomain(const QString& name); + void hostChanged(const QString& name); + +private: + QTimer _timer; +}; + +#endif // hifi_ConnectionMonitor_h \ No newline at end of file diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 2f826146ae..dc06c50626 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -50,6 +50,10 @@ void DialogsManager::toggleAddressBar() { emit addressBarToggled(); } +void DialogsManager::showAddressBar() { + AddressBarDialog::show(); +} + void DialogsManager::toggleDiskCacheEditor() { maybeCreateDialog(_diskCacheEditor); _diskCacheEditor->toggle(); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index c48c6df0e6..5b4995029f 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -44,6 +44,7 @@ public: public slots: void toggleAddressBar(); + void showAddressBar(); void toggleDiskCacheEditor(); void toggleLoginDialog(); void showLoginDialog(); From a37bcdafdaa9ebd5c5cab24041088a29ed8046a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 14:40:41 -0700 Subject: [PATCH 24/78] Remove debug logging in ConnectionMonitor --- interface/src/ConnectionMonitor.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index 462efc1bf9..be1ffb41e8 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -42,17 +42,13 @@ void ConnectionMonitor::init() { } void ConnectionMonitor::disconnectedFromDomain() { - qDebug() << "CM: DISCONNECTED FROM DOMAIN!"; _timer.start(); } void ConnectionMonitor::connectedToDomain(const QString& name) { - qDebug() << "CM: CONNECTED FROM DOMAIN! - " << name; _timer.stop(); } void ConnectionMonitor::hostChanged(const QString& name) { - qDebug() << "CM: host changed: " << name; _timer.start(); - } From d775a92dabf9f0e6b530f1abbf6d0fdd61dc035d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 14:45:10 -0700 Subject: [PATCH 25/78] Update implementation of ConnectionMonitor timeout --- interface/src/ConnectionMonitor.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index be1ffb41e8..1956ace67b 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -35,10 +35,8 @@ void ConnectionMonitor::init() { _timer.setInterval(DISPLAY_AFTER_DISCONNECTED_FOR_X_MS); _timer.start(); - connect(&_timer, &QTimer::timeout, this, []() { - qDebug() << "CM: Showing address bar!"; - DependencyManager::get()->showAddressBar(); - }); + auto dialogsManager = DependencyManager::get(); + connect(&_timer, &QTimer::timeout, dialogsManager.data(), &DialogsManager::showAddressBar); } void ConnectionMonitor::disconnectedFromDomain() { From 83280aa3f265abd320125e3cb1d07ef0e36a4c1f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 5 Aug 2016 09:42:57 -0700 Subject: [PATCH 26/78] implement support for updating the render items of models when they finish their fade --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 6 ++++++ libraries/render-utils/src/MeshPartPayload.cpp | 7 +++++++ libraries/render-utils/src/MeshPartPayload.h | 4 ++++ libraries/render-utils/src/Model.cpp | 1 + libraries/render-utils/src/Model.h | 4 ++++ 5 files changed, 22 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 564a58708f..6c4cbe7a87 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -371,6 +371,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 { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index fe914f4d1a..3b78023496 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -526,6 +526,13 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { 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 + if (_wasFading && !isStillFading()) { + _model->setRenderItemsNeedUpdate(); + } + _wasFading = isStillFading(); + gpu::Batch& batch = *(args->_batch); if (!getShapeKey().isValid()) { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 54878f3352..c2305f3741 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -12,6 +12,8 @@ #ifndef hifi_MeshPartPayload_h #define hifi_MeshPartPayload_h +#include + #include #include @@ -85,6 +87,7 @@ public: void startFade() { _fadeStartTime = usecTimestampNow(); } bool hasStartedFade() { return _hasStartedFade; } void setHasStartedFade(bool hasStartedFade) { _hasStartedFade = hasStartedFade; } + bool isStillFading() const { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } // Render Item interface render::ItemKey getKey() const override; @@ -108,6 +111,7 @@ public: private: quint64 _fadeStartTime { 0 }; bool _hasStartedFade { false }; + mutable bool _wasFading { false }; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 2140f2a803..d41a518974 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -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. diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index b95c0318b4..afaf5600ee 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -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(); @@ -396,6 +398,8 @@ protected: bool _geometryRequestFailed { false }; + bool _renderItemsNeedUpdate { false }; + private slots: void handleGeometryResourceFailure() { _geometryRequestFailed = true; } }; From 130e64aabae475db0b917753bfa9ca066ba4a227 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 5 Aug 2016 10:36:48 -0700 Subject: [PATCH 27/78] remove polyvox fade, possibly fix web fade --- .../src/RenderablePolyVoxEntityItem.cpp | 6 ---- .../src/RenderablePolyVoxEntityItem.h | 3 +- libraries/entities-renderer/src/polyvox.slf | 29 ++++++------------- libraries/render-utils/src/GeometryCache.cpp | 2 +- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 769670b99c..eb6db2874f 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -596,9 +596,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); - 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); _pipeline = gpu::Pipeline::create(program, state); } @@ -645,9 +642,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { int voxelVolumeSizeLocation = _pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z); - int alphaLocation = _pipeline->getProgram()->getUniforms().findLocation("alpha"); - batch._glUniform1f(alphaLocation, 0.5f); - batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)mesh->getNumIndices(), 0); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 615451180a..44186073b2 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -131,7 +131,8 @@ public: void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; }); } - bool isTransparent() override { return 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 diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index a3c8315b62..bebefa9434 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -23,7 +23,6 @@ uniform sampler2D xMap; uniform sampler2D yMap; uniform sampler2D zMap; uniform vec3 voxelVolumeSize; -uniform float alpha; void main(void) { vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); @@ -42,23 +41,13 @@ void main(void) { vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); - const float ALPHA_THRESHOLD = 0.999; - if (alpha < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - _normal, - alpha, - vec3(diffuse), - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } else { - 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); } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 443421f8b8..dcd36946cb 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1785,7 +1785,7 @@ gpu::PipelinePointer GeometryCache::getSimpleSRGBTexturedUnlitNoTexAlphaPipeline auto state = std::make_shared(); 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); From b13edc7b6adde15e8f917529290881b96fb54835 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 5 Aug 2016 10:48:09 -0700 Subject: [PATCH 28/78] fixed web fade fo' real --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index b1370e72a7..d6c1c1f761 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -214,7 +214,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); DependencyManager::get()->bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(batch); - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio)); } void RenderableWebEntityItem::setSourceUrl(const QString& value) { From f2ee57f2de8b26a9b8848797be3cfff144057e64 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 5 Aug 2016 11:17:02 -0700 Subject: [PATCH 29/78] light fade --- libraries/entities-renderer/src/RenderableLightEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index fb6061e94f..fccd52d58c 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -35,7 +35,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { glm::vec3 color = toGlm(getXColor()); - float intensity = getIntensity(); + float intensity = getIntensity() * Interpolate::calculateFadeRatio(_fadeStartTime); float falloffRadius = getFalloffRadius(); float exponent = getExponent(); float cutoff = glm::radians(getCutoff()); From 84944000476ac3722faec4b05456dd69f4fd40eb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 5 Aug 2016 11:27:56 -0700 Subject: [PATCH 30/78] don't use web entity texel color alpha as per tony's suggestion --- .../src/simple_srgb_textured_unlit_no_tex_alpha.slf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/simple_srgb_textured_unlit_no_tex_alpha.slf b/libraries/render-utils/src/simple_srgb_textured_unlit_no_tex_alpha.slf index 6f8e1d7eb8..38b7e1002c 100644 --- a/libraries/render-utils/src/simple_srgb_textured_unlit_no_tex_alpha.slf +++ b/libraries/render-utils/src/simple_srgb_textured_unlit_no_tex_alpha.slf @@ -28,10 +28,10 @@ void main(void) { texel = colorToLinearRGBA(texel); const float ALPHA_THRESHOLD = 0.999; - if (_color.a * texel.a < ALPHA_THRESHOLD) { + if (_color.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normal), - _color.a * texel.a, + _color.a, _color.rgb * texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); From b794259b7dc59ba829771654c995b8703688f565 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 5 Aug 2016 16:15:10 -0700 Subject: [PATCH 31/78] fixed procedural entity fade --- .../src/RenderableShapeEntityItem.cpp | 6 +++--- .../entities-renderer/src/RenderableShapeEntityItem.h | 10 +++++----- libraries/procedural/src/procedural/Procedural.cpp | 8 +++++++- libraries/procedural/src/procedural/Procedural.h | 1 + libraries/render-utils/src/simple.slf | 3 +-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 5bfd669a7c..42b63ee2c2 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -71,13 +71,13 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } } -/*bool RenderableShapeEntityItem::isTransparent() { +bool RenderableShapeEntityItem::isTransparent() { if (_procedural && _procedural->ready()) { return Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; } else { return EntityItem::isTransparent(); } -}*/ +} void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); @@ -91,7 +91,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { _procedural->_fragmentSource = simple_frag; _procedural->_state->setCullMode(gpu::State::CULL_NONE); _procedural->_state->setDepthTest(true, true, gpu::LESS_EQUAL); - _procedural->_state->setBlendFunction(false, + _procedural->_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); } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 68b36f7e45..7eefe0e7a4 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -21,17 +21,17 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties); - RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) { _procedural.reset(nullptr); } + RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {} void render(RenderArgs* args) override; void setUserData(const QString& value) override; -// bool isTransparent() override; - - SIMPLE_RENDERABLE(); + bool isTransparent() override; private: - QSharedPointer _procedural; + std::unique_ptr _procedural { nullptr }; + + SIMPLE_RENDERABLE(); }; diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 1c7fcade18..7f8ab2db41 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -175,6 +175,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) { @@ -184,7 +188,6 @@ bool Procedural::ready() { // Reset dirty flag after reading _proceduralData, but before releasing lock // to avoid resetting it after more data is set _proceduralDataDirty = false; - _fadeStartTime = usecTimestampNow(); } if (!_enabled) { @@ -203,6 +206,9 @@ bool Procedural::ready() { } } + if (!_hasStartedFade) { + _hasStartedFade = true; + } return true; } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index f8d0c963f4..dea55f197b 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -109,6 +109,7 @@ private: void setupChannels(bool shouldCreate); quint64 _fadeStartTime; + bool _hasStartedFade { false }; }; #endif diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 85d85b3db7..228560f394 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -52,11 +52,10 @@ void main(void) { const float ALPHA_THRESHOLD = 0.999; if (_color.a < ALPHA_THRESHOLD) { if (emissiveAmount > 0.0) { - // TODO: transparent emissive? packDeferredFragmentTranslucent( normal, _color.a, - diffuse, + specular, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { From b23d3cd35ab833ae3b407ed86bf711475c628a74 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 5 Aug 2016 18:35:16 -0700 Subject: [PATCH 32/78] fixed messed up transparency on edit selection of shapes --- libraries/entities-renderer/src/RenderableShapeEntityItem.cpp | 2 +- scripts/system/libraries/entitySelectionTool.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 42b63ee2c2..f557625db2 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -75,7 +75,7 @@ bool RenderableShapeEntityItem::isTransparent() { if (_procedural && _procedural->ready()) { return Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; } else { - return EntityItem::isTransparent(); + return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent(); } } diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 2003df3652..461204b7aa 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1109,9 +1109,6 @@ SelectionDisplay = (function() { } - Entities.editEntity(entityID, { - localRenderAlpha: 0.1 - }); Overlays.editOverlay(highlightBox, { visible: false }); From 38b53143228d8d350a42350523527e6f34e5521f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 6 Aug 2016 17:53:59 +1200 Subject: [PATCH 33/78] Disable Asset Browser's right-click popup menu if in HMD mode --- interface/resources/qml/AssetServer.qml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 1ad2d1a1e4..050bc8e99e 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -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 From 4f2c00af46158387212c129b06951992835ecade Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 5 Aug 2016 23:38:45 -0700 Subject: [PATCH 34/78] faster TextureUsage::process2DImageColor() --- libraries/model/src/model/TextureMap.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 3e6016d7c0..6d96932e91 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -59,29 +59,27 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val const uint8 OPAQUE_ALPHA = 255; const uint8 TRANSPARENT_ALPHA = 0; if (image.hasAlphaChannel()) { - std::map 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) { + // Count the opaque and transparent pixels + int numOpaques = 0; + int numTransparents = 0; + int height = image.height(); + int width = image.width(); + for (int y = 0; y < height; ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); - for (int x = 0; x < image.width(); ++x) { + for (int x = 0; x < width; ++x) { auto alpha = qAlpha(data[x]); - alphaHistogram[alpha] ++; - validAlpha = validAlpha || (alpha != OPAQUE_ALPHA); + numOpaques += (int)(alpha == OPAQUE_ALPHA); + numTransparents += (int)(alpha == TRANSPARENT_ALPHA); } } // 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 totalNumPixels = height * width; + if (numOpaques != totalNumPixels) { auto numTranslucents = totalNumPixels - numOpaques - numTransparents; - alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); } } From f759fd10330292982ae1ca342d4262d49bd2a176 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sun, 7 Aug 2016 08:54:20 -0700 Subject: [PATCH 35/78] early exit when determining if alpha mask possible also don't bother scanning for alpha for cube maps --- libraries/model/src/model/TextureMap.cpp | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 6d96932e91..cceaaf6541 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -62,26 +62,27 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } - // Count the opaque and transparent pixels + + // Figure out if we can use a mask for alpha or not int numOpaques = 0; int numTransparents = 0; int height = image.height(); int width = image.width(); + const int MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(width * height)); for (int y = 0; y < height; ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); for (int x = 0; x < width; ++x) { auto alpha = qAlpha(data[x]); numOpaques += (int)(alpha == OPAQUE_ALPHA); - numTransparents += (int)(alpha == TRANSPARENT_ALPHA); + if (alpha == TRANSPARENT_ALPHA) { + if (++numTransparents > MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK) { + alphaAsMask = false; + break; + } + } } } - - // If alpha was meaningfull refine - auto totalNumPixels = height * width; - if (numOpaques != totalNumPixels) { - auto numTranslucents = totalNumPixels - numOpaques - numTransparents; - alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); - } + validAlpha = (numOpaques != width * height); } if (!validAlpha && image.format() != QImage::Format_RGB888) { @@ -658,13 +659,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; @@ -672,7 +672,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 faces; // If found, go extract the faces as separate images if (foundLayout >= 0) { From 4e23ecfb2cd6d1ce70cb266d76e7c814f518f945 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sun, 7 Aug 2016 10:50:25 -0700 Subject: [PATCH 36/78] count the _translucent_ pixels and fix break logic --- libraries/model/src/model/TextureMap.cpp | 28 +++++++++++------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index cceaaf6541..bbf411b109 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -65,24 +65,22 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val // Figure out if we can use a mask for alpha or not int numOpaques = 0; - int numTransparents = 0; - int height = image.height(); - int width = image.width(); - const int MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(width * height)); - for (int y = 0; y < height; ++y) { - const QRgb* data = reinterpret_cast(image.constScanLine(y)); - for (int x = 0; x < width; ++x) { - auto alpha = qAlpha(data[x]); - numOpaques += (int)(alpha == OPAQUE_ALPHA); - if (alpha == TRANSPARENT_ALPHA) { - if (++numTransparents > MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK) { - alphaAsMask = false; - break; - } + 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(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; } } } - validAlpha = (numOpaques != width * height); + validAlpha = (numOpaques != NUM_PIXELS); } if (!validAlpha && image.format() != QImage::Format_RGB888) { From f8c1d8f1238aba3da9af63dfefeab140a3b19760 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 8 Aug 2016 11:01:03 -0700 Subject: [PATCH 37/78] change property order and cleanup --- scripts/system/html/entityProperties.html | 63 ++++++++++++----------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index f2ade39144..5240b3da13 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -1389,23 +1389,13 @@ M
- +
-
-
-
+
+
+
-
- -
- - - -
-
- -
@@ -1414,19 +1404,28 @@
- -
- +
-
-
-
+
+
+
-
- - - +
+
+ +
+
+
+
+
+
+
+ +
+ + +
@@ -1439,15 +1438,17 @@
-
- -
-
-
-
+
+
+
+
+
+ + +
+
-
From f31190798226bccb793d95aa02ee90e39e608da5 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 8 Aug 2016 11:08:01 -0700 Subject: [PATCH 38/78] fix merge mistake --- libraries/render-utils/src/Model.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 785977e5f1..52cfdc67cf 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -407,12 +407,8 @@ protected: bool _visualGeometryRequestFailed { false }; bool _collisionGeometryRequestFailed { false }; - bool _geometryRequestFailed { false }; bool _renderItemsNeedUpdate { false }; - -private slots: - void handleGeometryResourceFailure() { _geometryRequestFailed = true; } }; Q_DECLARE_METATYPE(ModelPointer) From bde46adee8ec7e1e014a8cc6ac82acc61d35332d Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 8 Aug 2016 11:31:43 -0700 Subject: [PATCH 39/78] update description --- scripts/system/html/entityProperties.html | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 5240b3da13..424795981d 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -440,10 +440,11 @@ var elWebSections = document.querySelectorAll(".web-section"); allSections.push(elWebSections); var elWebSourceURL = document.getElementById("property-web-source-url"); - + + var elDescription = document.getElementById("property-description"); var elHyperlinkHref = document.getElementById("property-hyperlink-href"); - var elHyperlinkDescription = document.getElementById("property-hyperlink-description"); + var elHyperlinkSections = document.querySelectorAll(".hyperlink-section"); @@ -651,7 +652,7 @@ setTextareaScrolling(elUserData); elHyperlinkHref.value = properties.href; - elHyperlinkDescription.value = properties.description; + elDescription.value = properties.description; for (var i = 0; i < allSections.length; i++) { for (var j = 0; j < allSections[i].length; j++) { @@ -818,7 +819,7 @@ elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked')); elName.addEventListener('change', createEmitTextPropertyUpdateFunction('name')); elHyperlinkHref.addEventListener('change', createEmitTextPropertyUpdateFunction('href')); - elHyperlinkDescription.addEventListener('change', createEmitTextPropertyUpdateFunction('description')); + elDescription.addEventListener('change', createEmitTextPropertyUpdateFunction('description')); elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible')); var positionChangeFunction = createEmitVec3PropertyUpdateFunction( @@ -1363,6 +1364,10 @@
+
+ + +
@@ -1379,10 +1384,7 @@
- +
From 28b3ff9bcac97d81f43def3992583597ac361268 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 12:04:06 -0700 Subject: [PATCH 40/78] Update generation of srgb to linear lookup to include python script --- libraries/shared/src/ColorUtils.h | 49 +++++++++++++++++++++++++++++-- tools/srgb_gen.py | 22 ++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tools/srgb_gen.py diff --git a/libraries/shared/src/ColorUtils.h b/libraries/shared/src/ColorUtils.h index 42d36ebd4b..e7b4a1e5c2 100644 --- a/libraries/shared/src/ColorUtils.h +++ b/libraries/shared/src/ColorUtils.h @@ -17,8 +17,53 @@ #include "DependencyManager.h" -static 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.00251584218443f, 0.00279619194822f, 0.00309396642819f, 0.00340946205345f, 0.00374296799396f, 0.00409476661624f, 0.00446513389425f, 0.00485433978143f, 0.00526264854875f, 0.00569031909303f, 0.00613760521883f, 0.00660475589722f, 0.00709201550367f, 0.00759962403765f, 0.00812781732551f, 0.00867682720861f, 0.00924688171802f, 0.00983820523704f, 0.0104510186528f, 0.0110855394981f, 0.0117419820834f, 0.0124205576216f, 0.0131214743443f, 0.0138449376117f, 0.0145911500156f, 0.0153603114768f, 0.0161526193372f, 0.0169682684465f, 0.0178074512441f, 0.0186703578377f, 0.0195571760767f, 0.0204680916222f, 0.0214032880141f, 0.0223629467344f, 0.0233472472675f, 0.0243563671578f, 0.0253904820647f, 0.026449765815f, 0.0275343904531f, 0.0286445262888f, 0.0297803419432f, 0.0309420043928f, 0.0321296790111f, 0.0333435296099f, 0.0345837184768f, 0.0358504064137f, 0.0371437527716f, 0.0384639154854f, 0.0398110511069f, 0.0411853148367f, 0.0425868605546f, 0.0440158408496f, 0.045472407048f, 0.046956709241f, 0.0484688963113f, 0.0500091159586f, 0.0515775147244f, 0.0531742380159f, 0.0547994301291f, 0.0564532342711f, 0.058135792582f, 0.0598472461555f, 0.0615877350593f, 0.063357398355f, 0.0651563741167f, 0.0669847994499f, 0.0688428105093f, 0.0707305425158f, 0.0726481297741f, 0.0745957056885f, 0.0765734027789f, 0.0785813526965f, 0.0806196862387f, 0.0826885333636f, 0.0847880232044f, 0.086918284083f, 0.0890794435236f, 0.0912716282659f, 0.0934949642776f, 0.0957495767668f, 0.0980355901944f, 0.100353128286f, 0.102702314041f, 0.10508326975f, 0.107496116997f, 0.109940976678f, 0.112417969007f, 0.114927213525f, 0.117468829116f, 0.120042934009f, 0.122649645793f, 0.125289081424f, 0.127961357236f, 0.130666588944f, 0.13340489166f, 0.136176379898f, 0.138981167581f, 0.141819368051f, 0.144691094076f, 0.147596457859f, 0.150535571041f, 0.153508544716f, 0.156515489432f, 0.1595565152f, 0.1626317315f, 0.16574124729f, 0.168885171012f, 0.172063610595f, 0.175276673468f, 0.178524466557f, 0.181807096302f, 0.185124668654f, 0.188477289086f, 0.191865062595f, 0.195288093712f, 0.198746486503f, 0.202240344578f, 0.205769771096f, 0.209334868766f, 0.212935739858f, 0.216572486205f, 0.220245209207f, 0.223954009837f, 0.227698988648f, 0.231480245773f, 0.235297880934f, 0.239151993444f, 0.243042682212f, 0.246970045747f, 0.250934182163f, 0.254935189183f, 0.258973164144f, 0.263048203998f, 0.267160405319f, 0.271309864307f, 0.27549667679f, 0.279720938228f, 0.283982743718f, 0.288282187998f, 0.292619365448f, 0.296994370096f, 0.30140729562f, 0.305858235354f, 0.310347282289f, 0.314874529074f, 0.319440068025f, 0.324043991126f, 0.32868639003f, 0.333367356062f, 0.338086980228f, 0.34284535321f, 0.347642565374f, 0.352478706774f, 0.357353867148f, 0.36226813593f, 0.367221602246f, 0.372214354918f, 0.37724648247f, 0.382318073128f, 0.387429214822f, 0.392579995191f, 0.397770501584f, 0.403000821062f, 0.408271040402f, 0.413581246099f, 0.418931524369f, 0.424321961148f, 0.4297526421f, 0.435223652615f, 0.440735077813f, 0.446287002544f, 0.451879511396f, 0.45751268869f, 0.463186618488f, 0.46890138459f, 0.474657070542f, 0.480453759632f, 0.486291534897f, 0.492170479122f, 0.498090674843f, 0.50405220435f, 0.510055149687f, 0.516099592656f, 0.522185614816f, 0.528313297489f, 0.534482721758f, 0.54069396847f, 0.546947118241f, 0.553242251452f, 0.559579448254f, 0.565958788573f, 0.572380352104f, 0.578844218319f, 0.585350466467f, 0.591899175574f, 0.598490424448f, 0.605124291677f, 0.611800855632f, 0.61852019447f, 0.625282386134f, 0.632087508355f, 0.638935638652f, 0.645826854338f, 0.652761232515f, 0.659738850081f, 0.66675978373f, 0.673824109951f, 0.680931905032f, 0.688083245062f, 0.695278205929f, 0.702516863324f, 0.709799292744f, 0.717125569488f, 0.724495768663f, 0.731909965185f, 0.739368233777f, 0.746870648974f, 0.754417285121f, 0.762008216379f, 0.76964351672f, 0.777323259932f, 0.785047519623f, 0.792816369214f, 0.800629881949f, 0.80848813089f, 0.816391188922f, 0.824339128751f, 0.832332022907f, 0.840369943747f, 0.848452963452f, 0.856581154031f, 0.864754587319f, 0.872973334984f, 0.881237468522f, 0.889547059261f, 0.897902178361f, 0.906302896816f, 0.914749285456f, 0.923241414944f, 0.931779355781f, 0.940363178305f, 0.948992952695f, 0.957668748966f, 0.966390636975f, 0.975158686423f }; +// Generated from python script in repository at `tools/srgb_gen.py` +static 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.00251584218443f, 0.00279619194822f, + 0.00309396642819f, 0.00340946205345f, 0.00374296799396f, 0.00409476661624f, 0.00446513389425f, 0.00485433978143f, + 0.00526264854875f, 0.00569031909303f, 0.00613760521883f, 0.00660475589722f, 0.00709201550367f, 0.00759962403765f, + 0.00812781732551f, 0.00867682720861f, 0.00924688171802f, 0.00983820523704f, 0.0104510186528f, 0.0110855394981f, + 0.0117419820834f, 0.0124205576216f, 0.0131214743443f, 0.0138449376117f, 0.0145911500156f, 0.0153603114768f, + 0.0161526193372f, 0.0169682684465f, 0.0178074512441f, 0.0186703578377f, 0.0195571760767f, 0.0204680916222f, + 0.0214032880141f, 0.0223629467344f, 0.0233472472675f, 0.0243563671578f, 0.0253904820647f, 0.026449765815f, + 0.0275343904531f, 0.0286445262888f, 0.0297803419432f, 0.0309420043928f, 0.0321296790111f, 0.0333435296099f, + 0.0345837184768f, 0.0358504064137f, 0.0371437527716f, 0.0384639154854f, 0.0398110511069f, 0.0411853148367f, + 0.0425868605546f, 0.0440158408496f, 0.045472407048f, 0.046956709241f, 0.0484688963113f, 0.0500091159586f, + 0.0515775147244f, 0.0531742380159f, 0.0547994301291f, 0.0564532342711f, 0.058135792582f, 0.0598472461555f, + 0.0615877350593f, 0.063357398355f, 0.0651563741167f, 0.0669847994499f, 0.0688428105093f, 0.0707305425158f, + 0.0726481297741f, 0.0745957056885f, 0.0765734027789f, 0.0785813526965f, 0.0806196862387f, 0.0826885333636f, + 0.0847880232044f, 0.086918284083f, 0.0890794435236f, 0.0912716282659f, 0.0934949642776f, 0.0957495767668f, + 0.0980355901944f, 0.100353128286f, 0.102702314041f, 0.10508326975f, 0.107496116997f, 0.109940976678f, + 0.112417969007f, 0.114927213525f, 0.117468829116f, 0.120042934009f, 0.122649645793f, 0.125289081424f, + 0.127961357236f, 0.130666588944f, 0.13340489166f, 0.136176379898f, 0.138981167581f, 0.141819368051f, + 0.144691094076f, 0.147596457859f, 0.150535571041f, 0.153508544716f, 0.156515489432f, 0.1595565152f, + 0.1626317315f, 0.16574124729f, 0.168885171012f, 0.172063610595f, 0.175276673468f, 0.178524466557f, + 0.181807096302f, 0.185124668654f, 0.188477289086f, 0.191865062595f, 0.195288093712f, 0.198746486503f, + 0.202240344578f, 0.205769771096f, 0.209334868766f, 0.212935739858f, 0.216572486205f, 0.220245209207f, + 0.223954009837f, 0.227698988648f, 0.231480245773f, 0.235297880934f, 0.239151993444f, 0.243042682212f, + 0.246970045747f, 0.250934182163f, 0.254935189183f, 0.258973164144f, 0.263048203998f, 0.267160405319f, + 0.271309864307f, 0.27549667679f, 0.279720938228f, 0.283982743718f, 0.288282187998f, 0.292619365448f, + 0.296994370096f, 0.30140729562f, 0.305858235354f, 0.310347282289f, 0.314874529074f, 0.319440068025f, + 0.324043991126f, 0.32868639003f, 0.333367356062f, 0.338086980228f, 0.34284535321f, 0.347642565374f, + 0.352478706774f, 0.357353867148f, 0.36226813593f, 0.367221602246f, 0.372214354918f, 0.37724648247f, + 0.382318073128f, 0.387429214822f, 0.392579995191f, 0.397770501584f, 0.403000821062f, 0.408271040402f, + 0.413581246099f, 0.418931524369f, 0.424321961148f, 0.4297526421f, 0.435223652615f, 0.440735077813f, + 0.446287002544f, 0.451879511396f, 0.45751268869f, 0.463186618488f, 0.46890138459f, 0.474657070542f, + 0.480453759632f, 0.486291534897f, 0.492170479122f, 0.498090674843f, 0.50405220435f, 0.510055149687f, + 0.516099592656f, 0.522185614816f, 0.528313297489f, 0.534482721758f, 0.54069396847f, 0.546947118241f, + 0.553242251452f, 0.559579448254f, 0.565958788573f, 0.572380352104f, 0.578844218319f, 0.585350466467f, + 0.591899175574f, 0.598490424448f, 0.605124291677f, 0.611800855632f, 0.61852019447f, 0.625282386134f, + 0.632087508355f, 0.638935638652f, 0.645826854338f, 0.652761232515f, 0.659738850081f, 0.66675978373f, + 0.673824109951f, 0.680931905032f, 0.688083245062f, 0.695278205929f, 0.702516863324f, 0.709799292744f, + 0.717125569488f, 0.724495768663f, 0.731909965185f, 0.739368233777f, 0.746870648974f, 0.754417285121f, + 0.762008216379f, 0.76964351672f, 0.777323259932f, 0.785047519623f, 0.792816369214f, 0.800629881949f, + 0.80848813089f, 0.816391188922f, 0.824339128751f, 0.832332022907f, 0.840369943747f, 0.848452963452f, + 0.856581154031f, 0.864754587319f, 0.872973334984f, 0.881237468522f, 0.889547059261f, 0.897902178361f, + 0.906302896816f, 0.914749285456f, 0.923241414944f, 0.931779355781f, 0.940363178305f, 0.948992952695f, + 0.957668748966f, 0.966390636975f, 0.975158686423f +} + class ColorUtils { public: diff --git a/tools/srgb_gen.py b/tools/srgb_gen.py new file mode 100644 index 0000000000..e52f4a6418 --- /dev/null +++ b/tools/srgb_gen.py @@ -0,0 +1,22 @@ +NUM_VALUES = 256 +srgb_to_linear = [] + +# Calculate srgb to linear +for i in range(NUM_VALUES): + s = float(i) / 255 + if s < 0.04045: + l = s / 12.92 + else: + l = ((s + 0.044) / 1.055) ** 2.4 + srgb_to_linear.append(l) + +# Format and print +data = "{\n " +for i, v in enumerate(srgb_to_linear): + data += str(v) + "f" + if i < NUM_VALUES - 1: + data += ", " + if i > 0 and i % 6 == 0: + data += "\n " +data += "\n}" +print(data) From d40b783ce2caf4fe2a591eeb99becdcb0d2dfb27 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 12:06:09 -0700 Subject: [PATCH 41/78] Add comments to srgb_gen.py --- tools/srgb_gen.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/srgb_gen.py b/tools/srgb_gen.py index e52f4a6418..e17970209a 100644 --- a/tools/srgb_gen.py +++ b/tools/srgb_gen.py @@ -1,3 +1,15 @@ +# +# srgb_gen.py +# tools/ +# +# Created by Ryan Huffman on 8/8/2016. +# 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 + +# Generates a lookup table for SRGB to Linear color transformations + NUM_VALUES = 256 srgb_to_linear = [] From 2ee511bae0972b0ee5ef02877445ebf2df55b979 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 12:30:11 -0700 Subject: [PATCH 42/78] Fix syntax error --- libraries/shared/src/ColorUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/ColorUtils.h b/libraries/shared/src/ColorUtils.h index e7b4a1e5c2..921b26399d 100644 --- a/libraries/shared/src/ColorUtils.h +++ b/libraries/shared/src/ColorUtils.h @@ -62,7 +62,7 @@ static const float srgbToLinearLookupTable[256] = { 0.856581154031f, 0.864754587319f, 0.872973334984f, 0.881237468522f, 0.889547059261f, 0.897902178361f, 0.906302896816f, 0.914749285456f, 0.923241414944f, 0.931779355781f, 0.940363178305f, 0.948992952695f, 0.957668748966f, 0.966390636975f, 0.975158686423f -} +}; class ColorUtils { From a5f3089fdaf9f0244f95c3e61d53e33d211ac58a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 8 Aug 2016 13:14:14 -0700 Subject: [PATCH 43/78] fix ABXY mapping for touch --- interface/resources/controllers/oculus_touch.json | 9 +++++++-- interface/resources/controllers/standard.json | 3 --- interface/resources/controllers/xbox.json | 4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/interface/resources/controllers/oculus_touch.json b/interface/resources/controllers/oculus_touch.json index 82f52e50db..ef5d8c59a8 100644 --- a/interface/resources/controllers/oculus_touch.json +++ b/interface/resources/controllers/oculus_touch.json @@ -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": [ diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 5c0ea09939..222357ac9d 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -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" }, diff --git a/interface/resources/controllers/xbox.json b/interface/resources/controllers/xbox.json index fdac70ff33..1234372a7e 100644 --- a/interface/resources/controllers/xbox.json +++ b/interface/resources/controllers/xbox.json @@ -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" }, From de900e85c059a951129f143e8cca0175cad327b1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 8 Aug 2016 14:10:47 -0700 Subject: [PATCH 44/78] remove duplicate include --- libraries/render-utils/src/MeshPartPayload.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 3b78023496..c2c27fb298 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -13,8 +13,6 @@ #include -#include - #include "DeferredLightingEffect.h" #include "Model.h" From 43bbe790d6389396d37306c985b5c80b098e20a4 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 5 Aug 2016 17:01:33 -0700 Subject: [PATCH 45/78] Add atp support to qml --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 3 + .../networking/src/AssetResourceRequest.cpp | 5 -- libraries/networking/src/QmlAtpReply.cpp | 88 +++++++++++++++++++ libraries/networking/src/QmlAtpReply.h | 40 +++++++++ .../src/QmlNetworkAccessManager.cpp | 29 ++++++ .../networking/src/QmlNetworkAccessManager.h | 33 +++++++ libraries/ui/src/QmlWindowClass.cpp | 7 +- 7 files changed, 197 insertions(+), 8 deletions(-) create mode 100644 libraries/networking/src/QmlAtpReply.cpp create mode 100644 libraries/networking/src/QmlAtpReply.h create mode 100644 libraries/networking/src/QmlNetworkAccessManager.cpp create mode 100644 libraries/networking/src/QmlNetworkAccessManager.h diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 8c167fafdc..ebccc8a1fc 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "OffscreenGLCanvas.h" #include "GLEscrow.h" @@ -402,6 +403,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); diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index 6b94ee152a..a8311c6146 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -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); diff --git a/libraries/networking/src/QmlAtpReply.cpp b/libraries/networking/src/QmlAtpReply.cpp new file mode 100644 index 0000000000..fd1e1e5023 --- /dev/null +++ b/libraries/networking/src/QmlAtpReply.cpp @@ -0,0 +1,88 @@ +// +// QmlAtpReply.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 "QmlAtpReply.h" + +QmlAtpReply::QmlAtpReply(const QUrl& url, QObject* parent) : + _resourceRequest(ResourceManager::createResourceRequest(parent, url)) { + setOperation(QNetworkAccessManager::GetOperation); + + connect(_resourceRequest, &AssetResourceRequest::progress, this, &QmlAtpReply::downloadProgress); + connect(_resourceRequest, &AssetResourceRequest::finished, this, &QmlAtpReply::handleRequestFinish); + + _resourceRequest->send(); +} + +QmlAtpReply::~QmlAtpReply() { + if (_resourceRequest) { + _resourceRequest->deleteLater(); + _resourceRequest = nullptr; + } +} + +qint64 QmlAtpReply::bytesAvailable() const { + return _content.size() - _readOffset + QIODevice::bytesAvailable(); +} + +qint64 QmlAtpReply::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 QmlAtpReply::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; +} \ No newline at end of file diff --git a/libraries/networking/src/QmlAtpReply.h b/libraries/networking/src/QmlAtpReply.h new file mode 100644 index 0000000000..7b0fa5686e --- /dev/null +++ b/libraries/networking/src/QmlAtpReply.h @@ -0,0 +1,40 @@ +// +// QmlAtpReply.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_QmlAtpReply_h +#define hifi_QmlAtpReply_h + +#include +#include + +#include "AssetResourceRequest.h" + +class QmlAtpReply : public QNetworkReply { + Q_OBJECT +public: + QmlAtpReply(const QUrl& url, QObject* parent = Q_NULLPTR); + ~QmlAtpReply(); + 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_QmlAtpReply_h \ No newline at end of file diff --git a/libraries/networking/src/QmlNetworkAccessManager.cpp b/libraries/networking/src/QmlNetworkAccessManager.cpp new file mode 100644 index 0000000000..9e86d3b85f --- /dev/null +++ b/libraries/networking/src/QmlNetworkAccessManager.cpp @@ -0,0 +1,29 @@ +// +// QmlNetworkAccessManager.cpp +// +// +// Created by Clement on 7/1/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "QmlAtpReply.h" +#include "QmlNetworkAccessManager.h" + +QNetworkAccessManager* QmlNetworkAccessManagerFactory::create(QObject* parent) { + return new QmlNetworkAccessManager(parent); +} + +QNetworkReply* QmlNetworkAccessManager::createRequest(Operation operation, const QNetworkRequest& request, QIODevice* device) { + if (request.url().scheme() == "atp" && operation == GetOperation) { + return new QmlAtpReply(request.url()); + //auto url = request.url().toString(); + //return QNetworkAccessManager::createRequest(operation, request, device); + } else { + return QNetworkAccessManager::createRequest(operation, request, device); + } +} \ No newline at end of file diff --git a/libraries/networking/src/QmlNetworkAccessManager.h b/libraries/networking/src/QmlNetworkAccessManager.h new file mode 100644 index 0000000000..72ca0a4cb4 --- /dev/null +++ b/libraries/networking/src/QmlNetworkAccessManager.h @@ -0,0 +1,33 @@ +// +// QmlNetworkAccessManager.h +// +// +// Created by Clement on 7/1/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_QmlNetworkAccessManager_h +#define hifi_QmlNetworkAccessManager_h + +#include +#include +#include + +class QmlNetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory { +public: + QNetworkAccessManager* create(QObject* parent); +}; + + +class QmlNetworkAccessManager : public QNetworkAccessManager { + Q_OBJECT +public: + QmlNetworkAccessManager(QObject* parent = Q_NULLPTR) : QNetworkAccessManager(parent) { } +protected: + QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* device = Q_NULLPTR); +}; + +#endif // hifi_QmlNetworkAccessManager_h \ No newline at end of file diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index c3ca5f54d9..554ae7d8c2 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -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; From 246a8457e176f8b8e95e098c9a10dc9c59917af3 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 8 Aug 2016 11:52:04 -0700 Subject: [PATCH 46/78] Add some asserts --- libraries/networking/src/ResourceCache.cpp | 1 + libraries/script-engine/src/ScriptCache.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 36828b3992..5fb686ca6f 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -462,6 +462,7 @@ int ResourceCache::getPendingRequestCount() { } bool ResourceCache::attemptRequest(QSharedPointer resource) { + Q_ASSERT(!resource.isNull()); auto sharedItems = DependencyManager::get(); if (_requestsActive >= _requestLimit) { diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index 40234e8134..91d7f36102 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -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) { From aebd18db7f50e207489e7a7da76f3ccadbd28baf Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 8 Aug 2016 13:38:14 -0700 Subject: [PATCH 47/78] Add EOF newlines --- libraries/networking/src/QmlAtpReply.cpp | 2 +- libraries/networking/src/QmlAtpReply.h | 2 +- libraries/networking/src/QmlNetworkAccessManager.cpp | 2 +- libraries/networking/src/QmlNetworkAccessManager.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/QmlAtpReply.cpp b/libraries/networking/src/QmlAtpReply.cpp index fd1e1e5023..a2e537ba1f 100644 --- a/libraries/networking/src/QmlAtpReply.cpp +++ b/libraries/networking/src/QmlAtpReply.cpp @@ -85,4 +85,4 @@ void QmlAtpReply::handleRequestFinish() { _resourceRequest->deleteLater(); _resourceRequest = nullptr; -} \ No newline at end of file +} diff --git a/libraries/networking/src/QmlAtpReply.h b/libraries/networking/src/QmlAtpReply.h index 7b0fa5686e..a8f6dfde14 100644 --- a/libraries/networking/src/QmlAtpReply.h +++ b/libraries/networking/src/QmlAtpReply.h @@ -37,4 +37,4 @@ private: qint64 _readOffset { 0 }; }; -#endif // hifi_QmlAtpReply_h \ No newline at end of file +#endif // hifi_QmlAtpReply_h diff --git a/libraries/networking/src/QmlNetworkAccessManager.cpp b/libraries/networking/src/QmlNetworkAccessManager.cpp index 9e86d3b85f..ef44eb8526 100644 --- a/libraries/networking/src/QmlNetworkAccessManager.cpp +++ b/libraries/networking/src/QmlNetworkAccessManager.cpp @@ -26,4 +26,4 @@ QNetworkReply* QmlNetworkAccessManager::createRequest(Operation operation, const } else { return QNetworkAccessManager::createRequest(operation, request, device); } -} \ No newline at end of file +} diff --git a/libraries/networking/src/QmlNetworkAccessManager.h b/libraries/networking/src/QmlNetworkAccessManager.h index 72ca0a4cb4..9b817d612e 100644 --- a/libraries/networking/src/QmlNetworkAccessManager.h +++ b/libraries/networking/src/QmlNetworkAccessManager.h @@ -30,4 +30,4 @@ protected: QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* device = Q_NULLPTR); }; -#endif // hifi_QmlNetworkAccessManager_h \ No newline at end of file +#endif // hifi_QmlNetworkAccessManager_h From cb153f2a29f59297fa8566918997a07335f741fb Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 8 Aug 2016 15:17:17 -0700 Subject: [PATCH 48/78] Fix file header comments --- libraries/networking/src/QmlNetworkAccessManager.cpp | 4 ++-- libraries/networking/src/QmlNetworkAccessManager.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/QmlNetworkAccessManager.cpp b/libraries/networking/src/QmlNetworkAccessManager.cpp index ef44eb8526..575bc02f8c 100644 --- a/libraries/networking/src/QmlNetworkAccessManager.cpp +++ b/libraries/networking/src/QmlNetworkAccessManager.cpp @@ -1,8 +1,8 @@ // // QmlNetworkAccessManager.cpp +// libraries/networking/src // -// -// Created by Clement on 7/1/14. +// Created by Zander Otavka on 8/4/16. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/networking/src/QmlNetworkAccessManager.h b/libraries/networking/src/QmlNetworkAccessManager.h index 9b817d612e..059d0ebba0 100644 --- a/libraries/networking/src/QmlNetworkAccessManager.h +++ b/libraries/networking/src/QmlNetworkAccessManager.h @@ -1,8 +1,8 @@ // // QmlNetworkAccessManager.h +// libraries/networking/src // -// -// Created by Clement on 7/1/14. +// Created by Zander Otavka on 8/4/16. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From d36e60bbaa84e1b0bd6530a552bc27796025b7a0 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 8 Aug 2016 15:20:58 -0700 Subject: [PATCH 49/78] eslintrc: accept spaces after function keyword in anonymous functions Anonymous functions `function () {}` and `function() {}` will both be accepted by eslint. --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 82dfe9e9bd..6183fa8aec 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -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"}] } }; From 9b137570cfb2fefe613c96d7f888d9deaef0c7fe Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 15:21:35 -0700 Subject: [PATCH 50/78] Fix srgb_gen lookup table generation --- tools/srgb_gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/srgb_gen.py b/tools/srgb_gen.py index e17970209a..6db2c1da03 100644 --- a/tools/srgb_gen.py +++ b/tools/srgb_gen.py @@ -19,7 +19,7 @@ for i in range(NUM_VALUES): if s < 0.04045: l = s / 12.92 else: - l = ((s + 0.044) / 1.055) ** 2.4 + l = ((s + 0.055) / 1.055) ** 2.4 srgb_to_linear.append(l) # Format and print From b800aa793da8753f13279a06e32f6c2d8c24a1bd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 15:45:05 -0700 Subject: [PATCH 51/78] Fix gamma correction adjusting uchar to float when unnecessary --- libraries/gpu/src/gpu/Texture.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index bd0ad0ce7b..25e4fa549c 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -788,9 +788,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(ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex]) * UCHAR_TO_FLOAT, - ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex+1]) * UCHAR_TO_FLOAT, - ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex+2]) * UCHAR_TO_FLOAT); + 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, From 43c1472b36681d4463d674c972c182fb9f0a518a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 15:47:53 -0700 Subject: [PATCH 52/78] Move srgbToLinear lookup table to external cpp --- libraries/shared/src/ColorUtils.cpp | 59 +++++++++++++++++++++++++++++ libraries/shared/src/ColorUtils.h | 51 ++----------------------- 2 files changed, 62 insertions(+), 48 deletions(-) create mode 100644 libraries/shared/src/ColorUtils.cpp diff --git a/libraries/shared/src/ColorUtils.cpp b/libraries/shared/src/ColorUtils.cpp new file mode 100644 index 0000000000..f0dfc89367 --- /dev/null +++ b/libraries/shared/src/ColorUtils.cpp @@ -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 +}; \ No newline at end of file diff --git a/libraries/shared/src/ColorUtils.h b/libraries/shared/src/ColorUtils.h index 921b26399d..fd0bbdd8ab 100644 --- a/libraries/shared/src/ColorUtils.h +++ b/libraries/shared/src/ColorUtils.h @@ -13,57 +13,12 @@ #define hifi_ColorUtils_h #include -#include + +#include "SharedUtil.h" #include "DependencyManager.h" -// Generated from python script in repository at `tools/srgb_gen.py` -static 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.00251584218443f, 0.00279619194822f, - 0.00309396642819f, 0.00340946205345f, 0.00374296799396f, 0.00409476661624f, 0.00446513389425f, 0.00485433978143f, - 0.00526264854875f, 0.00569031909303f, 0.00613760521883f, 0.00660475589722f, 0.00709201550367f, 0.00759962403765f, - 0.00812781732551f, 0.00867682720861f, 0.00924688171802f, 0.00983820523704f, 0.0104510186528f, 0.0110855394981f, - 0.0117419820834f, 0.0124205576216f, 0.0131214743443f, 0.0138449376117f, 0.0145911500156f, 0.0153603114768f, - 0.0161526193372f, 0.0169682684465f, 0.0178074512441f, 0.0186703578377f, 0.0195571760767f, 0.0204680916222f, - 0.0214032880141f, 0.0223629467344f, 0.0233472472675f, 0.0243563671578f, 0.0253904820647f, 0.026449765815f, - 0.0275343904531f, 0.0286445262888f, 0.0297803419432f, 0.0309420043928f, 0.0321296790111f, 0.0333435296099f, - 0.0345837184768f, 0.0358504064137f, 0.0371437527716f, 0.0384639154854f, 0.0398110511069f, 0.0411853148367f, - 0.0425868605546f, 0.0440158408496f, 0.045472407048f, 0.046956709241f, 0.0484688963113f, 0.0500091159586f, - 0.0515775147244f, 0.0531742380159f, 0.0547994301291f, 0.0564532342711f, 0.058135792582f, 0.0598472461555f, - 0.0615877350593f, 0.063357398355f, 0.0651563741167f, 0.0669847994499f, 0.0688428105093f, 0.0707305425158f, - 0.0726481297741f, 0.0745957056885f, 0.0765734027789f, 0.0785813526965f, 0.0806196862387f, 0.0826885333636f, - 0.0847880232044f, 0.086918284083f, 0.0890794435236f, 0.0912716282659f, 0.0934949642776f, 0.0957495767668f, - 0.0980355901944f, 0.100353128286f, 0.102702314041f, 0.10508326975f, 0.107496116997f, 0.109940976678f, - 0.112417969007f, 0.114927213525f, 0.117468829116f, 0.120042934009f, 0.122649645793f, 0.125289081424f, - 0.127961357236f, 0.130666588944f, 0.13340489166f, 0.136176379898f, 0.138981167581f, 0.141819368051f, - 0.144691094076f, 0.147596457859f, 0.150535571041f, 0.153508544716f, 0.156515489432f, 0.1595565152f, - 0.1626317315f, 0.16574124729f, 0.168885171012f, 0.172063610595f, 0.175276673468f, 0.178524466557f, - 0.181807096302f, 0.185124668654f, 0.188477289086f, 0.191865062595f, 0.195288093712f, 0.198746486503f, - 0.202240344578f, 0.205769771096f, 0.209334868766f, 0.212935739858f, 0.216572486205f, 0.220245209207f, - 0.223954009837f, 0.227698988648f, 0.231480245773f, 0.235297880934f, 0.239151993444f, 0.243042682212f, - 0.246970045747f, 0.250934182163f, 0.254935189183f, 0.258973164144f, 0.263048203998f, 0.267160405319f, - 0.271309864307f, 0.27549667679f, 0.279720938228f, 0.283982743718f, 0.288282187998f, 0.292619365448f, - 0.296994370096f, 0.30140729562f, 0.305858235354f, 0.310347282289f, 0.314874529074f, 0.319440068025f, - 0.324043991126f, 0.32868639003f, 0.333367356062f, 0.338086980228f, 0.34284535321f, 0.347642565374f, - 0.352478706774f, 0.357353867148f, 0.36226813593f, 0.367221602246f, 0.372214354918f, 0.37724648247f, - 0.382318073128f, 0.387429214822f, 0.392579995191f, 0.397770501584f, 0.403000821062f, 0.408271040402f, - 0.413581246099f, 0.418931524369f, 0.424321961148f, 0.4297526421f, 0.435223652615f, 0.440735077813f, - 0.446287002544f, 0.451879511396f, 0.45751268869f, 0.463186618488f, 0.46890138459f, 0.474657070542f, - 0.480453759632f, 0.486291534897f, 0.492170479122f, 0.498090674843f, 0.50405220435f, 0.510055149687f, - 0.516099592656f, 0.522185614816f, 0.528313297489f, 0.534482721758f, 0.54069396847f, 0.546947118241f, - 0.553242251452f, 0.559579448254f, 0.565958788573f, 0.572380352104f, 0.578844218319f, 0.585350466467f, - 0.591899175574f, 0.598490424448f, 0.605124291677f, 0.611800855632f, 0.61852019447f, 0.625282386134f, - 0.632087508355f, 0.638935638652f, 0.645826854338f, 0.652761232515f, 0.659738850081f, 0.66675978373f, - 0.673824109951f, 0.680931905032f, 0.688083245062f, 0.695278205929f, 0.702516863324f, 0.709799292744f, - 0.717125569488f, 0.724495768663f, 0.731909965185f, 0.739368233777f, 0.746870648974f, 0.754417285121f, - 0.762008216379f, 0.76964351672f, 0.777323259932f, 0.785047519623f, 0.792816369214f, 0.800629881949f, - 0.80848813089f, 0.816391188922f, 0.824339128751f, 0.832332022907f, 0.840369943747f, 0.848452963452f, - 0.856581154031f, 0.864754587319f, 0.872973334984f, 0.881237468522f, 0.889547059261f, 0.897902178361f, - 0.906302896816f, 0.914749285456f, 0.923241414944f, 0.931779355781f, 0.940363178305f, 0.948992952695f, - 0.957668748966f, 0.966390636975f, 0.975158686423f -}; - +extern const float srgbToLinearLookupTable[256]; class ColorUtils { public: From 35ea9908cde7aa384fefcb0de36b4dd4ae6dc433 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 22:37:06 -0700 Subject: [PATCH 53/78] Add default skybox --- interface/src/Application.cpp | 32 ++++++++++++++++++- .../src/EntityTreeRenderer.cpp | 1 - 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd55f32629..5c3daaa9c2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -164,6 +164,13 @@ extern "C" { } #endif +#include +#include + +static model::Skybox* skybox{ new ProceduralSkybox() } ; +static NetworkTexturePointer skyboxTexture; +static bool skyboxTextureLoaded = false; + using namespace std; static QTimer locationUpdateTimer; @@ -1212,6 +1219,9 @@ 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(); + skyboxTexture = textureCache->getTexture(QUrl("https://hifi-public.s3.amazonaws.com/images/SkyboxTextures/FullMoon1024Compressed.jpg"), NetworkTexture::CUBE_TEXTURE); + // After all of the constructor is completed, then set firstRun to false. Setting::Handle firstRun{ Settings::firstRun, true }; firstRun.set(false); @@ -4241,6 +4251,7 @@ 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), @@ -4250,6 +4261,25 @@ namespace render { static const float alpha = 1.0f; background->_stars.render(args, alpha); } + */ + + if (!skyboxTextureLoaded && skyboxTexture && skyboxTexture->isLoaded()) { + skybox->setColor({ 1.0, 1.0, 1.0 }); + skyboxTextureLoaded = true; + auto texture = skyboxTexture->getGPUTexture(); + if (texture) { + skybox->setCubemap(texture); + auto scene = DependencyManager::get()->getStage(); + auto sceneKeyLight = scene->getKeyLight(); + sceneKeyLight->setAmbientSphere(texture->getIrradiance()); + sceneKeyLight->setAmbientMap(texture); + } else { + skybox->setCubemap(nullptr); + } + } + if (skyboxTextureLoaded) { + skybox->render(batch, args->getViewFrustum()); + } } break; @@ -4443,7 +4473,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 +4498,7 @@ void Application::clearDomainOctreeDetails() { getEntities()->clear(); auto skyStage = DependencyManager::get()->getSkyStage(); + skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); _recentlyClearedDomain = true; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 24827ea111..9eadd6d0b9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -375,7 +375,6 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrsetBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application background through - return; // Early exit } From 5b69ca03f04b6e26fdc3e04aeadc8e49142ccbc4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 10:26:57 -0700 Subject: [PATCH 54/78] Move default skybox out of global and make irradiance gen optional --- interface/src/Application.cpp | 49 +++++++++---------- interface/src/Application.h | 11 +++++ .../src/model-networking/TextureCache.cpp | 12 +++-- .../src/model-networking/TextureCache.h | 2 +- libraries/model/src/model/TextureMap.cpp | 4 ++ libraries/model/src/model/TextureMap.h | 1 + 6 files changed, 48 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5c3daaa9c2..4739fedc26 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -164,13 +164,6 @@ extern "C" { } #endif -#include -#include - -static model::Skybox* skybox{ new ProceduralSkybox() } ; -static NetworkTexturePointer skyboxTexture; -static bool skyboxTextureLoaded = false; - using namespace std; static QTimer locationUpdateTimer; @@ -1219,8 +1212,16 @@ 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(); - skyboxTexture = textureCache->getTexture(QUrl("https://hifi-public.s3.amazonaws.com/images/SkyboxTextures/FullMoon1024Compressed.jpg"), NetworkTexture::CUBE_TEXTURE); + auto textureCache = DependencyManager::get(); + + 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 firstRun{ Settings::firstRun, true }; @@ -4263,23 +4264,19 @@ namespace render { } */ - if (!skyboxTextureLoaded && skyboxTexture && skyboxTexture->isLoaded()) { - skybox->setColor({ 1.0, 1.0, 1.0 }); - skyboxTextureLoaded = true; - auto texture = skyboxTexture->getGPUTexture(); - if (texture) { - skybox->setCubemap(texture); - auto scene = DependencyManager::get()->getStage(); - auto sceneKeyLight = scene->getKeyLight(); - sceneKeyLight->setAmbientSphere(texture->getIrradiance()); - sceneKeyLight->setAmbientMap(texture); - } else { - skybox->setCubemap(nullptr); - } - } - if (skyboxTextureLoaded) { - skybox->render(batch, args->getViewFrustum()); - } + auto scene = DependencyManager::get()->getStage(); + auto sceneKeyLight = scene->getKeyLight(); + scene->setSunModelEnable(false); + sceneKeyLight->setColor(glm::vec3(255.0f / 255.0f, 220.0f / 255.0f, 194.0f / 255.0f) * 0.2f); + sceneKeyLight->setIntensity(0.2f); + sceneKeyLight->setAmbientIntensity(3.5f); + sceneKeyLight->setDirection({ 0.0f, 0.0f, -1.0f }); + + auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture(); + sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance()); + sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture); + + qApp->getDefaultSkybox()->render(batch, args->getViewFrustum()); } break; diff --git a/interface/src/Application.h b/interface/src/Application.h index c81d56e0aa..8936206790 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -65,6 +65,9 @@ #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" +#include +#include + 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; }; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 000ca67989..c373da34ba 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -171,7 +171,7 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const } -NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type) { +NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type, const QVariantMap& options = {}) { using Type = NetworkTexture; switch (type) { @@ -188,7 +188,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 +229,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())); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 0108a3dd6c..66634b6ac0 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -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 = {}); /// Loads a texture from the specified URL. NetworkTexturePointer getTexture(const QUrl& url, Type type = Type::DEFAULT_TEXTURE, diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 3e6016d7c0..587aa6e0fa 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -729,3 +729,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); +} diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index daa4b0d7bb..795b685f27 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -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); From c47a5c5aad8e0239f7ff3bd20609d6cb79b24619 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 10:28:06 -0700 Subject: [PATCH 55/78] Add default skybox images --- .../resources/images/Default-Sky-9-ambient.jpg | Bin 0 -> 6223 bytes .../resources/images/Default-Sky-9-cubemap.jpg | Bin 0 -> 403009 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 interface/resources/images/Default-Sky-9-ambient.jpg create mode 100644 interface/resources/images/Default-Sky-9-cubemap.jpg diff --git a/interface/resources/images/Default-Sky-9-ambient.jpg b/interface/resources/images/Default-Sky-9-ambient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8fb383c5e8d31fdb9aafeadddaa921aa6676c578 GIT binary patch literal 6223 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 Date: Thu, 4 Aug 2016 10:31:06 -0700 Subject: [PATCH 56/78] Add static consts for default skybox values --- interface/src/Application.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4739fedc26..1a11096a7a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4264,13 +4264,18 @@ namespace render { } */ + 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 { 3.5f }; + static const glm::vec3 DEFAULT_SKYBOX_DIRECTION { 0.0f, 0.0f, -1.0f }; + auto scene = DependencyManager::get()->getStage(); auto sceneKeyLight = scene->getKeyLight(); scene->setSunModelEnable(false); - sceneKeyLight->setColor(glm::vec3(255.0f / 255.0f, 220.0f / 255.0f, 194.0f / 255.0f) * 0.2f); - sceneKeyLight->setIntensity(0.2f); - sceneKeyLight->setAmbientIntensity(3.5f); - sceneKeyLight->setDirection({ 0.0f, 0.0f, -1.0f }); + 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()); From 9cbfe195cd465d48d2911877ab20c5624e99a1f3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 10:32:05 -0700 Subject: [PATCH 57/78] Adjust commenting out of old stars rendering code --- interface/src/Application.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a11096a7a..13267f30e7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4252,17 +4252,15 @@ 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() ... My god, it's full of stars..."); - // should be the first rendering pass - w/o depth buffer / lighting - - static const float alpha = 1.0f; - background->_stars.render(args, alpha); - } - */ +// if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { +// PerformanceTimer perfTimer("stars"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), +// "Application::payloadRender() ... My god, it's full of stars..."); +// // should be the first rendering pass - w/o depth buffer / lighting +// +// static const float alpha = 1.0f; +// background->_stars.render(args, alpha); +// } 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 }; From 36744d72d6c3d7456ded5a7a223725e8eb1e658e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 4 Aug 2016 11:00:21 -0700 Subject: [PATCH 58/78] Fix warning using init list for QVariantMap --- .../model-networking/src/model-networking/TextureCache.cpp | 3 ++- libraries/model-networking/src/model-networking/TextureCache.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index c373da34ba..e10be30f54 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -171,7 +171,8 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const } -NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type, const QVariantMap& options = {}) { +NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type, + const QVariantMap& options = QVariantMap()) { using Type = NetworkTexture; switch (type) { diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 66634b6ac0..9c78e7e378 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -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, QVariantMap options = {}); + 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, From eaa77edc25b251a2e0bd708b4df43c6613f37310 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 08:59:57 -0700 Subject: [PATCH 59/78] Replace 'Stars' menu option with 'Default Skybox' --- interface/src/Application.cpp | 47 ++++++++++++++--------------------- interface/src/Menu.cpp | 2 +- interface/src/Menu.h | 2 +- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 13267f30e7..209ef8d02f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -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" @@ -2291,7 +2290,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: @@ -4216,8 +4215,6 @@ public: typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - Stars _stars; - static render::ItemID _item; // unique WorldBoxRenderData }; @@ -4252,34 +4249,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() ... My god, it's full of stars..."); -// // should be the first rendering pass - w/o depth buffer / lighting -// -// static const float alpha = 1.0f; -// background->_stars.render(args, alpha); -// } + 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 { 3.5f }; + static const glm::vec3 DEFAULT_SKYBOX_DIRECTION { 0.0f, 0.0f, -1.0f }; - 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 { 3.5f }; - static const glm::vec3 DEFAULT_SKYBOX_DIRECTION { 0.0f, 0.0f, -1.0f }; + auto scene = DependencyManager::get()->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 scene = DependencyManager::get()->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); - auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture(); - sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance()); - sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture); - - qApp->getDefaultSkybox()->render(batch, args->getViewFrustum()); + qApp->getDefaultSkybox()->render(batch, args->getViewFrustum()); + } } break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6308ac6c73..a8340e8f47 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -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); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 503cbf51fa..d47b6842a5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -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"; From 6854f9fda4c3358ce56eeb7adaca388732b68ba1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 09:02:23 -0700 Subject: [PATCH 60/78] Remove stars shaders and renderable --- interface/src/Stars.cpp | 216 ----------------------- interface/src/Stars.h | 49 ----- libraries/render-utils/src/stars.slf | 34 ---- libraries/render-utils/src/stars.slv | 36 ---- libraries/render-utils/src/starsGrid.slf | 63 ------- tests/shaders/src/main.cpp | 7 - 6 files changed, 405 deletions(-) delete mode 100644 interface/src/Stars.cpp delete mode 100644 interface/src/Stars.h delete mode 100644 libraries/render-utils/src/stars.slf delete mode 100644 libraries/render-utils/src/stars.slv delete mode 100644 libraries/render-utils/src/starsGrid.slf diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp deleted file mode 100644 index 9510710eb3..0000000000 --- a/interface/src/Stars.cpp +++ /dev/null @@ -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 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -//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 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(); - auto textureCache = DependencyManager::get(); - auto geometryCache = DependencyManager::get(); - - - 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); -} diff --git a/interface/src/Stars.h b/interface/src/Stars.h deleted file mode 100644 index f07caff770..0000000000 --- a/interface/src/Stars.h +++ /dev/null @@ -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 - -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 diff --git a/libraries/render-utils/src/stars.slf b/libraries/render-utils/src/stars.slf deleted file mode 100644 index 14191f2a6a..0000000000 --- a/libraries/render-utils/src/stars.slf +++ /dev/null @@ -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); - } -} diff --git a/libraries/render-utils/src/stars.slv b/libraries/render-utils/src/stars.slv deleted file mode 100644 index d00bb8b7dd..0000000000 --- a/libraries/render-utils/src/stars.slv +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/libraries/render-utils/src/starsGrid.slf b/libraries/render-utils/src/starsGrid.slf deleted file mode 100644 index ad9a45a4f5..0000000000 --- a/libraries/render-utils/src/starsGrid.slf +++ /dev/null @@ -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)); -} - diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index 2ef7bbdd02..9c4a835966 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -75,10 +75,6 @@ #include #include -#include -#include -#include - #include #include #include @@ -168,9 +164,6 @@ void QTestWindow::draw() { testShaderBuild(deferred_light_limited_vert, spot_light_frag); testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag); testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag); - - testShaderBuild(standardTransformPNTC_vert, starsGrid_frag); - testShaderBuild(stars_vert, stars_frag); testShaderBuild(model_vert, model_frag); testShaderBuild(model_normal_map_vert, model_normal_map_frag); From 8ee3f680c91b1b3e4324bc92b1a59ac18fbe7971 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 Aug 2016 14:08:49 -0700 Subject: [PATCH 61/78] Change default skybox ambient intensity from 3.5 to 2.0 --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 209ef8d02f..dfebb6bcb2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4252,7 +4252,7 @@ namespace render { 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 { 3.5f }; + static const float DEFAULT_SKYBOX_AMBIENT_INTENSITY { 2.0f }; static const glm::vec3 DEFAULT_SKYBOX_DIRECTION { 0.0f, 0.0f, -1.0f }; auto scene = DependencyManager::get()->getStage(); From 3df8aa0dba370f9c0f11c3ad6099e91dcc8c6956 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 8 Aug 2016 17:01:32 -0700 Subject: [PATCH 62/78] Suppress repeated ice server connection messages --- domain-server/src/DomainServer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6c4b12d4c0..d5f23f7c4e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -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"; From ae9fb3768c6154f419e739136875af6245698687 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 8 Aug 2016 17:45:25 -0700 Subject: [PATCH 63/78] CR notes --- libraries/render-utils/src/GeometryCache.cpp | 37 +++++++++---------- .../render-utils/src/MeshPartPayload.cpp | 4 ++ libraries/render-utils/src/MeshPartPayload.h | 3 +- libraries/render-utils/src/Model.cpp | 1 - 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index dcd36946cb..f906a871fe 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -406,29 +406,28 @@ GeometryCache::GeometryCache() : _nextID(0) { buildShapes(); GeometryCache::_simpleOpaquePipeline = - std::make_shared(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()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); - } - ); + std::make_shared(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()->getWhiteTexture()); + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, + DependencyManager::get()->getNormalFittingTexture()); + } + ); GeometryCache::_simpleTransparentPipeline = std::make_shared(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()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); - } - ); + [](const render::ShapePipeline&, gpu::Batch& batch) { + // Set the defaults needed for a simple program + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, + DependencyManager::get()->getWhiteTexture()); + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, + DependencyManager::get()->getNormalFittingTexture()); + } + ); GeometryCache::_simpleWirePipeline = std::make_shared(getSimplePipeline(false, false, true, true), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) {} - ); + [](const render::ShapePipeline&, gpu::Batch& batch) {}); } GeometryCache::~GeometryCache() { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index c2c27fb298..2fa31022ec 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -516,6 +516,10 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(transform); } +void ModelMeshPartPayload::startFade() { + _fadeStartTime = usecTimestampNow(); + _hasStartedFade = true; +} void ModelMeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index c2305f3741..8fdafee9b0 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -84,9 +84,8 @@ public: void updateTransformForSkinnedMesh(const Transform& transform, const Transform& offsetTransform, const QVector& clusterMatrices); // Entity fade in - void startFade() { _fadeStartTime = usecTimestampNow(); } + void startFade(); bool hasStartedFade() { return _hasStartedFade; } - void setHasStartedFade(bool hasStartedFade) { _hasStartedFade = hasStartedFade; } bool isStillFading() const { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } // Render Item interface diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9d158810e7..2c7e9485fb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -214,7 +214,6 @@ void Model::updateRenderItems() { pendingChanges.updateItem(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) { if (!data.hasStartedFade() && data._model && data._model->isLoaded() && data._model->getGeometry()->areTexturesLoaded()) { data.startFade(); - data.setHasStartedFade(true); } // Ensure the model geometry was not reset between frames if (data._model && data._model->isLoaded() && deleteGeometryCounter == data._model->_deleteGeometryCounter) { From 51fb52977e039af704dfc74b7faf653ed80a6d09 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 9 Aug 2016 11:46:08 -0700 Subject: [PATCH 64/78] Generalize atp handling in network access managers --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 18 +++++++++- .../src/{QmlAtpReply.cpp => AtpReply.cpp} | 18 +++++----- .../src/{QmlAtpReply.h => AtpReply.h} | 14 ++++---- .../networking/src/NetworkAccessManager.cpp | 13 +++++++- .../networking/src/NetworkAccessManager.h | 9 +++-- .../src/OAuthNetworkAccessManager.h | 5 +-- .../src/QmlNetworkAccessManager.cpp | 29 ---------------- .../networking/src/QmlNetworkAccessManager.h | 33 ------------------- 8 files changed, 55 insertions(+), 84 deletions(-) rename libraries/networking/src/{QmlAtpReply.cpp => AtpReply.cpp} (86%) rename libraries/networking/src/{QmlAtpReply.h => AtpReply.h} (76%) delete mode 100644 libraries/networking/src/QmlNetworkAccessManager.cpp delete mode 100644 libraries/networking/src/QmlNetworkAccessManager.h diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index ebccc8a1fc..d813e002c7 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "OffscreenGLCanvas.h" #include "GLEscrow.h" @@ -56,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") diff --git a/libraries/networking/src/QmlAtpReply.cpp b/libraries/networking/src/AtpReply.cpp similarity index 86% rename from libraries/networking/src/QmlAtpReply.cpp rename to libraries/networking/src/AtpReply.cpp index a2e537ba1f..4440995ee0 100644 --- a/libraries/networking/src/QmlAtpReply.cpp +++ b/libraries/networking/src/AtpReply.cpp @@ -1,5 +1,5 @@ // -// QmlAtpReply.cpp +// AtpReply.cpp // libraries/networking/src // // Created by Zander Otavka on 8/4/16. @@ -10,30 +10,30 @@ // #include "ResourceManager.h" -#include "QmlAtpReply.h" +#include "AtpReply.h" -QmlAtpReply::QmlAtpReply(const QUrl& url, QObject* parent) : +AtpReply::AtpReply(const QUrl& url, QObject* parent) : _resourceRequest(ResourceManager::createResourceRequest(parent, url)) { setOperation(QNetworkAccessManager::GetOperation); - connect(_resourceRequest, &AssetResourceRequest::progress, this, &QmlAtpReply::downloadProgress); - connect(_resourceRequest, &AssetResourceRequest::finished, this, &QmlAtpReply::handleRequestFinish); + connect(_resourceRequest, &AssetResourceRequest::progress, this, &AtpReply::downloadProgress); + connect(_resourceRequest, &AssetResourceRequest::finished, this, &AtpReply::handleRequestFinish); _resourceRequest->send(); } -QmlAtpReply::~QmlAtpReply() { +AtpReply::~AtpReply() { if (_resourceRequest) { _resourceRequest->deleteLater(); _resourceRequest = nullptr; } } -qint64 QmlAtpReply::bytesAvailable() const { +qint64 AtpReply::bytesAvailable() const { return _content.size() - _readOffset + QIODevice::bytesAvailable(); } -qint64 QmlAtpReply::readData(char* data, qint64 maxSize) { +qint64 AtpReply::readData(char* data, qint64 maxSize) { if (_readOffset < _content.size()) { qint64 readSize = qMin(maxSize, _content.size() - _readOffset); memcpy(data, _content.constData() + _readOffset, readSize); @@ -44,7 +44,7 @@ qint64 QmlAtpReply::readData(char* data, qint64 maxSize) { } } -void QmlAtpReply::handleRequestFinish() { +void AtpReply::handleRequestFinish() { Q_ASSERT(_resourceRequest->getState() == ResourceRequest::State::Finished); switch (_resourceRequest->getResult()) { diff --git a/libraries/networking/src/QmlAtpReply.h b/libraries/networking/src/AtpReply.h similarity index 76% rename from libraries/networking/src/QmlAtpReply.h rename to libraries/networking/src/AtpReply.h index a8f6dfde14..6ed5dd8fb8 100644 --- a/libraries/networking/src/QmlAtpReply.h +++ b/libraries/networking/src/AtpReply.h @@ -1,5 +1,5 @@ // -// QmlAtpReply.h +// AtpReply.h // libraries/networking/src // // Created by Zander Otavka on 8/4/16. @@ -9,19 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_QmlAtpReply_h -#define hifi_QmlAtpReply_h +#ifndef hifi_AtpReply_h +#define hifi_AtpReply_h #include #include #include "AssetResourceRequest.h" -class QmlAtpReply : public QNetworkReply { +class AtpReply : public QNetworkReply { Q_OBJECT public: - QmlAtpReply(const QUrl& url, QObject* parent = Q_NULLPTR); - ~QmlAtpReply(); + AtpReply(const QUrl& url, QObject* parent = Q_NULLPTR); + ~AtpReply(); qint64 bytesAvailable() const override; void abort() override { } bool isSequential() const override { return true; } @@ -37,4 +37,4 @@ private: qint64 _readOffset { 0 }; }; -#endif // hifi_QmlAtpReply_h +#endif // hifi_AtpReply_h diff --git a/libraries/networking/src/NetworkAccessManager.cpp b/libraries/networking/src/NetworkAccessManager.cpp index 97171d5ad7..78a05677fd 100644 --- a/libraries/networking/src/NetworkAccessManager.cpp +++ b/libraries/networking/src/NetworkAccessManager.cpp @@ -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 +#include "AtpReply.h" #include "NetworkAccessManager.h" QThreadStorage 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); + } +} diff --git a/libraries/networking/src/NetworkAccessManager.h b/libraries/networking/src/NetworkAccessManager.h index c4b435adb6..1679ed081c 100644 --- a/libraries/networking/src/NetworkAccessManager.h +++ b/libraries/networking/src/NetworkAccessManager.h @@ -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 +#include +#include /// 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 \ No newline at end of file diff --git a/libraries/networking/src/OAuthNetworkAccessManager.h b/libraries/networking/src/OAuthNetworkAccessManager.h index acfd52e18f..434d9b7c75 100644 --- a/libraries/networking/src/OAuthNetworkAccessManager.h +++ b/libraries/networking/src/OAuthNetworkAccessManager.h @@ -12,12 +12,13 @@ #ifndef hifi_OAuthNetworkAccessManager_h #define hifi_OAuthNetworkAccessManager_h -#include +#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); }; diff --git a/libraries/networking/src/QmlNetworkAccessManager.cpp b/libraries/networking/src/QmlNetworkAccessManager.cpp deleted file mode 100644 index 575bc02f8c..0000000000 --- a/libraries/networking/src/QmlNetworkAccessManager.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// QmlNetworkAccessManager.cpp -// libraries/networking/src -// -// Created by Zander Otavka on 8/4/16. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "QmlAtpReply.h" -#include "QmlNetworkAccessManager.h" - -QNetworkAccessManager* QmlNetworkAccessManagerFactory::create(QObject* parent) { - return new QmlNetworkAccessManager(parent); -} - -QNetworkReply* QmlNetworkAccessManager::createRequest(Operation operation, const QNetworkRequest& request, QIODevice* device) { - if (request.url().scheme() == "atp" && operation == GetOperation) { - return new QmlAtpReply(request.url()); - //auto url = request.url().toString(); - //return QNetworkAccessManager::createRequest(operation, request, device); - } else { - return QNetworkAccessManager::createRequest(operation, request, device); - } -} diff --git a/libraries/networking/src/QmlNetworkAccessManager.h b/libraries/networking/src/QmlNetworkAccessManager.h deleted file mode 100644 index 059d0ebba0..0000000000 --- a/libraries/networking/src/QmlNetworkAccessManager.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// QmlNetworkAccessManager.h -// libraries/networking/src -// -// Created by Zander Otavka on 8/4/16. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_QmlNetworkAccessManager_h -#define hifi_QmlNetworkAccessManager_h - -#include -#include -#include - -class QmlNetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory { -public: - QNetworkAccessManager* create(QObject* parent); -}; - - -class QmlNetworkAccessManager : public QNetworkAccessManager { - Q_OBJECT -public: - QmlNetworkAccessManager(QObject* parent = Q_NULLPTR) : QNetworkAccessManager(parent) { } -protected: - QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* device = Q_NULLPTR); -}; - -#endif // hifi_QmlNetworkAccessManager_h From 36d9f921011cc5e3ea4c5d4efedae4eaadbd4524 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Aug 2016 13:10:02 -0700 Subject: [PATCH 65/78] performance optimization to minimize calling usecTimestampNow --- .../entities-renderer/src/RenderableEntityItem.h | 9 +++++---- .../src/RenderableLightEntityItem.cpp | 4 +++- .../src/RenderablePolyLineEntityItem.cpp | 6 ++++-- .../src/RenderableShapeEntityItem.cpp | 12 +++++++----- .../src/RenderableTextEntityItem.cpp | 4 ++-- .../src/RenderableWebEntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItem.h | 3 ++- .../procedural/src/procedural/Procedural.cpp | 1 + libraries/procedural/src/procedural/Procedural.h | 3 +++ libraries/render-utils/src/MeshPartPayload.cpp | 15 ++++++++++----- libraries/render-utils/src/MeshPartPayload.h | 4 +++- 12 files changed, 43 insertions(+), 24 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 09d6d88c6a..22b6264520 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -96,16 +96,17 @@ public: \ virtual void removeFromScene(EntityItemPointer self, std::shared_ptr 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 checkTransparency() { \ + void checkFading() { \ bool transparent = isTransparent(); \ - if (transparent != prevIsTransparent) { \ + if (transparent != _prevIsTransparent) { \ _renderHelper.notifyChanged(); \ - prevIsTransparent = transparent; \ + _isFading = false; \ + _prevIsTransparent = transparent; \ } \ } \ private: \ SimpleRenderableEntityItem _renderHelper; \ - bool prevIsTransparent { isTransparent() }; + bool _prevIsTransparent { isTransparent() }; #endif // hifi_RenderableEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index fccd52d58c..b7f32cca65 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -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() * Interpolate::calculateFadeRatio(_fadeStartTime); + float intensity = getIntensity() * (_isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); float falloffRadius = getFalloffRadius(); float exponent = getExponent(); float cutoff = glm::radians(getCutoff()); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index ef4c9d6b5d..dc2545b956 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -167,7 +167,7 @@ void RenderablePolyLineEntityItem::update(const quint64& now) { } void RenderablePolyLineEntityItem::render(RenderArgs* args) { - checkTransparency(); + checkFading(); QWriteLocker lock(&_quadReadWriteLock); if (_points.size() < 2 || _normals.size () < 2 || _strokeWidths.size() < 2) { @@ -206,7 +206,9 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); - batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); + if (_isFading) { + batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); + } batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index f557625db2..73c4d99b5e 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -72,8 +72,10 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } bool RenderableShapeEntityItem::isTransparent() { - if (_procedural && _procedural->ready()) { - return Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; + if (_procedural && _procedural->isFading()) { + float isFading = Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; + _procedural->setIsFading(isFading); + return isFading; } else { return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent(); } @@ -83,7 +85,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); Q_ASSERT(args->_batch); - checkTransparency(); + checkFading(); if (!_procedural) { _procedural.reset(new Procedural(getUserData())); @@ -110,12 +112,12 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation()); auto outColor = _procedural->getColor(color); - outColor.a *= Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()); + outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f; batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); DependencyManager::get()->renderShape(batch, MAPPING[_shape]); } else { // FIXME, support instanced multi-shape rendering using multidraw indirect - color.a *= Interpolate::calculateFadeRatio(_fadeStartTime); + color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; auto geometryCache = DependencyManager::get(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); geometryCache->renderSolidShapeInstance(batch, MAPPING[_shape], color, pipeline); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index ccdaa39bdd..20adff83df 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -27,10 +27,10 @@ EntityItemPointer RenderableTextEntityItem::factory(const EntityItemID& entityID void RenderableTextEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Text); - checkTransparency(); + checkFading(); static const float SLIGHTLY_BEHIND = -0.005f; - float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); + 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); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index d6c1c1f761..c712ee506e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -164,7 +164,7 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { } void RenderableWebEntityItem::render(RenderArgs* args) { - checkTransparency(); + checkFading(); #ifdef WANT_EXTRA_DEBUGGING { @@ -210,7 +210,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); } - float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); + float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); DependencyManager::get()->bindSimpleSRGBTexturedUnlitNoTexAlphaProgram(batch); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f774d52274..b9f384f013 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2212,4 +2212,4 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt } QUuid empty; properties.setParentID(empty); -} +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 198928da4e..f12075d191 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -436,7 +436,7 @@ public: QUuid getOwningAvatarID() const { return _owningAvatarID; } void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; } - virtual bool isTransparent() { return Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f; } + virtual bool isTransparent() { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; } protected: @@ -568,6 +568,7 @@ protected: quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _fadeStartTime { usecTimestampNow() }; + bool _isFading { true }; }; #endif // hifi_EntityItem_h diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 7f8ab2db41..cd9edb6621 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -208,6 +208,7 @@ bool Procedural::ready() { if (!_hasStartedFade) { _hasStartedFade = true; + _isFading = true; } return true; } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index dea55f197b..c2939e4a01 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -43,6 +43,8 @@ public: glm::vec4 getColor(const glm::vec4& entityColor); quint64 getFadeStartTime() { return _fadeStartTime; } + bool isFading() { return _isFading; } + void setIsFading(bool isFading) { _isFading = isFading; } uint8_t _version { 1 }; @@ -110,6 +112,7 @@ private: quint64 _fadeStartTime; bool _hasStartedFade { false }; + bool _isFading { false }; }; #endif diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2fa31022ec..38d181e748 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -391,7 +391,7 @@ ItemKey ModelMeshPartPayload::getKey() const { } } - if (Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f) { + if (!_hasFinishedFade) { builder.withTransparent(); } @@ -446,7 +446,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (isTranslucent || Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f) { + if (isTranslucent || !_hasFinishedFade) { builder.withTranslucent(); } if (hasTangents) { @@ -487,7 +487,7 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); } - float fadeRatio = Interpolate::calculateFadeRatio(_fadeStartTime); + float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; if (!_hasColorAttrib || fadeRatio < 1.0f) { batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); } @@ -519,6 +519,8 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: void ModelMeshPartPayload::startFade() { _fadeStartTime = usecTimestampNow(); _hasStartedFade = true; + _prevHasStartedFade = false; + _hasFinishedFade = false; } void ModelMeshPartPayload::render(RenderArgs* args) const { @@ -530,10 +532,13 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { // When an individual mesh parts like this finishes its fade, we will mark the Model as // having render items that need updating - if (_wasFading && !isStillFading()) { + bool nextIsFading = _isFading ? isStillFading() : false; + if (_isFading != nextIsFading || _prevHasStartedFade != _hasStartedFade) { + _isFading = nextIsFading || _prevHasStartedFade != _hasStartedFade; + _hasFinishedFade = _prevHasStartedFade == _hasStartedFade && !_isFading; + _prevHasStartedFade = _hasStartedFade; _model->setRenderItemsNeedUpdate(); } - _wasFading = isStillFading(); gpu::Batch& batch = *(args->_batch); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 8fdafee9b0..67fb660f8b 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -110,7 +110,9 @@ public: private: quint64 _fadeStartTime { 0 }; bool _hasStartedFade { false }; - mutable bool _wasFading { false }; + mutable bool _prevHasStartedFade{ false }; + mutable bool _hasFinishedFade { false }; + mutable bool _isFading { false }; }; namespace render { From 5a4d15dd5bf06190148635a8a8a56b499e0be9ff Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Aug 2016 14:02:42 -0700 Subject: [PATCH 66/78] fix warning --- libraries/gpu/src/gpu/Texture.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 25e4fa549c..f1a8960fa1 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -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::max()); - // for each face of cube texture for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) { From 956078bc91ef652ad1b38f66a3d767f87155de35 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Aug 2016 15:17:36 -0700 Subject: [PATCH 67/78] teleport works with xbox controller --- scripts/system/controllers/teleport.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index fae9b98b96..5ec429fae0 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -232,14 +232,11 @@ function Teleporter() { }; this.rightRay = function() { + 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) : MyAvatar.headOrientation; - 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, { + var rightFinal = Quat.multiply(rightRotation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 @@ -247,7 +244,7 @@ function Teleporter() { var rightPickRay = { origin: rightPosition, - direction: Quat.getUp(rightRotation), + direction: Quat.getUp(pose.valid ? rightRotation : rightFinal), }; this.rightPickRay = rightPickRay; @@ -288,11 +285,11 @@ function Teleporter() { this.leftRay = function() { - var leftPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getPoseValue(Controller.Standard.LeftHand).translation), MyAvatar.position); + 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) : MyAvatar.headOrientation; - var leftRotation = Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(Controller.Standard.LeftHand).rotation) - - var leftFinal = Quat.multiply(leftRotation, Quat.angleAxis(90, { + var leftFinal = Quat.multiply(leftRotation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 @@ -300,7 +297,7 @@ function Teleporter() { var leftPickRay = { origin: leftPosition, - direction: Quat.getUp(leftRotation), + direction: Quat.getUp(pose.valid ? leftRotation : leftFinal), }; this.leftPickRay = leftPickRay; From 6965fb05206dfb8463ba435446f1fe96eefec461 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 9 Aug 2016 14:15:06 -0700 Subject: [PATCH 68/78] refactor system html to split js/css --- scripts/system/html/{ => css}/edit-style.css | 46 +- scripts/system/html/entityList.html | 314 +--- scripts/system/html/entityProperties.html | 1322 +---------------- scripts/system/html/entityProperties.js | 1317 ++++++++++++++++ scripts/system/html/gridControls.html | 142 +- scripts/system/html/{ => js}/colpick.js | 0 scripts/system/html/js/entityList.js | 310 ++++ scripts/system/html/js/entityProperties.js | 1317 ++++++++++++++++ .../system/html/{ => js}/eventBridgeLoader.js | 0 scripts/system/html/js/gridControls.js | 138 ++ .../system/html/{ => js}/jquery-2.1.4.min.js | 0 scripts/system/html/{ => js}/list.min.js | 0 scripts/system/html/{ => js}/spinButtons.js | 0 13 files changed, 3121 insertions(+), 1785 deletions(-) rename scripts/system/html/{ => css}/edit-style.css (94%) create mode 100644 scripts/system/html/entityProperties.js rename scripts/system/html/{ => js}/colpick.js (100%) create mode 100644 scripts/system/html/js/entityList.js create mode 100644 scripts/system/html/js/entityProperties.js rename scripts/system/html/{ => js}/eventBridgeLoader.js (100%) create mode 100644 scripts/system/html/js/gridControls.js rename scripts/system/html/{ => js}/jquery-2.1.4.min.js (100%) rename scripts/system/html/{ => js}/list.min.js (100%) rename scripts/system/html/{ => js}/spinButtons.js (100%) diff --git a/scripts/system/html/edit-style.css b/scripts/system/html/css/edit-style.css similarity index 94% rename from scripts/system/html/edit-style.css rename to scripts/system/html/css/edit-style.css index 19d1cd95a9..0b58cf22ac 100644 --- a/scripts/system/html/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -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; diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index dbc224e9fb..2088898613 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -10,314 +10,12 @@ - - + + - - - + + +

@@ -378,4 +76,4 @@
- \ No newline at end of file + diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 424795981d..01826b8e10 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -11,1325 +11,15 @@ Properties - + - - + + - - - + + + -
diff --git a/scripts/system/html/entityProperties.js b/scripts/system/html/entityProperties.js new file mode 100644 index 0000000000..490579e909 --- /dev/null +++ b/scripts/system/html/entityProperties.js @@ -0,0 +1,1317 @@ +// entityProperties.js +// +// Created by Ryan Huffman on 13 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 PI = 3.14159265358979; +var DEGREES_TO_RADIANS = PI / 180.0; +var RADIANS_TO_DEGREES = 180.0 / PI; +var ICON_FOR_TYPE = { + Box: "V", + Sphere: "n", + Shape: "n", + ParticleEffect: "", + Model: "", + Web: "q", + Text: "l", + Light: "p", + Zone: "o", + PolyVox: "", + Multiple: "" +} + +var colorPickers = []; + +debugPrint = function(message) { + EventBridge.emitWebEvent( + JSON.stringify({ + type:"print", + message: message + }) + ); +}; + +function enableChildren(el, selector) { + els = el.querySelectorAll(selector); + for (var i = 0; i < els.length; i++) { + els[i].removeAttribute('disabled'); + } +} +function disableChildren(el, selector) { + els = el.querySelectorAll(selector); + for (var i = 0; i < els.length; i++) { + els[i].setAttribute('disabled', 'disabled'); + } +} + +function enableProperties() { + enableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); + enableChildren(document, ".colpick"); +} + +function disableProperties() { + disableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); + disableChildren(document, ".colpick"); + for (var i = 0; i < colorPickers.length; i++) { + colorPickers[i].colpickHide(); + } +} + +function showElements(els, show) { + for (var i = 0; i < els.length; i++) { + els[i].style.display = (show) ? 'table' : 'none'; + } +} + +function createEmitCheckedPropertyUpdateFunction(propertyName) { + return function() { + EventBridge.emitWebEvent( + '{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}' + ); + }; +} + +function createEmitCheckedToStringPropertyUpdateFunction(checkboxElement, name, propertyName) { + var newString = ""; + if (checkboxElement.checked) { + newString += name + ""; + } else { + + } + +} + +function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) { + return function () { + var properties = {}; + properties[group] = {}; + properties[group][propertyName] = this.checked; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties + }) + ); + }; +} + +function createEmitNumberPropertyUpdateFunction(propertyName, decimals) { + decimals = decimals == undefined ? 4 : decimals; + return function() { + var value = parseFloat(this.value).toFixed(decimals); + + EventBridge.emitWebEvent( + '{ "type":"update", "properties":{"' + propertyName + '":' + value + '}}' + ); + }; +} +function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { + return function() { + var properties = {}; + properties[group] = {}; + properties[group][propertyName] = this.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + }; +} + + +function createEmitTextPropertyUpdateFunction(propertyName) { + return function() { + var properties = {}; + properties[propertyName] = this.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + }; +} + +function createEmitGroupTextPropertyUpdateFunction(group,propertyName) { + return function() { + var properties = {}; + properties[group] = {}; + properties[group][propertyName] = this.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + }; +} + +function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[property] = { + x: elX.value, + y: elY.value, + z: elZ.value, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, elZ) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[group] = { }; + data.properties[group][property] = { + x: elX.value, + y: elY.value, + z: elZ ? elZ.value : 0, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[property] = { + x: elX.value * multiplier, + y: elY.value * multiplier, + z: elZ.value * multiplier, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) { + return function() { + emitColorPropertyUpdate(property, elRed.value, elGreen.value, elBlue.value); + } +}; + +function emitColorPropertyUpdate(property, red, green, blue, group) { + var data = { + type: "update", + properties: { + } + }; + if (group) { + data.properties[group] = { }; + data.properties[group][property] = { + red: red, + green: green, + blue: blue, + }; + } else { + data.properties[property] = { + red: red, + green: green, + blue: blue, + }; + } + EventBridge.emitWebEvent(JSON.stringify(data)); +}; + + +function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[group] = { }; + + data.properties[group][property] = { + red: elRed.value, + green: elGreen.value, + blue: elBlue.value, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElement, subPropertyString) { + if (subPropertyElement.checked) { + if (propertyValue.indexOf(subPropertyString)) { + propertyValue += subPropertyString + ','; + } + } else { + // We've unchecked, so remove + propertyValue = propertyValue.replace(subPropertyString + ",", ""); + } + + var _properties ={} + _properties[propertyName] = propertyValue; + + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: _properties + }) + ); + +} + +function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) { + var properties = {}; + var parsedData = {}; + try { + parsedData = JSON.parse(userDataElement.value); + } catch(e) {} + + if (!(groupName in parsedData)) { + parsedData[groupName] = {} + } + delete parsedData[groupName][keyName]; + if (checkBoxElement.checked !== defaultValue) { + parsedData[groupName][keyName] = checkBoxElement.checked; + } + + if (Object.keys(parsedData[groupName]).length == 0) { + delete parsedData[groupName]; + } + if (Object.keys(parsedData).length > 0) { + properties['userData'] = JSON.stringify(parsedData); + } else { + properties['userData'] = ''; + } + + userDataElement.value = properties['userData']; + + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); +}; + +function setTextareaScrolling(element) { + var isScrolling = element.scrollHeight > element.offsetHeight; + element.setAttribute("scrolling", isScrolling ? "true" : "false"); +} + +function loaded() { + openEventBridge(function() { + var allSections = []; + var elID = document.getElementById("property-id"); + var elType = document.getElementById("property-type"); + var elTypeIcon = document.getElementById("type-icon"); + var elName = document.getElementById("property-name"); + var elLocked = document.getElementById("property-locked"); + var elVisible = document.getElementById("property-visible"); + var elPositionX = document.getElementById("property-pos-x"); + var elPositionY = document.getElementById("property-pos-y"); + var elPositionZ = document.getElementById("property-pos-z"); + var elMoveSelectionToGrid = document.getElementById("move-selection-to-grid"); + var elMoveAllToGrid = document.getElementById("move-all-to-grid"); + + var elDimensionsX = document.getElementById("property-dim-x"); + var elDimensionsY = document.getElementById("property-dim-y"); + var elDimensionsZ = document.getElementById("property-dim-z"); + var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); + var elRescaleDimensionsPct = document.getElementById("dimension-rescale-pct"); + var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button"); + + var elParentID = document.getElementById("property-parent-id"); + var elParentJointIndex = document.getElementById("property-parent-joint-index"); + + var elRegistrationX = document.getElementById("property-reg-x"); + var elRegistrationY = document.getElementById("property-reg-y"); + var elRegistrationZ = document.getElementById("property-reg-z"); + + var elRotationX = document.getElementById("property-rot-x"); + var elRotationY = document.getElementById("property-rot-y"); + var elRotationZ = document.getElementById("property-rot-z"); + + var elLinearVelocityX = document.getElementById("property-lvel-x"); + var elLinearVelocityY = document.getElementById("property-lvel-y"); + var elLinearVelocityZ = document.getElementById("property-lvel-z"); + var elLinearDamping = document.getElementById("property-ldamping"); + + var elAngularVelocityX = document.getElementById("property-avel-x"); + var elAngularVelocityY = document.getElementById("property-avel-y"); + var elAngularVelocityZ = document.getElementById("property-avel-z"); + var elAngularDamping = document.getElementById("property-adamping"); + + var elRestitution = document.getElementById("property-restitution"); + var elFriction = document.getElementById("property-friction"); + + var elGravityX = document.getElementById("property-grav-x"); + var elGravityY = document.getElementById("property-grav-y"); + var elGravityZ = document.getElementById("property-grav-z"); + + var elAccelerationX = document.getElementById("property-lacc-x"); + var elAccelerationY = document.getElementById("property-lacc-y"); + var elAccelerationZ = document.getElementById("property-lacc-z"); + + var elDensity = document.getElementById("property-density"); + var elCollisionless = document.getElementById("property-collisionless"); + var elDynamic = document.getElementById("property-dynamic" ); + var elCollideStatic = document.getElementById("property-collide-static"); + var elCollideDynamic = document.getElementById("property-collide-dynamic"); + var elCollideKinematic = document.getElementById("property-collide-kinematic"); + var elCollideMyAvatar = document.getElementById("property-collide-myAvatar"); + var elCollideOtherAvatar = document.getElementById("property-collide-otherAvatar"); + var elCollisionSoundURL = document.getElementById("property-collision-sound-url"); + + var elGrabbable = document.getElementById("property-grabbable"); + var elWantsTrigger = document.getElementById("property-wants-trigger"); + var elIgnoreIK = document.getElementById("property-ignore-ik"); + + var elLifetime = document.getElementById("property-lifetime"); + var elScriptURL = document.getElementById("property-script-url"); + /* + FIXME: See FIXME for property-script-url. + var elScriptTimestamp = document.getElementById("property-script-timestamp"); + */ + var elReloadScriptButton = document.getElementById("reload-script-button"); + var elUserData = document.getElementById("property-user-data"); + + var elColorSections = document.querySelectorAll(".color-section"); + var elColor = document.getElementById("property-color"); + var elColorRed = document.getElementById("property-color-red"); + var elColorGreen = document.getElementById("property-color-green"); + var elColorBlue = document.getElementById("property-color-blue"); + + var elShapeSections = document.querySelectorAll(".shape-section"); + allSections.push(elShapeSections); + var elShape = document.getElementById("property-shape"); + + var elLightSections = document.querySelectorAll(".light-section"); + allSections.push(elLightSections); + var elLightSpotLight = document.getElementById("property-light-spot-light"); + var elLightColor = document.getElementById("property-light-color"); + var elLightColorRed = document.getElementById("property-light-color-red"); + var elLightColorGreen = document.getElementById("property-light-color-green"); + var elLightColorBlue = document.getElementById("property-light-color-blue"); + + var elLightIntensity = document.getElementById("property-light-intensity"); + var elLightFalloffRadius = document.getElementById("property-light-falloff-radius"); + var elLightExponent = document.getElementById("property-light-exponent"); + var elLightCutoff = document.getElementById("property-light-cutoff"); + + var elModelSections = document.querySelectorAll(".model-section"); + allSections.push(elModelSections); + var elModelURL = document.getElementById("property-model-url"); + var elShapeType = document.getElementById("property-shape-type"); + var elCompoundShapeURL = document.getElementById("property-compound-shape-url"); + var elModelAnimationURL = document.getElementById("property-model-animation-url"); + var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); + var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); + var elModelAnimationFrame = document.getElementById("property-model-animation-frame"); + var elModelAnimationFirstFrame = document.getElementById("property-model-animation-first-frame"); + var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame"); + var elModelAnimationLoop = document.getElementById("property-model-animation-loop"); + var elModelAnimationHold = document.getElementById("property-model-animation-hold"); + var elModelTextures = document.getElementById("property-model-textures"); + var elModelOriginalTextures = document.getElementById("property-model-original-textures"); + + var elWebSections = document.querySelectorAll(".web-section"); + allSections.push(elWebSections); + var elWebSourceURL = document.getElementById("property-web-source-url"); + + var elDescription = document.getElementById("property-description"); + + var elHyperlinkHref = document.getElementById("property-hyperlink-href"); + + var elHyperlinkSections = document.querySelectorAll(".hyperlink-section"); + + + var elTextSections = document.querySelectorAll(".text-section"); + allSections.push(elTextSections); + var elTextText = document.getElementById("property-text-text"); + var elTextLineHeight = document.getElementById("property-text-line-height"); + var elTextTextColor = document.getElementById("property-text-text-color"); + var elTextFaceCamera = document.getElementById("property-text-face-camera"); + var elTextTextColorRed = document.getElementById("property-text-text-color-red"); + var elTextTextColorGreen = document.getElementById("property-text-text-color-green"); + var elTextTextColorBlue = document.getElementById("property-text-text-color-blue"); + var elTextBackgroundColor = document.getElementById("property-text-background-color"); + var elTextBackgroundColorRed = document.getElementById("property-text-background-color-red"); + var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green"); + var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue"); + + var elZoneSections = document.querySelectorAll(".zone-section"); + allSections.push(elZoneSections); + var elZoneStageSunModelEnabled = document.getElementById("property-zone-stage-sun-model-enabled"); + + var elZoneKeyLightColor = document.getElementById("property-zone-key-light-color"); + var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red"); + var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green"); + var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue"); + var elZoneKeyLightIntensity = document.getElementById("property-zone-key-intensity"); + var elZoneKeyLightAmbientIntensity = document.getElementById("property-zone-key-ambient-intensity"); + var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x"); + var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); + var elZoneKeyLightDirectionZ = document.getElementById("property-zone-key-light-direction-z"); + var elZoneKeyLightAmbientURL = document.getElementById("property-zone-key-ambient-url"); + + var elZoneStageLatitude = document.getElementById("property-zone-stage-latitude"); + var elZoneStageLongitude = document.getElementById("property-zone-stage-longitude"); + var elZoneStageAltitude = document.getElementById("property-zone-stage-altitude"); + var elZoneStageAutomaticHourDay = document.getElementById("property-zone-stage-automatic-hour-day"); + var elZoneStageDay = document.getElementById("property-zone-stage-day"); + var elZoneStageHour = document.getElementById("property-zone-stage-hour"); + + var elZoneBackgroundMode = document.getElementById("property-zone-background-mode"); + + var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color"); + var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red"); + var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green"); + var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue"); + var elZoneSkyboxURL = document.getElementById("property-zone-skybox-url"); + + var elZoneFlyingAllowed = document.getElementById("property-zone-flying-allowed"); + var elZoneGhostingAllowed = document.getElementById("property-zone-ghosting-allowed"); + + var elPolyVoxSections = document.querySelectorAll(".poly-vox-section"); + allSections.push(elPolyVoxSections); + var elVoxelVolumeSizeX = document.getElementById("property-voxel-volume-size-x"); + var elVoxelVolumeSizeY = document.getElementById("property-voxel-volume-size-y"); + var elVoxelVolumeSizeZ = document.getElementById("property-voxel-volume-size-z"); + var elVoxelSurfaceStyle = document.getElementById("property-voxel-surface-style"); + var elXTextureURL = document.getElementById("property-x-texture-url"); + var elYTextureURL = document.getElementById("property-y-texture-url"); + var elZTextureURL = document.getElementById("property-z-texture-url"); + + var elPreviewCameraButton = document.getElementById("preview-camera-button"); + + if (window.EventBridge !== undefined) { + var properties; + EventBridge.scriptEventReceived.connect(function(data) { + data = JSON.parse(data); + if (data.type == "update") { + if (data.selections.length == 0) { + elTypeIcon.style.display = "none"; + elType.innerHTML = "No selection"; + elID.innerHTML = ""; + disableProperties(); + } else if (data.selections.length > 1) { + var selections = data.selections; + + var ids = []; + var types = {}; + var numTypes = 0; + + for (var i = 0; i < selections.length; i++) { + ids.push(selections[i].id); + var type = selections[i].properties.type; + if (types[type] === undefined) { + types[type] = 0; + numTypes += 1; + } + types[type]++; + } + + var type; + if (numTypes === 1) { + type = selections[0].properties.type; + } else { + type = "Multiple"; + } + elType.innerHTML = type + " (" + data.selections.length + ")"; + elTypeIcon.innerHTML = ICON_FOR_TYPE[type]; + elTypeIcon.style.display = "inline-block"; + + elID.innerHTML = ids.join("
"); + + disableProperties(); + } else { + + + properties = data.selections[0].properties; + + elID.innerHTML = properties.id; + + elType.innerHTML = properties.type; + elTypeIcon.innerHTML = ICON_FOR_TYPE[properties.type]; + elTypeIcon.style.display = "inline-block"; + + elLocked.checked = properties.locked; + + if (properties.locked) { + disableProperties(); + elLocked.removeAttribute('disabled'); + } else { + enableProperties(); + } + + elName.value = properties.name; + + elVisible.checked = properties.visible; + + elPositionX.value = properties.position.x.toFixed(4); + elPositionY.value = properties.position.y.toFixed(4); + elPositionZ.value = properties.position.z.toFixed(4); + + elDimensionsX.value = properties.dimensions.x.toFixed(4); + elDimensionsY.value = properties.dimensions.y.toFixed(4); + elDimensionsZ.value = properties.dimensions.z.toFixed(4); + + elParentID.value = properties.parentID; + elParentJointIndex.value = properties.parentJointIndex; + + elRegistrationX.value = properties.registrationPoint.x.toFixed(4); + elRegistrationY.value = properties.registrationPoint.y.toFixed(4); + elRegistrationZ.value = properties.registrationPoint.z.toFixed(4); + + elRotationX.value = properties.rotation.x.toFixed(4); + elRotationY.value = properties.rotation.y.toFixed(4); + elRotationZ.value = properties.rotation.z.toFixed(4); + + elLinearVelocityX.value = properties.velocity.x.toFixed(4); + elLinearVelocityY.value = properties.velocity.y.toFixed(4); + elLinearVelocityZ.value = properties.velocity.z.toFixed(4); + elLinearDamping.value = properties.damping.toFixed(2); + + elAngularVelocityX.value = (properties.angularVelocity.x * RADIANS_TO_DEGREES).toFixed(4); + elAngularVelocityY.value = (properties.angularVelocity.y * RADIANS_TO_DEGREES).toFixed(4); + elAngularVelocityZ.value = (properties.angularVelocity.z * RADIANS_TO_DEGREES).toFixed(4); + elAngularDamping.value = properties.angularDamping.toFixed(4); + + elRestitution.value = properties.restitution.toFixed(4); + elFriction.value = properties.friction.toFixed(4); + + elGravityX.value = properties.gravity.x.toFixed(4); + elGravityY.value = properties.gravity.y.toFixed(4); + elGravityZ.value = properties.gravity.z.toFixed(4); + + elAccelerationX.value = properties.acceleration.x.toFixed(4); + elAccelerationY.value = properties.acceleration.y.toFixed(4); + elAccelerationZ.value = properties.acceleration.z.toFixed(4); + + elDensity.value = properties.density.toFixed(4); + elCollisionless.checked = properties.collisionless; + elDynamic.checked = properties.dynamic; + + elCollideStatic.checked = properties.collidesWith.indexOf("static") > -1; + elCollideKinematic.checked = properties.collidesWith.indexOf("kinematic") > -1; + elCollideDynamic.checked = properties.collidesWith.indexOf("dynamic") > -1; + elCollideMyAvatar.checked = properties.collidesWith.indexOf("myAvatar") > -1; + elCollideOtherAvatar.checked = properties.collidesWith.indexOf("otherAvatar") > -1; + + elGrabbable.checked = properties.dynamic; + elWantsTrigger.checked = false; + elIgnoreIK.checked = false; + var parsedUserData = {} + try { + parsedUserData = JSON.parse(properties.userData); + + if ("grabbableKey" in parsedUserData) { + if ("grabbable" in parsedUserData["grabbableKey"]) { + elGrabbable.checked = parsedUserData["grabbableKey"].grabbable; + } + if ("wantsTrigger" in parsedUserData["grabbableKey"]) { + elWantsTrigger.checked = parsedUserData["grabbableKey"].wantsTrigger; + } + if ("ignoreIK" in parsedUserData["grabbableKey"]) { + elIgnoreIK.checked = parsedUserData["grabbableKey"].ignoreIK; + } + } + } catch(e) {} + + elCollisionSoundURL.value = properties.collisionSoundURL; + elLifetime.value = properties.lifetime; + elScriptURL.value = properties.script; + /* + FIXME: See FIXME for property-script-url. + elScriptTimestamp.value = properties.scriptTimestamp; + */ + elUserData.value = properties.userData; + setTextareaScrolling(elUserData); + + elHyperlinkHref.value = properties.href; + elDescription.value = properties.description; + + for (var i = 0; i < allSections.length; i++) { + for (var j = 0; j < allSections[i].length; j++) { + allSections[i][j].style.display = 'none'; + } + } + + for (var i = 0; i < elHyperlinkSections.length; i++) { + elHyperlinkSections[i].style.display = 'table'; + } + + if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere") { + for (var i = 0; i < elShapeSections.length; i++) { + elShapeSections[i].style.display = 'table'; + } + elShape.value = properties.shape; + setDropdownText(elShape); + + } else { + for (var i = 0; i < elShapeSections.length; i++) { + elShapeSections[i].style.display = 'none'; + } + } + + if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") { + for (var i = 0; i < elColorSections.length; i++) { + elColorSections[i].style.display = 'table'; + } + elColorRed.value = properties.color.red; + elColorGreen.value = properties.color.green; + elColorBlue.value = properties.color.blue; + elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; + } else { + for (var i = 0; i < elColorSections.length; i++) { + elColorSections[i].style.display = 'none'; + } + } + + if (properties.type == "Model") { + for (var i = 0; i < elModelSections.length; i++) { + elModelSections[i].style.display = 'table'; + } + + elModelURL.value = properties.modelURL; + elShapeType.value = properties.shapeType; + setDropdownText(elShapeType); + elCompoundShapeURL.value = properties.compoundShapeURL; + elModelAnimationURL.value = properties.animation.url; + elModelAnimationPlaying.checked = properties.animation.running; + elModelAnimationFPS.value = properties.animation.fps; + elModelAnimationFrame.value = properties.animation.currentFrame; + elModelAnimationFirstFrame.value = properties.animation.firstFrame; + elModelAnimationLastFrame.value = properties.animation.lastFrame; + elModelAnimationLoop.checked = properties.animation.loop; + elModelAnimationHold.checked = properties.animation.hold; + elModelTextures.value = properties.textures; + setTextareaScrolling(elModelTextures); + elModelOriginalTextures.value = properties.originalTextures; + setTextareaScrolling(elModelOriginalTextures); + } else if (properties.type == "Web") { + for (var i = 0; i < elWebSections.length; i++) { + elWebSections[i].style.display = 'table'; + } + for (var i = 0; i < elHyperlinkSections.length; i++) { + elHyperlinkSections[i].style.display = 'none'; + } + + elWebSourceURL.value = properties.sourceUrl; + } else if (properties.type == "Text") { + for (var i = 0; i < elTextSections.length; i++) { + elTextSections[i].style.display = 'table'; + } + + elTextText.value = properties.text; + elTextLineHeight.value = properties.lineHeight.toFixed(4); + elTextFaceCamera = properties.faceCamera; + elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")"; + elTextTextColorRed.value = properties.textColor.red; + elTextTextColorGreen.value = properties.textColor.green; + elTextTextColorBlue.value = properties.textColor.blue; + elTextBackgroundColorRed.value = properties.backgroundColor.red; + elTextBackgroundColorGreen.value = properties.backgroundColor.green; + elTextBackgroundColorBlue.value = properties.backgroundColor.blue; + } else if (properties.type == "Light") { + for (var i = 0; i < elLightSections.length; i++) { + elLightSections[i].style.display = 'table'; + } + + elLightSpotLight.checked = properties.isSpotlight; + + elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; + elLightColorRed.value = properties.color.red; + elLightColorGreen.value = properties.color.green; + elLightColorBlue.value = properties.color.blue; + + elLightIntensity.value = properties.intensity.toFixed(1); + elLightFalloffRadius.value = properties.falloffRadius.toFixed(1); + elLightExponent.value = properties.exponent.toFixed(2); + elLightCutoff.value = properties.cutoff.toFixed(2); + } else if (properties.type == "Zone") { + for (var i = 0; i < elZoneSections.length; i++) { + elZoneSections[i].style.display = 'table'; + } + + elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled; + elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; + elZoneKeyLightColorRed.value = properties.keyLight.color.red; + elZoneKeyLightColorGreen.value = properties.keyLight.color.green; + elZoneKeyLightColorBlue.value = properties.keyLight.color.blue; + elZoneKeyLightIntensity.value = properties.keyLight.intensity.toFixed(2); + elZoneKeyLightAmbientIntensity.value = properties.keyLight.ambientIntensity.toFixed(2); + elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2); + elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); + elZoneKeyLightAmbientURL.value = properties.keyLight.ambientURL; + + + elZoneStageLatitude.value = properties.stage.latitude.toFixed(2); + elZoneStageLongitude.value = properties.stage.longitude.toFixed(2); + elZoneStageAltitude.value = properties.stage.altitude.toFixed(2); + elZoneStageAutomaticHourDay.checked = properties.stage.automaticHourDay; + elZoneStageDay.value = properties.stage.day; + elZoneStageHour.value = properties.stage.hour; + elShapeType.value = properties.shapeType; + elCompoundShapeURL.value = properties.compoundShapeURL; + + elZoneBackgroundMode.value = properties.backgroundMode; + setDropdownText(elZoneBackgroundMode); + + elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")"; + elZoneSkyboxColorRed.value = properties.skybox.color.red; + elZoneSkyboxColorGreen.value = properties.skybox.color.green; + elZoneSkyboxColorBlue.value = properties.skybox.color.blue; + elZoneSkyboxURL.value = properties.skybox.url; + + elZoneFlyingAllowed.checked = properties.flyingAllowed; + elZoneGhostingAllowed.checked = properties.ghostingAllowed; + + showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox'); + } else if (properties.type == "PolyVox") { + for (var i = 0; i < elPolyVoxSections.length; i++) { + elPolyVoxSections[i].style.display = 'table'; + } + + elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); + elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); + elVoxelVolumeSizeZ.value = properties.voxelVolumeSize.z.toFixed(2); + elVoxelSurfaceStyle.value = properties.voxelSurfaceStyle; + setDropdownText(elVoxelSurfaceStyle); + elXTextureURL.value = properties.xTextureURL; + elYTextureURL.value = properties.yTextureURL; + elZTextureURL.value = properties.zTextureURL; + } + + var activeElement = document.activeElement; + + if(typeof activeElement.select!=="undefined"){ + activeElement.select(); + } + } + } + }); + } + + elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked')); + elName.addEventListener('change', createEmitTextPropertyUpdateFunction('name')); + elHyperlinkHref.addEventListener('change', createEmitTextPropertyUpdateFunction('href')); + elDescription.addEventListener('change', createEmitTextPropertyUpdateFunction('description')); + elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible')); + + var positionChangeFunction = createEmitVec3PropertyUpdateFunction( + 'position', elPositionX, elPositionY, elPositionZ); + elPositionX.addEventListener('change', positionChangeFunction); + elPositionY.addEventListener('change', positionChangeFunction); + elPositionZ.addEventListener('change', positionChangeFunction); + + var dimensionsChangeFunction = createEmitVec3PropertyUpdateFunction( + 'dimensions', elDimensionsX, elDimensionsY, elDimensionsZ); + elDimensionsX.addEventListener('change', dimensionsChangeFunction); + elDimensionsY.addEventListener('change', dimensionsChangeFunction); + elDimensionsZ.addEventListener('change', dimensionsChangeFunction); + + elParentID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentID')); + elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex')); + + var registrationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ); + elRegistrationX.addEventListener('change', registrationChangeFunction); + elRegistrationY.addEventListener('change', registrationChangeFunction); + elRegistrationZ.addEventListener('change', registrationChangeFunction); + + var rotationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'rotation', elRotationX, elRotationY, elRotationZ); + elRotationX.addEventListener('change', rotationChangeFunction); + elRotationY.addEventListener('change', rotationChangeFunction); + elRotationZ.addEventListener('change', rotationChangeFunction); + + var velocityChangeFunction = createEmitVec3PropertyUpdateFunction( + 'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ); + elLinearVelocityX.addEventListener('change', velocityChangeFunction); + elLinearVelocityY.addEventListener('change', velocityChangeFunction); + elLinearVelocityZ.addEventListener('change', velocityChangeFunction); + elLinearDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('damping')); + + var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( + 'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ, DEGREES_TO_RADIANS); + elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction); + elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction); + elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction); + elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping')); + + elRestitution.addEventListener('change', createEmitNumberPropertyUpdateFunction('restitution')); + elFriction.addEventListener('change', createEmitNumberPropertyUpdateFunction('friction')); + + var gravityChangeFunction = createEmitVec3PropertyUpdateFunction( + 'gravity', elGravityX, elGravityY, elGravityZ); + elGravityX.addEventListener('change', gravityChangeFunction); + elGravityY.addEventListener('change', gravityChangeFunction); + elGravityZ.addEventListener('change', gravityChangeFunction); + + var accelerationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'acceleration', elAccelerationX, elAccelerationY, elAccelerationZ); + elAccelerationX.addEventListener('change', accelerationChangeFunction); + elAccelerationY.addEventListener('change', accelerationChangeFunction); + elAccelerationZ.addEventListener('change', accelerationChangeFunction); + + elDensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('density')); + elCollisionless.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionless')); + elDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('dynamic')); + + elCollideDynamic.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideDynamic, 'dynamic'); + }); + + elCollideKinematic.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideKinematic, 'kinematic'); + }); + + elCollideStatic.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideStatic, 'static'); + }); + elCollideMyAvatar.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideMyAvatar, 'myAvatar'); + }); + elCollideOtherAvatar.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideOtherAvatar, 'otherAvatar'); + }); + + elGrabbable.addEventListener('change', function() { + userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); + }); + elWantsTrigger.addEventListener('change', function() { + userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); + }); + elIgnoreIK.addEventListener('change', function() { + userDataChanger("grabbableKey", "ignoreIK", elIgnoreIK, elUserData, false); + }); + + elCollisionSoundURL.addEventListener('change', createEmitTextPropertyUpdateFunction('collisionSoundURL')); + + elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); + elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); + /* + FIXME: See FIXME for property-script-url. + elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp')); + */ + elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); + + var colorChangeFunction = createEmitColorPropertyUpdateFunction( + 'color', elColorRed, elColorGreen, elColorBlue); + elColorRed.addEventListener('change', colorChangeFunction); + elColorGreen.addEventListener('change', colorChangeFunction); + elColorBlue.addEventListener('change', colorChangeFunction); + colorPickers.push($('#property-color').colpick({ + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function (colpick) { + $('#property-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); + } + })); + + elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight')); + + var lightColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'color', elLightColorRed, elLightColorGreen, elLightColorBlue); + elLightColorRed.addEventListener('change', lightColorChangeFunction); + elLightColorGreen.addEventListener('change', lightColorChangeFunction); + elLightColorBlue.addEventListener('change', lightColorChangeFunction); + colorPickers.push($('#property-light-color').colpick({ + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function (colpick) { + $('#property-light-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-light-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); + } + })); + + elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity', 1)); + elLightFalloffRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('falloffRadius', 1)); + elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent', 2)); + elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff', 2)); + + elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); + + elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); + + elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL')); + elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType')); + elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL')); + + elModelAnimationURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('animation', 'url')); + elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation','running')); + elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation','fps')); + elModelAnimationFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'currentFrame')); + elModelAnimationFirstFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'firstFrame')); + elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame')); + elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop')); + elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold')); + + elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); + + elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); + elTextFaceCamera.addEventListener('change', createEmitCheckedPropertyUpdateFunction('faceCamera')); + elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); + var textTextColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'textColor', elTextTextColorRed, elTextTextColorGreen, elTextTextColorBlue); + elTextTextColorRed.addEventListener('change', textTextColorChangeFunction); + elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction); + elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction); + colorPickers.push($('#property-text-text-color').colpick({ + colorScheme:'dark', + layout:'hex', + color: '000000', + onShow: function (colpick) { + $('#property-text-text-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-text-text-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + $(el).attr('active', 'false'); + emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); + } + })); + + var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue); + elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction); + elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); + elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); + colorPickers.push($('#property-text-background-color').colpick({ + colorScheme:'dark', + layout:'hex', + color:'000000', + onShow: function (colpick) { + $('#property-text-background-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-text-background-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); + } + })); + + elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled')); + colorPickers.push($('#property-zone-key-light-color').colpick({ + colorScheme:'dark', + layout:'hex', + color:'000000', + onShow: function (colpick) { + $('#property-zone-key-light-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-zone-key-light-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); + } + })); + var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight','color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); + elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightColorGreen.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity')); + elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity')); + elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL')); + var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY); + elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction); + elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); + + elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude')); + elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude')); + elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude')); + elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','automaticHourDay')); + elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day')); + elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour')); + + + elZoneBackgroundMode.addEventListener('change', createEmitTextPropertyUpdateFunction('backgroundMode')); + var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox','color', + elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue); + elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction); + elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction); + elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction); + colorPickers.push($('#property-zone-skybox-color').colpick({ + colorScheme:'dark', + layout:'hex', + color:'000000', + onShow: function (colpick) { + $('#property-zone-skybox-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-zone-skybox-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); + } + })); + + elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url')); + + elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed')); + elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed')); + + var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction( + 'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ); + elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction); + elVoxelVolumeSizeY.addEventListener('change', voxelVolumeSizeChangeFunction); + elVoxelVolumeSizeZ.addEventListener('change', voxelVolumeSizeChangeFunction); + elVoxelSurfaceStyle.addEventListener('change', createEmitTextPropertyUpdateFunction('voxelSurfaceStyle')); + elXTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('xTextureURL')); + elYTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('yTextureURL')); + elZTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('zTextureURL')); + + elMoveSelectionToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveSelectionToGrid", + })); + }); + elMoveAllToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveAllToGrid", + })); + }); + elResetToNaturalDimensions.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "resetToNaturalDimensions", + })); + }); + elRescaleDimensionsButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "rescaleDimensions", + percentage: parseInt(elRescaleDimensionsPct.value), + })); + }); + /* + FIXME: See FIXME for property-script-url. + elReloadScriptButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "reloadScript" + })); + }); + */ + elPreviewCameraButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "previewCamera" + })); + }); + + window.onblur = function() { + // Fake a change event + var ev = document.createEvent("HTMLEvents"); + ev.initEvent("change", true, true); + document.activeElement.dispatchEvent(ev); + } + + // For input and textarea elements, select all of the text on focus + // WebKit-based browsers, such as is used with QWebView, have a quirk + // where the mouseup event comes after the focus event, causing the + // text to be deselected immediately after selecting all of the text. + // To make this work we block the first mouseup event after the elements + // received focus. If we block all mouseup events the user will not + // be able to click within the selected text. + // We also check to see if the value has changed to make sure we aren't + // blocking a mouse-up event when clicking on an input spinner. + var els = document.querySelectorAll("input, textarea"); + for (var i = 0; i < els.length; i++) { + var clicked = false; + var originalText; + els[i].onfocus = function(e) { + originalText = this.value; + this.select(); + clicked = false; + }; + els[i].onmouseup = function(e) { + if (!clicked && originalText == this.value) { + e.preventDefault(); + } + clicked = true; + }; + } + }); + + // Collapsible sections + var elCollapsible = document.getElementsByClassName("section-header"); + + var toggleCollapsedEvent = function (event) { + var element = event.target; + if (element.nodeName !== "DIV") { + element = element.parentNode; + } + var isCollapsed = element.getAttribute("collapsed") !== "true"; + element.setAttribute("collapsed", isCollapsed ? "true" : "false"); + element.getElementsByTagName("span")[0].textContent = isCollapsed ? "L" : "M"; + }; + + for (var i = 0, length = elCollapsible.length; i < length; i++) { + var element = elCollapsible[i]; + element.addEventListener("click", toggleCollapsedEvent, true); + }; + + + // Textarea scrollbars + var elTextareas = document.getElementsByTagName("TEXTAREA"); + + var textareaOnChangeEvent = function (event) { + setTextareaScrolling(event.target); + } + + for (var i = 0, length = elTextareas.length; i < length; i++) { + var element = elTextareas[i]; + setTextareaScrolling(element); + element.addEventListener("input", textareaOnChangeEvent, false); + element.addEventListener("change", textareaOnChangeEvent, false); + /* FIXME: Detect and update textarea scrolling attribute on resize. Unfortunately textarea doesn't have a resize + event; mouseup is a partial stand-in but doesn't handle resizing if mouse moves outside textarea rectangle. */ + element.addEventListener("mouseup", textareaOnChangeEvent, false); + }; + + // Dropdowns + // For each dropdown the following replacement is created in place of the oriringal dropdown... + // Structure created: + //
+ //
display textcarat
+ //
+ //
    + //
  • 0) { + var el = elDropdowns[0]; + el.parentNode.removeChild(el); + elDropdowns = document.getElementsByTagName("select"); + } + + 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); +} + diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index 4b18a8555b..f7f206d702 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -10,144 +10,14 @@ - + - - + + - - - + + +
    diff --git a/scripts/system/html/colpick.js b/scripts/system/html/js/colpick.js similarity index 100% rename from scripts/system/html/colpick.js rename to scripts/system/html/js/colpick.js diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js new file mode 100644 index 0000000000..8e5e190068 --- /dev/null +++ b/scripts/system/html/js/entityList.js @@ -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); +} + diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js new file mode 100644 index 0000000000..490579e909 --- /dev/null +++ b/scripts/system/html/js/entityProperties.js @@ -0,0 +1,1317 @@ +// entityProperties.js +// +// Created by Ryan Huffman on 13 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 PI = 3.14159265358979; +var DEGREES_TO_RADIANS = PI / 180.0; +var RADIANS_TO_DEGREES = 180.0 / PI; +var ICON_FOR_TYPE = { + Box: "V", + Sphere: "n", + Shape: "n", + ParticleEffect: "", + Model: "", + Web: "q", + Text: "l", + Light: "p", + Zone: "o", + PolyVox: "", + Multiple: "" +} + +var colorPickers = []; + +debugPrint = function(message) { + EventBridge.emitWebEvent( + JSON.stringify({ + type:"print", + message: message + }) + ); +}; + +function enableChildren(el, selector) { + els = el.querySelectorAll(selector); + for (var i = 0; i < els.length; i++) { + els[i].removeAttribute('disabled'); + } +} +function disableChildren(el, selector) { + els = el.querySelectorAll(selector); + for (var i = 0; i < els.length; i++) { + els[i].setAttribute('disabled', 'disabled'); + } +} + +function enableProperties() { + enableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); + enableChildren(document, ".colpick"); +} + +function disableProperties() { + disableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); + disableChildren(document, ".colpick"); + for (var i = 0; i < colorPickers.length; i++) { + colorPickers[i].colpickHide(); + } +} + +function showElements(els, show) { + for (var i = 0; i < els.length; i++) { + els[i].style.display = (show) ? 'table' : 'none'; + } +} + +function createEmitCheckedPropertyUpdateFunction(propertyName) { + return function() { + EventBridge.emitWebEvent( + '{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}' + ); + }; +} + +function createEmitCheckedToStringPropertyUpdateFunction(checkboxElement, name, propertyName) { + var newString = ""; + if (checkboxElement.checked) { + newString += name + ""; + } else { + + } + +} + +function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) { + return function () { + var properties = {}; + properties[group] = {}; + properties[group][propertyName] = this.checked; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties + }) + ); + }; +} + +function createEmitNumberPropertyUpdateFunction(propertyName, decimals) { + decimals = decimals == undefined ? 4 : decimals; + return function() { + var value = parseFloat(this.value).toFixed(decimals); + + EventBridge.emitWebEvent( + '{ "type":"update", "properties":{"' + propertyName + '":' + value + '}}' + ); + }; +} +function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { + return function() { + var properties = {}; + properties[group] = {}; + properties[group][propertyName] = this.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + }; +} + + +function createEmitTextPropertyUpdateFunction(propertyName) { + return function() { + var properties = {}; + properties[propertyName] = this.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + }; +} + +function createEmitGroupTextPropertyUpdateFunction(group,propertyName) { + return function() { + var properties = {}; + properties[group] = {}; + properties[group][propertyName] = this.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + }; +} + +function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[property] = { + x: elX.value, + y: elY.value, + z: elZ.value, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, elZ) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[group] = { }; + data.properties[group][property] = { + x: elX.value, + y: elY.value, + z: elZ ? elZ.value : 0, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[property] = { + x: elX.value * multiplier, + y: elY.value * multiplier, + z: elZ.value * multiplier, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) { + return function() { + emitColorPropertyUpdate(property, elRed.value, elGreen.value, elBlue.value); + } +}; + +function emitColorPropertyUpdate(property, red, green, blue, group) { + var data = { + type: "update", + properties: { + } + }; + if (group) { + data.properties[group] = { }; + data.properties[group][property] = { + red: red, + green: green, + blue: blue, + }; + } else { + data.properties[property] = { + red: red, + green: green, + blue: blue, + }; + } + EventBridge.emitWebEvent(JSON.stringify(data)); +}; + + +function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[group] = { }; + + data.properties[group][property] = { + red: elRed.value, + green: elGreen.value, + blue: elBlue.value, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } +}; + +function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElement, subPropertyString) { + if (subPropertyElement.checked) { + if (propertyValue.indexOf(subPropertyString)) { + propertyValue += subPropertyString + ','; + } + } else { + // We've unchecked, so remove + propertyValue = propertyValue.replace(subPropertyString + ",", ""); + } + + var _properties ={} + _properties[propertyName] = propertyValue; + + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: _properties + }) + ); + +} + +function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) { + var properties = {}; + var parsedData = {}; + try { + parsedData = JSON.parse(userDataElement.value); + } catch(e) {} + + if (!(groupName in parsedData)) { + parsedData[groupName] = {} + } + delete parsedData[groupName][keyName]; + if (checkBoxElement.checked !== defaultValue) { + parsedData[groupName][keyName] = checkBoxElement.checked; + } + + if (Object.keys(parsedData[groupName]).length == 0) { + delete parsedData[groupName]; + } + if (Object.keys(parsedData).length > 0) { + properties['userData'] = JSON.stringify(parsedData); + } else { + properties['userData'] = ''; + } + + userDataElement.value = properties['userData']; + + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); +}; + +function setTextareaScrolling(element) { + var isScrolling = element.scrollHeight > element.offsetHeight; + element.setAttribute("scrolling", isScrolling ? "true" : "false"); +} + +function loaded() { + openEventBridge(function() { + var allSections = []; + var elID = document.getElementById("property-id"); + var elType = document.getElementById("property-type"); + var elTypeIcon = document.getElementById("type-icon"); + var elName = document.getElementById("property-name"); + var elLocked = document.getElementById("property-locked"); + var elVisible = document.getElementById("property-visible"); + var elPositionX = document.getElementById("property-pos-x"); + var elPositionY = document.getElementById("property-pos-y"); + var elPositionZ = document.getElementById("property-pos-z"); + var elMoveSelectionToGrid = document.getElementById("move-selection-to-grid"); + var elMoveAllToGrid = document.getElementById("move-all-to-grid"); + + var elDimensionsX = document.getElementById("property-dim-x"); + var elDimensionsY = document.getElementById("property-dim-y"); + var elDimensionsZ = document.getElementById("property-dim-z"); + var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); + var elRescaleDimensionsPct = document.getElementById("dimension-rescale-pct"); + var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button"); + + var elParentID = document.getElementById("property-parent-id"); + var elParentJointIndex = document.getElementById("property-parent-joint-index"); + + var elRegistrationX = document.getElementById("property-reg-x"); + var elRegistrationY = document.getElementById("property-reg-y"); + var elRegistrationZ = document.getElementById("property-reg-z"); + + var elRotationX = document.getElementById("property-rot-x"); + var elRotationY = document.getElementById("property-rot-y"); + var elRotationZ = document.getElementById("property-rot-z"); + + var elLinearVelocityX = document.getElementById("property-lvel-x"); + var elLinearVelocityY = document.getElementById("property-lvel-y"); + var elLinearVelocityZ = document.getElementById("property-lvel-z"); + var elLinearDamping = document.getElementById("property-ldamping"); + + var elAngularVelocityX = document.getElementById("property-avel-x"); + var elAngularVelocityY = document.getElementById("property-avel-y"); + var elAngularVelocityZ = document.getElementById("property-avel-z"); + var elAngularDamping = document.getElementById("property-adamping"); + + var elRestitution = document.getElementById("property-restitution"); + var elFriction = document.getElementById("property-friction"); + + var elGravityX = document.getElementById("property-grav-x"); + var elGravityY = document.getElementById("property-grav-y"); + var elGravityZ = document.getElementById("property-grav-z"); + + var elAccelerationX = document.getElementById("property-lacc-x"); + var elAccelerationY = document.getElementById("property-lacc-y"); + var elAccelerationZ = document.getElementById("property-lacc-z"); + + var elDensity = document.getElementById("property-density"); + var elCollisionless = document.getElementById("property-collisionless"); + var elDynamic = document.getElementById("property-dynamic" ); + var elCollideStatic = document.getElementById("property-collide-static"); + var elCollideDynamic = document.getElementById("property-collide-dynamic"); + var elCollideKinematic = document.getElementById("property-collide-kinematic"); + var elCollideMyAvatar = document.getElementById("property-collide-myAvatar"); + var elCollideOtherAvatar = document.getElementById("property-collide-otherAvatar"); + var elCollisionSoundURL = document.getElementById("property-collision-sound-url"); + + var elGrabbable = document.getElementById("property-grabbable"); + var elWantsTrigger = document.getElementById("property-wants-trigger"); + var elIgnoreIK = document.getElementById("property-ignore-ik"); + + var elLifetime = document.getElementById("property-lifetime"); + var elScriptURL = document.getElementById("property-script-url"); + /* + FIXME: See FIXME for property-script-url. + var elScriptTimestamp = document.getElementById("property-script-timestamp"); + */ + var elReloadScriptButton = document.getElementById("reload-script-button"); + var elUserData = document.getElementById("property-user-data"); + + var elColorSections = document.querySelectorAll(".color-section"); + var elColor = document.getElementById("property-color"); + var elColorRed = document.getElementById("property-color-red"); + var elColorGreen = document.getElementById("property-color-green"); + var elColorBlue = document.getElementById("property-color-blue"); + + var elShapeSections = document.querySelectorAll(".shape-section"); + allSections.push(elShapeSections); + var elShape = document.getElementById("property-shape"); + + var elLightSections = document.querySelectorAll(".light-section"); + allSections.push(elLightSections); + var elLightSpotLight = document.getElementById("property-light-spot-light"); + var elLightColor = document.getElementById("property-light-color"); + var elLightColorRed = document.getElementById("property-light-color-red"); + var elLightColorGreen = document.getElementById("property-light-color-green"); + var elLightColorBlue = document.getElementById("property-light-color-blue"); + + var elLightIntensity = document.getElementById("property-light-intensity"); + var elLightFalloffRadius = document.getElementById("property-light-falloff-radius"); + var elLightExponent = document.getElementById("property-light-exponent"); + var elLightCutoff = document.getElementById("property-light-cutoff"); + + var elModelSections = document.querySelectorAll(".model-section"); + allSections.push(elModelSections); + var elModelURL = document.getElementById("property-model-url"); + var elShapeType = document.getElementById("property-shape-type"); + var elCompoundShapeURL = document.getElementById("property-compound-shape-url"); + var elModelAnimationURL = document.getElementById("property-model-animation-url"); + var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); + var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); + var elModelAnimationFrame = document.getElementById("property-model-animation-frame"); + var elModelAnimationFirstFrame = document.getElementById("property-model-animation-first-frame"); + var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame"); + var elModelAnimationLoop = document.getElementById("property-model-animation-loop"); + var elModelAnimationHold = document.getElementById("property-model-animation-hold"); + var elModelTextures = document.getElementById("property-model-textures"); + var elModelOriginalTextures = document.getElementById("property-model-original-textures"); + + var elWebSections = document.querySelectorAll(".web-section"); + allSections.push(elWebSections); + var elWebSourceURL = document.getElementById("property-web-source-url"); + + var elDescription = document.getElementById("property-description"); + + var elHyperlinkHref = document.getElementById("property-hyperlink-href"); + + var elHyperlinkSections = document.querySelectorAll(".hyperlink-section"); + + + var elTextSections = document.querySelectorAll(".text-section"); + allSections.push(elTextSections); + var elTextText = document.getElementById("property-text-text"); + var elTextLineHeight = document.getElementById("property-text-line-height"); + var elTextTextColor = document.getElementById("property-text-text-color"); + var elTextFaceCamera = document.getElementById("property-text-face-camera"); + var elTextTextColorRed = document.getElementById("property-text-text-color-red"); + var elTextTextColorGreen = document.getElementById("property-text-text-color-green"); + var elTextTextColorBlue = document.getElementById("property-text-text-color-blue"); + var elTextBackgroundColor = document.getElementById("property-text-background-color"); + var elTextBackgroundColorRed = document.getElementById("property-text-background-color-red"); + var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green"); + var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue"); + + var elZoneSections = document.querySelectorAll(".zone-section"); + allSections.push(elZoneSections); + var elZoneStageSunModelEnabled = document.getElementById("property-zone-stage-sun-model-enabled"); + + var elZoneKeyLightColor = document.getElementById("property-zone-key-light-color"); + var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red"); + var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green"); + var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue"); + var elZoneKeyLightIntensity = document.getElementById("property-zone-key-intensity"); + var elZoneKeyLightAmbientIntensity = document.getElementById("property-zone-key-ambient-intensity"); + var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x"); + var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); + var elZoneKeyLightDirectionZ = document.getElementById("property-zone-key-light-direction-z"); + var elZoneKeyLightAmbientURL = document.getElementById("property-zone-key-ambient-url"); + + var elZoneStageLatitude = document.getElementById("property-zone-stage-latitude"); + var elZoneStageLongitude = document.getElementById("property-zone-stage-longitude"); + var elZoneStageAltitude = document.getElementById("property-zone-stage-altitude"); + var elZoneStageAutomaticHourDay = document.getElementById("property-zone-stage-automatic-hour-day"); + var elZoneStageDay = document.getElementById("property-zone-stage-day"); + var elZoneStageHour = document.getElementById("property-zone-stage-hour"); + + var elZoneBackgroundMode = document.getElementById("property-zone-background-mode"); + + var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color"); + var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red"); + var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green"); + var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue"); + var elZoneSkyboxURL = document.getElementById("property-zone-skybox-url"); + + var elZoneFlyingAllowed = document.getElementById("property-zone-flying-allowed"); + var elZoneGhostingAllowed = document.getElementById("property-zone-ghosting-allowed"); + + var elPolyVoxSections = document.querySelectorAll(".poly-vox-section"); + allSections.push(elPolyVoxSections); + var elVoxelVolumeSizeX = document.getElementById("property-voxel-volume-size-x"); + var elVoxelVolumeSizeY = document.getElementById("property-voxel-volume-size-y"); + var elVoxelVolumeSizeZ = document.getElementById("property-voxel-volume-size-z"); + var elVoxelSurfaceStyle = document.getElementById("property-voxel-surface-style"); + var elXTextureURL = document.getElementById("property-x-texture-url"); + var elYTextureURL = document.getElementById("property-y-texture-url"); + var elZTextureURL = document.getElementById("property-z-texture-url"); + + var elPreviewCameraButton = document.getElementById("preview-camera-button"); + + if (window.EventBridge !== undefined) { + var properties; + EventBridge.scriptEventReceived.connect(function(data) { + data = JSON.parse(data); + if (data.type == "update") { + if (data.selections.length == 0) { + elTypeIcon.style.display = "none"; + elType.innerHTML = "No selection"; + elID.innerHTML = ""; + disableProperties(); + } else if (data.selections.length > 1) { + var selections = data.selections; + + var ids = []; + var types = {}; + var numTypes = 0; + + for (var i = 0; i < selections.length; i++) { + ids.push(selections[i].id); + var type = selections[i].properties.type; + if (types[type] === undefined) { + types[type] = 0; + numTypes += 1; + } + types[type]++; + } + + var type; + if (numTypes === 1) { + type = selections[0].properties.type; + } else { + type = "Multiple"; + } + elType.innerHTML = type + " (" + data.selections.length + ")"; + elTypeIcon.innerHTML = ICON_FOR_TYPE[type]; + elTypeIcon.style.display = "inline-block"; + + elID.innerHTML = ids.join("
    "); + + disableProperties(); + } else { + + + properties = data.selections[0].properties; + + elID.innerHTML = properties.id; + + elType.innerHTML = properties.type; + elTypeIcon.innerHTML = ICON_FOR_TYPE[properties.type]; + elTypeIcon.style.display = "inline-block"; + + elLocked.checked = properties.locked; + + if (properties.locked) { + disableProperties(); + elLocked.removeAttribute('disabled'); + } else { + enableProperties(); + } + + elName.value = properties.name; + + elVisible.checked = properties.visible; + + elPositionX.value = properties.position.x.toFixed(4); + elPositionY.value = properties.position.y.toFixed(4); + elPositionZ.value = properties.position.z.toFixed(4); + + elDimensionsX.value = properties.dimensions.x.toFixed(4); + elDimensionsY.value = properties.dimensions.y.toFixed(4); + elDimensionsZ.value = properties.dimensions.z.toFixed(4); + + elParentID.value = properties.parentID; + elParentJointIndex.value = properties.parentJointIndex; + + elRegistrationX.value = properties.registrationPoint.x.toFixed(4); + elRegistrationY.value = properties.registrationPoint.y.toFixed(4); + elRegistrationZ.value = properties.registrationPoint.z.toFixed(4); + + elRotationX.value = properties.rotation.x.toFixed(4); + elRotationY.value = properties.rotation.y.toFixed(4); + elRotationZ.value = properties.rotation.z.toFixed(4); + + elLinearVelocityX.value = properties.velocity.x.toFixed(4); + elLinearVelocityY.value = properties.velocity.y.toFixed(4); + elLinearVelocityZ.value = properties.velocity.z.toFixed(4); + elLinearDamping.value = properties.damping.toFixed(2); + + elAngularVelocityX.value = (properties.angularVelocity.x * RADIANS_TO_DEGREES).toFixed(4); + elAngularVelocityY.value = (properties.angularVelocity.y * RADIANS_TO_DEGREES).toFixed(4); + elAngularVelocityZ.value = (properties.angularVelocity.z * RADIANS_TO_DEGREES).toFixed(4); + elAngularDamping.value = properties.angularDamping.toFixed(4); + + elRestitution.value = properties.restitution.toFixed(4); + elFriction.value = properties.friction.toFixed(4); + + elGravityX.value = properties.gravity.x.toFixed(4); + elGravityY.value = properties.gravity.y.toFixed(4); + elGravityZ.value = properties.gravity.z.toFixed(4); + + elAccelerationX.value = properties.acceleration.x.toFixed(4); + elAccelerationY.value = properties.acceleration.y.toFixed(4); + elAccelerationZ.value = properties.acceleration.z.toFixed(4); + + elDensity.value = properties.density.toFixed(4); + elCollisionless.checked = properties.collisionless; + elDynamic.checked = properties.dynamic; + + elCollideStatic.checked = properties.collidesWith.indexOf("static") > -1; + elCollideKinematic.checked = properties.collidesWith.indexOf("kinematic") > -1; + elCollideDynamic.checked = properties.collidesWith.indexOf("dynamic") > -1; + elCollideMyAvatar.checked = properties.collidesWith.indexOf("myAvatar") > -1; + elCollideOtherAvatar.checked = properties.collidesWith.indexOf("otherAvatar") > -1; + + elGrabbable.checked = properties.dynamic; + elWantsTrigger.checked = false; + elIgnoreIK.checked = false; + var parsedUserData = {} + try { + parsedUserData = JSON.parse(properties.userData); + + if ("grabbableKey" in parsedUserData) { + if ("grabbable" in parsedUserData["grabbableKey"]) { + elGrabbable.checked = parsedUserData["grabbableKey"].grabbable; + } + if ("wantsTrigger" in parsedUserData["grabbableKey"]) { + elWantsTrigger.checked = parsedUserData["grabbableKey"].wantsTrigger; + } + if ("ignoreIK" in parsedUserData["grabbableKey"]) { + elIgnoreIK.checked = parsedUserData["grabbableKey"].ignoreIK; + } + } + } catch(e) {} + + elCollisionSoundURL.value = properties.collisionSoundURL; + elLifetime.value = properties.lifetime; + elScriptURL.value = properties.script; + /* + FIXME: See FIXME for property-script-url. + elScriptTimestamp.value = properties.scriptTimestamp; + */ + elUserData.value = properties.userData; + setTextareaScrolling(elUserData); + + elHyperlinkHref.value = properties.href; + elDescription.value = properties.description; + + for (var i = 0; i < allSections.length; i++) { + for (var j = 0; j < allSections[i].length; j++) { + allSections[i][j].style.display = 'none'; + } + } + + for (var i = 0; i < elHyperlinkSections.length; i++) { + elHyperlinkSections[i].style.display = 'table'; + } + + if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere") { + for (var i = 0; i < elShapeSections.length; i++) { + elShapeSections[i].style.display = 'table'; + } + elShape.value = properties.shape; + setDropdownText(elShape); + + } else { + for (var i = 0; i < elShapeSections.length; i++) { + elShapeSections[i].style.display = 'none'; + } + } + + if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") { + for (var i = 0; i < elColorSections.length; i++) { + elColorSections[i].style.display = 'table'; + } + elColorRed.value = properties.color.red; + elColorGreen.value = properties.color.green; + elColorBlue.value = properties.color.blue; + elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; + } else { + for (var i = 0; i < elColorSections.length; i++) { + elColorSections[i].style.display = 'none'; + } + } + + if (properties.type == "Model") { + for (var i = 0; i < elModelSections.length; i++) { + elModelSections[i].style.display = 'table'; + } + + elModelURL.value = properties.modelURL; + elShapeType.value = properties.shapeType; + setDropdownText(elShapeType); + elCompoundShapeURL.value = properties.compoundShapeURL; + elModelAnimationURL.value = properties.animation.url; + elModelAnimationPlaying.checked = properties.animation.running; + elModelAnimationFPS.value = properties.animation.fps; + elModelAnimationFrame.value = properties.animation.currentFrame; + elModelAnimationFirstFrame.value = properties.animation.firstFrame; + elModelAnimationLastFrame.value = properties.animation.lastFrame; + elModelAnimationLoop.checked = properties.animation.loop; + elModelAnimationHold.checked = properties.animation.hold; + elModelTextures.value = properties.textures; + setTextareaScrolling(elModelTextures); + elModelOriginalTextures.value = properties.originalTextures; + setTextareaScrolling(elModelOriginalTextures); + } else if (properties.type == "Web") { + for (var i = 0; i < elWebSections.length; i++) { + elWebSections[i].style.display = 'table'; + } + for (var i = 0; i < elHyperlinkSections.length; i++) { + elHyperlinkSections[i].style.display = 'none'; + } + + elWebSourceURL.value = properties.sourceUrl; + } else if (properties.type == "Text") { + for (var i = 0; i < elTextSections.length; i++) { + elTextSections[i].style.display = 'table'; + } + + elTextText.value = properties.text; + elTextLineHeight.value = properties.lineHeight.toFixed(4); + elTextFaceCamera = properties.faceCamera; + elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")"; + elTextTextColorRed.value = properties.textColor.red; + elTextTextColorGreen.value = properties.textColor.green; + elTextTextColorBlue.value = properties.textColor.blue; + elTextBackgroundColorRed.value = properties.backgroundColor.red; + elTextBackgroundColorGreen.value = properties.backgroundColor.green; + elTextBackgroundColorBlue.value = properties.backgroundColor.blue; + } else if (properties.type == "Light") { + for (var i = 0; i < elLightSections.length; i++) { + elLightSections[i].style.display = 'table'; + } + + elLightSpotLight.checked = properties.isSpotlight; + + elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; + elLightColorRed.value = properties.color.red; + elLightColorGreen.value = properties.color.green; + elLightColorBlue.value = properties.color.blue; + + elLightIntensity.value = properties.intensity.toFixed(1); + elLightFalloffRadius.value = properties.falloffRadius.toFixed(1); + elLightExponent.value = properties.exponent.toFixed(2); + elLightCutoff.value = properties.cutoff.toFixed(2); + } else if (properties.type == "Zone") { + for (var i = 0; i < elZoneSections.length; i++) { + elZoneSections[i].style.display = 'table'; + } + + elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled; + elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; + elZoneKeyLightColorRed.value = properties.keyLight.color.red; + elZoneKeyLightColorGreen.value = properties.keyLight.color.green; + elZoneKeyLightColorBlue.value = properties.keyLight.color.blue; + elZoneKeyLightIntensity.value = properties.keyLight.intensity.toFixed(2); + elZoneKeyLightAmbientIntensity.value = properties.keyLight.ambientIntensity.toFixed(2); + elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2); + elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); + elZoneKeyLightAmbientURL.value = properties.keyLight.ambientURL; + + + elZoneStageLatitude.value = properties.stage.latitude.toFixed(2); + elZoneStageLongitude.value = properties.stage.longitude.toFixed(2); + elZoneStageAltitude.value = properties.stage.altitude.toFixed(2); + elZoneStageAutomaticHourDay.checked = properties.stage.automaticHourDay; + elZoneStageDay.value = properties.stage.day; + elZoneStageHour.value = properties.stage.hour; + elShapeType.value = properties.shapeType; + elCompoundShapeURL.value = properties.compoundShapeURL; + + elZoneBackgroundMode.value = properties.backgroundMode; + setDropdownText(elZoneBackgroundMode); + + elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")"; + elZoneSkyboxColorRed.value = properties.skybox.color.red; + elZoneSkyboxColorGreen.value = properties.skybox.color.green; + elZoneSkyboxColorBlue.value = properties.skybox.color.blue; + elZoneSkyboxURL.value = properties.skybox.url; + + elZoneFlyingAllowed.checked = properties.flyingAllowed; + elZoneGhostingAllowed.checked = properties.ghostingAllowed; + + showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox'); + } else if (properties.type == "PolyVox") { + for (var i = 0; i < elPolyVoxSections.length; i++) { + elPolyVoxSections[i].style.display = 'table'; + } + + elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); + elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); + elVoxelVolumeSizeZ.value = properties.voxelVolumeSize.z.toFixed(2); + elVoxelSurfaceStyle.value = properties.voxelSurfaceStyle; + setDropdownText(elVoxelSurfaceStyle); + elXTextureURL.value = properties.xTextureURL; + elYTextureURL.value = properties.yTextureURL; + elZTextureURL.value = properties.zTextureURL; + } + + var activeElement = document.activeElement; + + if(typeof activeElement.select!=="undefined"){ + activeElement.select(); + } + } + } + }); + } + + elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked')); + elName.addEventListener('change', createEmitTextPropertyUpdateFunction('name')); + elHyperlinkHref.addEventListener('change', createEmitTextPropertyUpdateFunction('href')); + elDescription.addEventListener('change', createEmitTextPropertyUpdateFunction('description')); + elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible')); + + var positionChangeFunction = createEmitVec3PropertyUpdateFunction( + 'position', elPositionX, elPositionY, elPositionZ); + elPositionX.addEventListener('change', positionChangeFunction); + elPositionY.addEventListener('change', positionChangeFunction); + elPositionZ.addEventListener('change', positionChangeFunction); + + var dimensionsChangeFunction = createEmitVec3PropertyUpdateFunction( + 'dimensions', elDimensionsX, elDimensionsY, elDimensionsZ); + elDimensionsX.addEventListener('change', dimensionsChangeFunction); + elDimensionsY.addEventListener('change', dimensionsChangeFunction); + elDimensionsZ.addEventListener('change', dimensionsChangeFunction); + + elParentID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentID')); + elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex')); + + var registrationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ); + elRegistrationX.addEventListener('change', registrationChangeFunction); + elRegistrationY.addEventListener('change', registrationChangeFunction); + elRegistrationZ.addEventListener('change', registrationChangeFunction); + + var rotationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'rotation', elRotationX, elRotationY, elRotationZ); + elRotationX.addEventListener('change', rotationChangeFunction); + elRotationY.addEventListener('change', rotationChangeFunction); + elRotationZ.addEventListener('change', rotationChangeFunction); + + var velocityChangeFunction = createEmitVec3PropertyUpdateFunction( + 'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ); + elLinearVelocityX.addEventListener('change', velocityChangeFunction); + elLinearVelocityY.addEventListener('change', velocityChangeFunction); + elLinearVelocityZ.addEventListener('change', velocityChangeFunction); + elLinearDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('damping')); + + var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( + 'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ, DEGREES_TO_RADIANS); + elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction); + elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction); + elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction); + elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping')); + + elRestitution.addEventListener('change', createEmitNumberPropertyUpdateFunction('restitution')); + elFriction.addEventListener('change', createEmitNumberPropertyUpdateFunction('friction')); + + var gravityChangeFunction = createEmitVec3PropertyUpdateFunction( + 'gravity', elGravityX, elGravityY, elGravityZ); + elGravityX.addEventListener('change', gravityChangeFunction); + elGravityY.addEventListener('change', gravityChangeFunction); + elGravityZ.addEventListener('change', gravityChangeFunction); + + var accelerationChangeFunction = createEmitVec3PropertyUpdateFunction( + 'acceleration', elAccelerationX, elAccelerationY, elAccelerationZ); + elAccelerationX.addEventListener('change', accelerationChangeFunction); + elAccelerationY.addEventListener('change', accelerationChangeFunction); + elAccelerationZ.addEventListener('change', accelerationChangeFunction); + + elDensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('density')); + elCollisionless.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionless')); + elDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('dynamic')); + + elCollideDynamic.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideDynamic, 'dynamic'); + }); + + elCollideKinematic.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideKinematic, 'kinematic'); + }); + + elCollideStatic.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideStatic, 'static'); + }); + elCollideMyAvatar.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideMyAvatar, 'myAvatar'); + }); + elCollideOtherAvatar.addEventListener('change', function() { + updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideOtherAvatar, 'otherAvatar'); + }); + + elGrabbable.addEventListener('change', function() { + userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); + }); + elWantsTrigger.addEventListener('change', function() { + userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); + }); + elIgnoreIK.addEventListener('change', function() { + userDataChanger("grabbableKey", "ignoreIK", elIgnoreIK, elUserData, false); + }); + + elCollisionSoundURL.addEventListener('change', createEmitTextPropertyUpdateFunction('collisionSoundURL')); + + elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); + elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); + /* + FIXME: See FIXME for property-script-url. + elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp')); + */ + elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); + + var colorChangeFunction = createEmitColorPropertyUpdateFunction( + 'color', elColorRed, elColorGreen, elColorBlue); + elColorRed.addEventListener('change', colorChangeFunction); + elColorGreen.addEventListener('change', colorChangeFunction); + elColorBlue.addEventListener('change', colorChangeFunction); + colorPickers.push($('#property-color').colpick({ + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function (colpick) { + $('#property-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); + } + })); + + elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight')); + + var lightColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'color', elLightColorRed, elLightColorGreen, elLightColorBlue); + elLightColorRed.addEventListener('change', lightColorChangeFunction); + elLightColorGreen.addEventListener('change', lightColorChangeFunction); + elLightColorBlue.addEventListener('change', lightColorChangeFunction); + colorPickers.push($('#property-light-color').colpick({ + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function (colpick) { + $('#property-light-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-light-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); + } + })); + + elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity', 1)); + elLightFalloffRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('falloffRadius', 1)); + elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent', 2)); + elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff', 2)); + + elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); + + elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); + + elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL')); + elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType')); + elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL')); + + elModelAnimationURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('animation', 'url')); + elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation','running')); + elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation','fps')); + elModelAnimationFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'currentFrame')); + elModelAnimationFirstFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'firstFrame')); + elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame')); + elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop')); + elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold')); + + elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); + + elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); + elTextFaceCamera.addEventListener('change', createEmitCheckedPropertyUpdateFunction('faceCamera')); + elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); + var textTextColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'textColor', elTextTextColorRed, elTextTextColorGreen, elTextTextColorBlue); + elTextTextColorRed.addEventListener('change', textTextColorChangeFunction); + elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction); + elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction); + colorPickers.push($('#property-text-text-color').colpick({ + colorScheme:'dark', + layout:'hex', + color: '000000', + onShow: function (colpick) { + $('#property-text-text-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-text-text-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + $(el).attr('active', 'false'); + emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); + } + })); + + var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue); + elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction); + elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); + elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); + colorPickers.push($('#property-text-background-color').colpick({ + colorScheme:'dark', + layout:'hex', + color:'000000', + onShow: function (colpick) { + $('#property-text-background-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-text-background-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); + } + })); + + elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled')); + colorPickers.push($('#property-zone-key-light-color').colpick({ + colorScheme:'dark', + layout:'hex', + color:'000000', + onShow: function (colpick) { + $('#property-zone-key-light-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-zone-key-light-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); + } + })); + var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight','color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); + elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightColorGreen.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction); + elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity')); + elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity')); + elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL')); + var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY); + elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction); + elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); + + elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude')); + elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude')); + elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude')); + elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','automaticHourDay')); + elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day')); + elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour')); + + + elZoneBackgroundMode.addEventListener('change', createEmitTextPropertyUpdateFunction('backgroundMode')); + var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox','color', + elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue); + elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction); + elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction); + elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction); + colorPickers.push($('#property-zone-skybox-color').colpick({ + colorScheme:'dark', + layout:'hex', + color:'000000', + onShow: function (colpick) { + $('#property-zone-skybox-color').attr('active', 'true'); + }, + onHide: function (colpick) { + $('#property-zone-skybox-color').attr('active', 'false'); + }, + onSubmit: function (hsb, hex, rgb, el) { + $(el).css('background-color', '#'+hex); + $(el).colpickHide(); + emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); + } + })); + + elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url')); + + elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed')); + elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed')); + + var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction( + 'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ); + elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction); + elVoxelVolumeSizeY.addEventListener('change', voxelVolumeSizeChangeFunction); + elVoxelVolumeSizeZ.addEventListener('change', voxelVolumeSizeChangeFunction); + elVoxelSurfaceStyle.addEventListener('change', createEmitTextPropertyUpdateFunction('voxelSurfaceStyle')); + elXTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('xTextureURL')); + elYTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('yTextureURL')); + elZTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('zTextureURL')); + + elMoveSelectionToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveSelectionToGrid", + })); + }); + elMoveAllToGrid.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "moveAllToGrid", + })); + }); + elResetToNaturalDimensions.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "resetToNaturalDimensions", + })); + }); + elRescaleDimensionsButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "rescaleDimensions", + percentage: parseInt(elRescaleDimensionsPct.value), + })); + }); + /* + FIXME: See FIXME for property-script-url. + elReloadScriptButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "reloadScript" + })); + }); + */ + elPreviewCameraButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "previewCamera" + })); + }); + + window.onblur = function() { + // Fake a change event + var ev = document.createEvent("HTMLEvents"); + ev.initEvent("change", true, true); + document.activeElement.dispatchEvent(ev); + } + + // For input and textarea elements, select all of the text on focus + // WebKit-based browsers, such as is used with QWebView, have a quirk + // where the mouseup event comes after the focus event, causing the + // text to be deselected immediately after selecting all of the text. + // To make this work we block the first mouseup event after the elements + // received focus. If we block all mouseup events the user will not + // be able to click within the selected text. + // We also check to see if the value has changed to make sure we aren't + // blocking a mouse-up event when clicking on an input spinner. + var els = document.querySelectorAll("input, textarea"); + for (var i = 0; i < els.length; i++) { + var clicked = false; + var originalText; + els[i].onfocus = function(e) { + originalText = this.value; + this.select(); + clicked = false; + }; + els[i].onmouseup = function(e) { + if (!clicked && originalText == this.value) { + e.preventDefault(); + } + clicked = true; + }; + } + }); + + // Collapsible sections + var elCollapsible = document.getElementsByClassName("section-header"); + + var toggleCollapsedEvent = function (event) { + var element = event.target; + if (element.nodeName !== "DIV") { + element = element.parentNode; + } + var isCollapsed = element.getAttribute("collapsed") !== "true"; + element.setAttribute("collapsed", isCollapsed ? "true" : "false"); + element.getElementsByTagName("span")[0].textContent = isCollapsed ? "L" : "M"; + }; + + for (var i = 0, length = elCollapsible.length; i < length; i++) { + var element = elCollapsible[i]; + element.addEventListener("click", toggleCollapsedEvent, true); + }; + + + // Textarea scrollbars + var elTextareas = document.getElementsByTagName("TEXTAREA"); + + var textareaOnChangeEvent = function (event) { + setTextareaScrolling(event.target); + } + + for (var i = 0, length = elTextareas.length; i < length; i++) { + var element = elTextareas[i]; + setTextareaScrolling(element); + element.addEventListener("input", textareaOnChangeEvent, false); + element.addEventListener("change", textareaOnChangeEvent, false); + /* FIXME: Detect and update textarea scrolling attribute on resize. Unfortunately textarea doesn't have a resize + event; mouseup is a partial stand-in but doesn't handle resizing if mouse moves outside textarea rectangle. */ + element.addEventListener("mouseup", textareaOnChangeEvent, false); + }; + + // Dropdowns + // For each dropdown the following replacement is created in place of the oriringal dropdown... + // Structure created: + //
    + //
    display textcarat
    + //
    + //
      + //
    • 0) { + var el = elDropdowns[0]; + el.parentNode.removeChild(el); + elDropdowns = document.getElementsByTagName("select"); + } + + 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); +} + diff --git a/scripts/system/html/eventBridgeLoader.js b/scripts/system/html/js/eventBridgeLoader.js similarity index 100% rename from scripts/system/html/eventBridgeLoader.js rename to scripts/system/html/js/eventBridgeLoader.js diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/html/js/gridControls.js new file mode 100644 index 0000000000..cc268bcbff --- /dev/null +++ b/scripts/system/html/js/gridControls.js @@ -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); +} + diff --git a/scripts/system/html/jquery-2.1.4.min.js b/scripts/system/html/js/jquery-2.1.4.min.js similarity index 100% rename from scripts/system/html/jquery-2.1.4.min.js rename to scripts/system/html/js/jquery-2.1.4.min.js diff --git a/scripts/system/html/list.min.js b/scripts/system/html/js/list.min.js similarity index 100% rename from scripts/system/html/list.min.js rename to scripts/system/html/js/list.min.js diff --git a/scripts/system/html/spinButtons.js b/scripts/system/html/js/spinButtons.js similarity index 100% rename from scripts/system/html/spinButtons.js rename to scripts/system/html/js/spinButtons.js From d5b822ddbe50fad78a2d17f086f75291e086e8a9 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 9 Aug 2016 15:20:56 -0700 Subject: [PATCH 69/78] remove missing camera selectors --- scripts/system/html/entityProperties.js | 1317 -------------------- scripts/system/html/js/entityProperties.js | 8 - 2 files changed, 1325 deletions(-) delete mode 100644 scripts/system/html/entityProperties.js diff --git a/scripts/system/html/entityProperties.js b/scripts/system/html/entityProperties.js deleted file mode 100644 index 490579e909..0000000000 --- a/scripts/system/html/entityProperties.js +++ /dev/null @@ -1,1317 +0,0 @@ -// entityProperties.js -// -// Created by Ryan Huffman on 13 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 PI = 3.14159265358979; -var DEGREES_TO_RADIANS = PI / 180.0; -var RADIANS_TO_DEGREES = 180.0 / PI; -var ICON_FOR_TYPE = { - Box: "V", - Sphere: "n", - Shape: "n", - ParticleEffect: "", - Model: "", - Web: "q", - Text: "l", - Light: "p", - Zone: "o", - PolyVox: "", - Multiple: "" -} - -var colorPickers = []; - -debugPrint = function(message) { - EventBridge.emitWebEvent( - JSON.stringify({ - type:"print", - message: message - }) - ); -}; - -function enableChildren(el, selector) { - els = el.querySelectorAll(selector); - for (var i = 0; i < els.length; i++) { - els[i].removeAttribute('disabled'); - } -} -function disableChildren(el, selector) { - els = el.querySelectorAll(selector); - for (var i = 0; i < els.length; i++) { - els[i].setAttribute('disabled', 'disabled'); - } -} - -function enableProperties() { - enableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); - enableChildren(document, ".colpick"); -} - -function disableProperties() { - disableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); - disableChildren(document, ".colpick"); - for (var i = 0; i < colorPickers.length; i++) { - colorPickers[i].colpickHide(); - } -} - -function showElements(els, show) { - for (var i = 0; i < els.length; i++) { - els[i].style.display = (show) ? 'table' : 'none'; - } -} - -function createEmitCheckedPropertyUpdateFunction(propertyName) { - return function() { - EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}' - ); - }; -} - -function createEmitCheckedToStringPropertyUpdateFunction(checkboxElement, name, propertyName) { - var newString = ""; - if (checkboxElement.checked) { - newString += name + ""; - } else { - - } - -} - -function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) { - return function () { - var properties = {}; - properties[group] = {}; - properties[group][propertyName] = this.checked; - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: properties - }) - ); - }; -} - -function createEmitNumberPropertyUpdateFunction(propertyName, decimals) { - decimals = decimals == undefined ? 4 : decimals; - return function() { - var value = parseFloat(this.value).toFixed(decimals); - - EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":' + value + '}}' - ); - }; -} -function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { - return function() { - var properties = {}; - properties[group] = {}; - properties[group][propertyName] = this.value; - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: properties, - }) - ); - }; -} - - -function createEmitTextPropertyUpdateFunction(propertyName) { - return function() { - var properties = {}; - properties[propertyName] = this.value; - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: properties, - }) - ); - }; -} - -function createEmitGroupTextPropertyUpdateFunction(group,propertyName) { - return function() { - var properties = {}; - properties[group] = {}; - properties[group][propertyName] = this.value; - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: properties, - }) - ); - }; -} - -function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { - return function() { - var data = { - type: "update", - properties: { - } - }; - data.properties[property] = { - x: elX.value, - y: elY.value, - z: elZ.value, - }; - EventBridge.emitWebEvent(JSON.stringify(data)); - } -}; - -function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, elZ) { - return function() { - var data = { - type: "update", - properties: { - } - }; - data.properties[group] = { }; - data.properties[group][property] = { - x: elX.value, - y: elY.value, - z: elZ ? elZ.value : 0, - }; - EventBridge.emitWebEvent(JSON.stringify(data)); - } -}; - -function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { - return function() { - var data = { - type: "update", - properties: { - } - }; - data.properties[property] = { - x: elX.value * multiplier, - y: elY.value * multiplier, - z: elZ.value * multiplier, - }; - EventBridge.emitWebEvent(JSON.stringify(data)); - } -}; - -function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) { - return function() { - emitColorPropertyUpdate(property, elRed.value, elGreen.value, elBlue.value); - } -}; - -function emitColorPropertyUpdate(property, red, green, blue, group) { - var data = { - type: "update", - properties: { - } - }; - if (group) { - data.properties[group] = { }; - data.properties[group][property] = { - red: red, - green: green, - blue: blue, - }; - } else { - data.properties[property] = { - red: red, - green: green, - blue: blue, - }; - } - EventBridge.emitWebEvent(JSON.stringify(data)); -}; - - -function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) { - return function() { - var data = { - type: "update", - properties: { - } - }; - data.properties[group] = { }; - - data.properties[group][property] = { - red: elRed.value, - green: elGreen.value, - blue: elBlue.value, - }; - EventBridge.emitWebEvent(JSON.stringify(data)); - } -}; - -function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElement, subPropertyString) { - if (subPropertyElement.checked) { - if (propertyValue.indexOf(subPropertyString)) { - propertyValue += subPropertyString + ','; - } - } else { - // We've unchecked, so remove - propertyValue = propertyValue.replace(subPropertyString + ",", ""); - } - - var _properties ={} - _properties[propertyName] = propertyValue; - - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: _properties - }) - ); - -} - -function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) { - var properties = {}; - var parsedData = {}; - try { - parsedData = JSON.parse(userDataElement.value); - } catch(e) {} - - if (!(groupName in parsedData)) { - parsedData[groupName] = {} - } - delete parsedData[groupName][keyName]; - if (checkBoxElement.checked !== defaultValue) { - parsedData[groupName][keyName] = checkBoxElement.checked; - } - - if (Object.keys(parsedData[groupName]).length == 0) { - delete parsedData[groupName]; - } - if (Object.keys(parsedData).length > 0) { - properties['userData'] = JSON.stringify(parsedData); - } else { - properties['userData'] = ''; - } - - userDataElement.value = properties['userData']; - - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: properties, - }) - ); -}; - -function setTextareaScrolling(element) { - var isScrolling = element.scrollHeight > element.offsetHeight; - element.setAttribute("scrolling", isScrolling ? "true" : "false"); -} - -function loaded() { - openEventBridge(function() { - var allSections = []; - var elID = document.getElementById("property-id"); - var elType = document.getElementById("property-type"); - var elTypeIcon = document.getElementById("type-icon"); - var elName = document.getElementById("property-name"); - var elLocked = document.getElementById("property-locked"); - var elVisible = document.getElementById("property-visible"); - var elPositionX = document.getElementById("property-pos-x"); - var elPositionY = document.getElementById("property-pos-y"); - var elPositionZ = document.getElementById("property-pos-z"); - var elMoveSelectionToGrid = document.getElementById("move-selection-to-grid"); - var elMoveAllToGrid = document.getElementById("move-all-to-grid"); - - var elDimensionsX = document.getElementById("property-dim-x"); - var elDimensionsY = document.getElementById("property-dim-y"); - var elDimensionsZ = document.getElementById("property-dim-z"); - var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); - var elRescaleDimensionsPct = document.getElementById("dimension-rescale-pct"); - var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button"); - - var elParentID = document.getElementById("property-parent-id"); - var elParentJointIndex = document.getElementById("property-parent-joint-index"); - - var elRegistrationX = document.getElementById("property-reg-x"); - var elRegistrationY = document.getElementById("property-reg-y"); - var elRegistrationZ = document.getElementById("property-reg-z"); - - var elRotationX = document.getElementById("property-rot-x"); - var elRotationY = document.getElementById("property-rot-y"); - var elRotationZ = document.getElementById("property-rot-z"); - - var elLinearVelocityX = document.getElementById("property-lvel-x"); - var elLinearVelocityY = document.getElementById("property-lvel-y"); - var elLinearVelocityZ = document.getElementById("property-lvel-z"); - var elLinearDamping = document.getElementById("property-ldamping"); - - var elAngularVelocityX = document.getElementById("property-avel-x"); - var elAngularVelocityY = document.getElementById("property-avel-y"); - var elAngularVelocityZ = document.getElementById("property-avel-z"); - var elAngularDamping = document.getElementById("property-adamping"); - - var elRestitution = document.getElementById("property-restitution"); - var elFriction = document.getElementById("property-friction"); - - var elGravityX = document.getElementById("property-grav-x"); - var elGravityY = document.getElementById("property-grav-y"); - var elGravityZ = document.getElementById("property-grav-z"); - - var elAccelerationX = document.getElementById("property-lacc-x"); - var elAccelerationY = document.getElementById("property-lacc-y"); - var elAccelerationZ = document.getElementById("property-lacc-z"); - - var elDensity = document.getElementById("property-density"); - var elCollisionless = document.getElementById("property-collisionless"); - var elDynamic = document.getElementById("property-dynamic" ); - var elCollideStatic = document.getElementById("property-collide-static"); - var elCollideDynamic = document.getElementById("property-collide-dynamic"); - var elCollideKinematic = document.getElementById("property-collide-kinematic"); - var elCollideMyAvatar = document.getElementById("property-collide-myAvatar"); - var elCollideOtherAvatar = document.getElementById("property-collide-otherAvatar"); - var elCollisionSoundURL = document.getElementById("property-collision-sound-url"); - - var elGrabbable = document.getElementById("property-grabbable"); - var elWantsTrigger = document.getElementById("property-wants-trigger"); - var elIgnoreIK = document.getElementById("property-ignore-ik"); - - var elLifetime = document.getElementById("property-lifetime"); - var elScriptURL = document.getElementById("property-script-url"); - /* - FIXME: See FIXME for property-script-url. - var elScriptTimestamp = document.getElementById("property-script-timestamp"); - */ - var elReloadScriptButton = document.getElementById("reload-script-button"); - var elUserData = document.getElementById("property-user-data"); - - var elColorSections = document.querySelectorAll(".color-section"); - var elColor = document.getElementById("property-color"); - var elColorRed = document.getElementById("property-color-red"); - var elColorGreen = document.getElementById("property-color-green"); - var elColorBlue = document.getElementById("property-color-blue"); - - var elShapeSections = document.querySelectorAll(".shape-section"); - allSections.push(elShapeSections); - var elShape = document.getElementById("property-shape"); - - var elLightSections = document.querySelectorAll(".light-section"); - allSections.push(elLightSections); - var elLightSpotLight = document.getElementById("property-light-spot-light"); - var elLightColor = document.getElementById("property-light-color"); - var elLightColorRed = document.getElementById("property-light-color-red"); - var elLightColorGreen = document.getElementById("property-light-color-green"); - var elLightColorBlue = document.getElementById("property-light-color-blue"); - - var elLightIntensity = document.getElementById("property-light-intensity"); - var elLightFalloffRadius = document.getElementById("property-light-falloff-radius"); - var elLightExponent = document.getElementById("property-light-exponent"); - var elLightCutoff = document.getElementById("property-light-cutoff"); - - var elModelSections = document.querySelectorAll(".model-section"); - allSections.push(elModelSections); - var elModelURL = document.getElementById("property-model-url"); - var elShapeType = document.getElementById("property-shape-type"); - var elCompoundShapeURL = document.getElementById("property-compound-shape-url"); - var elModelAnimationURL = document.getElementById("property-model-animation-url"); - var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); - var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); - var elModelAnimationFrame = document.getElementById("property-model-animation-frame"); - var elModelAnimationFirstFrame = document.getElementById("property-model-animation-first-frame"); - var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame"); - var elModelAnimationLoop = document.getElementById("property-model-animation-loop"); - var elModelAnimationHold = document.getElementById("property-model-animation-hold"); - var elModelTextures = document.getElementById("property-model-textures"); - var elModelOriginalTextures = document.getElementById("property-model-original-textures"); - - var elWebSections = document.querySelectorAll(".web-section"); - allSections.push(elWebSections); - var elWebSourceURL = document.getElementById("property-web-source-url"); - - var elDescription = document.getElementById("property-description"); - - var elHyperlinkHref = document.getElementById("property-hyperlink-href"); - - var elHyperlinkSections = document.querySelectorAll(".hyperlink-section"); - - - var elTextSections = document.querySelectorAll(".text-section"); - allSections.push(elTextSections); - var elTextText = document.getElementById("property-text-text"); - var elTextLineHeight = document.getElementById("property-text-line-height"); - var elTextTextColor = document.getElementById("property-text-text-color"); - var elTextFaceCamera = document.getElementById("property-text-face-camera"); - var elTextTextColorRed = document.getElementById("property-text-text-color-red"); - var elTextTextColorGreen = document.getElementById("property-text-text-color-green"); - var elTextTextColorBlue = document.getElementById("property-text-text-color-blue"); - var elTextBackgroundColor = document.getElementById("property-text-background-color"); - var elTextBackgroundColorRed = document.getElementById("property-text-background-color-red"); - var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green"); - var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue"); - - var elZoneSections = document.querySelectorAll(".zone-section"); - allSections.push(elZoneSections); - var elZoneStageSunModelEnabled = document.getElementById("property-zone-stage-sun-model-enabled"); - - var elZoneKeyLightColor = document.getElementById("property-zone-key-light-color"); - var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red"); - var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green"); - var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue"); - var elZoneKeyLightIntensity = document.getElementById("property-zone-key-intensity"); - var elZoneKeyLightAmbientIntensity = document.getElementById("property-zone-key-ambient-intensity"); - var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x"); - var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); - var elZoneKeyLightDirectionZ = document.getElementById("property-zone-key-light-direction-z"); - var elZoneKeyLightAmbientURL = document.getElementById("property-zone-key-ambient-url"); - - var elZoneStageLatitude = document.getElementById("property-zone-stage-latitude"); - var elZoneStageLongitude = document.getElementById("property-zone-stage-longitude"); - var elZoneStageAltitude = document.getElementById("property-zone-stage-altitude"); - var elZoneStageAutomaticHourDay = document.getElementById("property-zone-stage-automatic-hour-day"); - var elZoneStageDay = document.getElementById("property-zone-stage-day"); - var elZoneStageHour = document.getElementById("property-zone-stage-hour"); - - var elZoneBackgroundMode = document.getElementById("property-zone-background-mode"); - - var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color"); - var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red"); - var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green"); - var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue"); - var elZoneSkyboxURL = document.getElementById("property-zone-skybox-url"); - - var elZoneFlyingAllowed = document.getElementById("property-zone-flying-allowed"); - var elZoneGhostingAllowed = document.getElementById("property-zone-ghosting-allowed"); - - var elPolyVoxSections = document.querySelectorAll(".poly-vox-section"); - allSections.push(elPolyVoxSections); - var elVoxelVolumeSizeX = document.getElementById("property-voxel-volume-size-x"); - var elVoxelVolumeSizeY = document.getElementById("property-voxel-volume-size-y"); - var elVoxelVolumeSizeZ = document.getElementById("property-voxel-volume-size-z"); - var elVoxelSurfaceStyle = document.getElementById("property-voxel-surface-style"); - var elXTextureURL = document.getElementById("property-x-texture-url"); - var elYTextureURL = document.getElementById("property-y-texture-url"); - var elZTextureURL = document.getElementById("property-z-texture-url"); - - var elPreviewCameraButton = document.getElementById("preview-camera-button"); - - if (window.EventBridge !== undefined) { - var properties; - EventBridge.scriptEventReceived.connect(function(data) { - data = JSON.parse(data); - if (data.type == "update") { - if (data.selections.length == 0) { - elTypeIcon.style.display = "none"; - elType.innerHTML = "No selection"; - elID.innerHTML = ""; - disableProperties(); - } else if (data.selections.length > 1) { - var selections = data.selections; - - var ids = []; - var types = {}; - var numTypes = 0; - - for (var i = 0; i < selections.length; i++) { - ids.push(selections[i].id); - var type = selections[i].properties.type; - if (types[type] === undefined) { - types[type] = 0; - numTypes += 1; - } - types[type]++; - } - - var type; - if (numTypes === 1) { - type = selections[0].properties.type; - } else { - type = "Multiple"; - } - elType.innerHTML = type + " (" + data.selections.length + ")"; - elTypeIcon.innerHTML = ICON_FOR_TYPE[type]; - elTypeIcon.style.display = "inline-block"; - - elID.innerHTML = ids.join("
      "); - - disableProperties(); - } else { - - - properties = data.selections[0].properties; - - elID.innerHTML = properties.id; - - elType.innerHTML = properties.type; - elTypeIcon.innerHTML = ICON_FOR_TYPE[properties.type]; - elTypeIcon.style.display = "inline-block"; - - elLocked.checked = properties.locked; - - if (properties.locked) { - disableProperties(); - elLocked.removeAttribute('disabled'); - } else { - enableProperties(); - } - - elName.value = properties.name; - - elVisible.checked = properties.visible; - - elPositionX.value = properties.position.x.toFixed(4); - elPositionY.value = properties.position.y.toFixed(4); - elPositionZ.value = properties.position.z.toFixed(4); - - elDimensionsX.value = properties.dimensions.x.toFixed(4); - elDimensionsY.value = properties.dimensions.y.toFixed(4); - elDimensionsZ.value = properties.dimensions.z.toFixed(4); - - elParentID.value = properties.parentID; - elParentJointIndex.value = properties.parentJointIndex; - - elRegistrationX.value = properties.registrationPoint.x.toFixed(4); - elRegistrationY.value = properties.registrationPoint.y.toFixed(4); - elRegistrationZ.value = properties.registrationPoint.z.toFixed(4); - - elRotationX.value = properties.rotation.x.toFixed(4); - elRotationY.value = properties.rotation.y.toFixed(4); - elRotationZ.value = properties.rotation.z.toFixed(4); - - elLinearVelocityX.value = properties.velocity.x.toFixed(4); - elLinearVelocityY.value = properties.velocity.y.toFixed(4); - elLinearVelocityZ.value = properties.velocity.z.toFixed(4); - elLinearDamping.value = properties.damping.toFixed(2); - - elAngularVelocityX.value = (properties.angularVelocity.x * RADIANS_TO_DEGREES).toFixed(4); - elAngularVelocityY.value = (properties.angularVelocity.y * RADIANS_TO_DEGREES).toFixed(4); - elAngularVelocityZ.value = (properties.angularVelocity.z * RADIANS_TO_DEGREES).toFixed(4); - elAngularDamping.value = properties.angularDamping.toFixed(4); - - elRestitution.value = properties.restitution.toFixed(4); - elFriction.value = properties.friction.toFixed(4); - - elGravityX.value = properties.gravity.x.toFixed(4); - elGravityY.value = properties.gravity.y.toFixed(4); - elGravityZ.value = properties.gravity.z.toFixed(4); - - elAccelerationX.value = properties.acceleration.x.toFixed(4); - elAccelerationY.value = properties.acceleration.y.toFixed(4); - elAccelerationZ.value = properties.acceleration.z.toFixed(4); - - elDensity.value = properties.density.toFixed(4); - elCollisionless.checked = properties.collisionless; - elDynamic.checked = properties.dynamic; - - elCollideStatic.checked = properties.collidesWith.indexOf("static") > -1; - elCollideKinematic.checked = properties.collidesWith.indexOf("kinematic") > -1; - elCollideDynamic.checked = properties.collidesWith.indexOf("dynamic") > -1; - elCollideMyAvatar.checked = properties.collidesWith.indexOf("myAvatar") > -1; - elCollideOtherAvatar.checked = properties.collidesWith.indexOf("otherAvatar") > -1; - - elGrabbable.checked = properties.dynamic; - elWantsTrigger.checked = false; - elIgnoreIK.checked = false; - var parsedUserData = {} - try { - parsedUserData = JSON.parse(properties.userData); - - if ("grabbableKey" in parsedUserData) { - if ("grabbable" in parsedUserData["grabbableKey"]) { - elGrabbable.checked = parsedUserData["grabbableKey"].grabbable; - } - if ("wantsTrigger" in parsedUserData["grabbableKey"]) { - elWantsTrigger.checked = parsedUserData["grabbableKey"].wantsTrigger; - } - if ("ignoreIK" in parsedUserData["grabbableKey"]) { - elIgnoreIK.checked = parsedUserData["grabbableKey"].ignoreIK; - } - } - } catch(e) {} - - elCollisionSoundURL.value = properties.collisionSoundURL; - elLifetime.value = properties.lifetime; - elScriptURL.value = properties.script; - /* - FIXME: See FIXME for property-script-url. - elScriptTimestamp.value = properties.scriptTimestamp; - */ - elUserData.value = properties.userData; - setTextareaScrolling(elUserData); - - elHyperlinkHref.value = properties.href; - elDescription.value = properties.description; - - for (var i = 0; i < allSections.length; i++) { - for (var j = 0; j < allSections[i].length; j++) { - allSections[i][j].style.display = 'none'; - } - } - - for (var i = 0; i < elHyperlinkSections.length; i++) { - elHyperlinkSections[i].style.display = 'table'; - } - - if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere") { - for (var i = 0; i < elShapeSections.length; i++) { - elShapeSections[i].style.display = 'table'; - } - elShape.value = properties.shape; - setDropdownText(elShape); - - } else { - for (var i = 0; i < elShapeSections.length; i++) { - elShapeSections[i].style.display = 'none'; - } - } - - if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") { - for (var i = 0; i < elColorSections.length; i++) { - elColorSections[i].style.display = 'table'; - } - elColorRed.value = properties.color.red; - elColorGreen.value = properties.color.green; - elColorBlue.value = properties.color.blue; - elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; - } else { - for (var i = 0; i < elColorSections.length; i++) { - elColorSections[i].style.display = 'none'; - } - } - - if (properties.type == "Model") { - for (var i = 0; i < elModelSections.length; i++) { - elModelSections[i].style.display = 'table'; - } - - elModelURL.value = properties.modelURL; - elShapeType.value = properties.shapeType; - setDropdownText(elShapeType); - elCompoundShapeURL.value = properties.compoundShapeURL; - elModelAnimationURL.value = properties.animation.url; - elModelAnimationPlaying.checked = properties.animation.running; - elModelAnimationFPS.value = properties.animation.fps; - elModelAnimationFrame.value = properties.animation.currentFrame; - elModelAnimationFirstFrame.value = properties.animation.firstFrame; - elModelAnimationLastFrame.value = properties.animation.lastFrame; - elModelAnimationLoop.checked = properties.animation.loop; - elModelAnimationHold.checked = properties.animation.hold; - elModelTextures.value = properties.textures; - setTextareaScrolling(elModelTextures); - elModelOriginalTextures.value = properties.originalTextures; - setTextareaScrolling(elModelOriginalTextures); - } else if (properties.type == "Web") { - for (var i = 0; i < elWebSections.length; i++) { - elWebSections[i].style.display = 'table'; - } - for (var i = 0; i < elHyperlinkSections.length; i++) { - elHyperlinkSections[i].style.display = 'none'; - } - - elWebSourceURL.value = properties.sourceUrl; - } else if (properties.type == "Text") { - for (var i = 0; i < elTextSections.length; i++) { - elTextSections[i].style.display = 'table'; - } - - elTextText.value = properties.text; - elTextLineHeight.value = properties.lineHeight.toFixed(4); - elTextFaceCamera = properties.faceCamera; - elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")"; - elTextTextColorRed.value = properties.textColor.red; - elTextTextColorGreen.value = properties.textColor.green; - elTextTextColorBlue.value = properties.textColor.blue; - elTextBackgroundColorRed.value = properties.backgroundColor.red; - elTextBackgroundColorGreen.value = properties.backgroundColor.green; - elTextBackgroundColorBlue.value = properties.backgroundColor.blue; - } else if (properties.type == "Light") { - for (var i = 0; i < elLightSections.length; i++) { - elLightSections[i].style.display = 'table'; - } - - elLightSpotLight.checked = properties.isSpotlight; - - elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; - elLightColorRed.value = properties.color.red; - elLightColorGreen.value = properties.color.green; - elLightColorBlue.value = properties.color.blue; - - elLightIntensity.value = properties.intensity.toFixed(1); - elLightFalloffRadius.value = properties.falloffRadius.toFixed(1); - elLightExponent.value = properties.exponent.toFixed(2); - elLightCutoff.value = properties.cutoff.toFixed(2); - } else if (properties.type == "Zone") { - for (var i = 0; i < elZoneSections.length; i++) { - elZoneSections[i].style.display = 'table'; - } - - elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled; - elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; - elZoneKeyLightColorRed.value = properties.keyLight.color.red; - elZoneKeyLightColorGreen.value = properties.keyLight.color.green; - elZoneKeyLightColorBlue.value = properties.keyLight.color.blue; - elZoneKeyLightIntensity.value = properties.keyLight.intensity.toFixed(2); - elZoneKeyLightAmbientIntensity.value = properties.keyLight.ambientIntensity.toFixed(2); - elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2); - elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); - elZoneKeyLightAmbientURL.value = properties.keyLight.ambientURL; - - - elZoneStageLatitude.value = properties.stage.latitude.toFixed(2); - elZoneStageLongitude.value = properties.stage.longitude.toFixed(2); - elZoneStageAltitude.value = properties.stage.altitude.toFixed(2); - elZoneStageAutomaticHourDay.checked = properties.stage.automaticHourDay; - elZoneStageDay.value = properties.stage.day; - elZoneStageHour.value = properties.stage.hour; - elShapeType.value = properties.shapeType; - elCompoundShapeURL.value = properties.compoundShapeURL; - - elZoneBackgroundMode.value = properties.backgroundMode; - setDropdownText(elZoneBackgroundMode); - - elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")"; - elZoneSkyboxColorRed.value = properties.skybox.color.red; - elZoneSkyboxColorGreen.value = properties.skybox.color.green; - elZoneSkyboxColorBlue.value = properties.skybox.color.blue; - elZoneSkyboxURL.value = properties.skybox.url; - - elZoneFlyingAllowed.checked = properties.flyingAllowed; - elZoneGhostingAllowed.checked = properties.ghostingAllowed; - - showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox'); - } else if (properties.type == "PolyVox") { - for (var i = 0; i < elPolyVoxSections.length; i++) { - elPolyVoxSections[i].style.display = 'table'; - } - - elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); - elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); - elVoxelVolumeSizeZ.value = properties.voxelVolumeSize.z.toFixed(2); - elVoxelSurfaceStyle.value = properties.voxelSurfaceStyle; - setDropdownText(elVoxelSurfaceStyle); - elXTextureURL.value = properties.xTextureURL; - elYTextureURL.value = properties.yTextureURL; - elZTextureURL.value = properties.zTextureURL; - } - - var activeElement = document.activeElement; - - if(typeof activeElement.select!=="undefined"){ - activeElement.select(); - } - } - } - }); - } - - elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked')); - elName.addEventListener('change', createEmitTextPropertyUpdateFunction('name')); - elHyperlinkHref.addEventListener('change', createEmitTextPropertyUpdateFunction('href')); - elDescription.addEventListener('change', createEmitTextPropertyUpdateFunction('description')); - elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible')); - - var positionChangeFunction = createEmitVec3PropertyUpdateFunction( - 'position', elPositionX, elPositionY, elPositionZ); - elPositionX.addEventListener('change', positionChangeFunction); - elPositionY.addEventListener('change', positionChangeFunction); - elPositionZ.addEventListener('change', positionChangeFunction); - - var dimensionsChangeFunction = createEmitVec3PropertyUpdateFunction( - 'dimensions', elDimensionsX, elDimensionsY, elDimensionsZ); - elDimensionsX.addEventListener('change', dimensionsChangeFunction); - elDimensionsY.addEventListener('change', dimensionsChangeFunction); - elDimensionsZ.addEventListener('change', dimensionsChangeFunction); - - elParentID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentID')); - elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex')); - - var registrationChangeFunction = createEmitVec3PropertyUpdateFunction( - 'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ); - elRegistrationX.addEventListener('change', registrationChangeFunction); - elRegistrationY.addEventListener('change', registrationChangeFunction); - elRegistrationZ.addEventListener('change', registrationChangeFunction); - - var rotationChangeFunction = createEmitVec3PropertyUpdateFunction( - 'rotation', elRotationX, elRotationY, elRotationZ); - elRotationX.addEventListener('change', rotationChangeFunction); - elRotationY.addEventListener('change', rotationChangeFunction); - elRotationZ.addEventListener('change', rotationChangeFunction); - - var velocityChangeFunction = createEmitVec3PropertyUpdateFunction( - 'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ); - elLinearVelocityX.addEventListener('change', velocityChangeFunction); - elLinearVelocityY.addEventListener('change', velocityChangeFunction); - elLinearVelocityZ.addEventListener('change', velocityChangeFunction); - elLinearDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('damping')); - - var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( - 'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ, DEGREES_TO_RADIANS); - elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction); - elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction); - elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction); - elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping')); - - elRestitution.addEventListener('change', createEmitNumberPropertyUpdateFunction('restitution')); - elFriction.addEventListener('change', createEmitNumberPropertyUpdateFunction('friction')); - - var gravityChangeFunction = createEmitVec3PropertyUpdateFunction( - 'gravity', elGravityX, elGravityY, elGravityZ); - elGravityX.addEventListener('change', gravityChangeFunction); - elGravityY.addEventListener('change', gravityChangeFunction); - elGravityZ.addEventListener('change', gravityChangeFunction); - - var accelerationChangeFunction = createEmitVec3PropertyUpdateFunction( - 'acceleration', elAccelerationX, elAccelerationY, elAccelerationZ); - elAccelerationX.addEventListener('change', accelerationChangeFunction); - elAccelerationY.addEventListener('change', accelerationChangeFunction); - elAccelerationZ.addEventListener('change', accelerationChangeFunction); - - elDensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('density')); - elCollisionless.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionless')); - elDynamic.addEventListener('change', createEmitCheckedPropertyUpdateFunction('dynamic')); - - elCollideDynamic.addEventListener('change', function() { - updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideDynamic, 'dynamic'); - }); - - elCollideKinematic.addEventListener('change', function() { - updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideKinematic, 'kinematic'); - }); - - elCollideStatic.addEventListener('change', function() { - updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideStatic, 'static'); - }); - elCollideMyAvatar.addEventListener('change', function() { - updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideMyAvatar, 'myAvatar'); - }); - elCollideOtherAvatar.addEventListener('change', function() { - updateCheckedSubProperty("collidesWith", properties.collidesWith, elCollideOtherAvatar, 'otherAvatar'); - }); - - elGrabbable.addEventListener('change', function() { - userDataChanger("grabbableKey", "grabbable", elGrabbable, elUserData, properties.dynamic); - }); - elWantsTrigger.addEventListener('change', function() { - userDataChanger("grabbableKey", "wantsTrigger", elWantsTrigger, elUserData, false); - }); - elIgnoreIK.addEventListener('change', function() { - userDataChanger("grabbableKey", "ignoreIK", elIgnoreIK, elUserData, false); - }); - - elCollisionSoundURL.addEventListener('change', createEmitTextPropertyUpdateFunction('collisionSoundURL')); - - elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); - elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); - /* - FIXME: See FIXME for property-script-url. - elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp')); - */ - elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); - - var colorChangeFunction = createEmitColorPropertyUpdateFunction( - 'color', elColorRed, elColorGreen, elColorBlue); - elColorRed.addEventListener('change', colorChangeFunction); - elColorGreen.addEventListener('change', colorChangeFunction); - elColorBlue.addEventListener('change', colorChangeFunction); - colorPickers.push($('#property-color').colpick({ - colorScheme: 'dark', - layout: 'hex', - color: '000000', - onShow: function (colpick) { - $('#property-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#property-color').attr('active', 'false'); - }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); - emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); - } - })); - - elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight')); - - var lightColorChangeFunction = createEmitColorPropertyUpdateFunction( - 'color', elLightColorRed, elLightColorGreen, elLightColorBlue); - elLightColorRed.addEventListener('change', lightColorChangeFunction); - elLightColorGreen.addEventListener('change', lightColorChangeFunction); - elLightColorBlue.addEventListener('change', lightColorChangeFunction); - colorPickers.push($('#property-light-color').colpick({ - colorScheme: 'dark', - layout: 'hex', - color: '000000', - onShow: function (colpick) { - $('#property-light-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#property-light-color').attr('active', 'false'); - }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); - emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); - } - })); - - elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity', 1)); - elLightFalloffRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('falloffRadius', 1)); - elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent', 2)); - elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff', 2)); - - elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); - - elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); - - elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL')); - elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType')); - elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL')); - - elModelAnimationURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('animation', 'url')); - elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation','running')); - elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation','fps')); - elModelAnimationFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'currentFrame')); - elModelAnimationFirstFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'firstFrame')); - elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame')); - elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop')); - elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold')); - - elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); - - elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); - elTextFaceCamera.addEventListener('change', createEmitCheckedPropertyUpdateFunction('faceCamera')); - elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); - var textTextColorChangeFunction = createEmitColorPropertyUpdateFunction( - 'textColor', elTextTextColorRed, elTextTextColorGreen, elTextTextColorBlue); - elTextTextColorRed.addEventListener('change', textTextColorChangeFunction); - elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction); - elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction); - colorPickers.push($('#property-text-text-color').colpick({ - colorScheme:'dark', - layout:'hex', - color: '000000', - onShow: function (colpick) { - $('#property-text-text-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#property-text-text-color').attr('active', 'false'); - }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); - $(el).colpickHide(); - $(el).attr('active', 'false'); - emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); - } - })); - - var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction( - 'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue); - elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction); - elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); - elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); - colorPickers.push($('#property-text-background-color').colpick({ - colorScheme:'dark', - layout:'hex', - color:'000000', - onShow: function (colpick) { - $('#property-text-background-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#property-text-background-color').attr('active', 'false'); - }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); - $(el).colpickHide(); - emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); - } - })); - - elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled')); - colorPickers.push($('#property-zone-key-light-color').colpick({ - colorScheme:'dark', - layout:'hex', - color:'000000', - onShow: function (colpick) { - $('#property-zone-key-light-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#property-zone-key-light-color').attr('active', 'false'); - }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); - $(el).colpickHide(); - emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); - } - })); - var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight','color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); - elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction); - elZoneKeyLightColorGreen.addEventListener('change', zoneKeyLightColorChangeFunction); - elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction); - elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity')); - elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity')); - elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL')); - var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY); - elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction); - elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); - - elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude')); - elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude')); - elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude')); - elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','automaticHourDay')); - elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day')); - elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour')); - - - elZoneBackgroundMode.addEventListener('change', createEmitTextPropertyUpdateFunction('backgroundMode')); - var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox','color', - elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue); - elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction); - elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction); - elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction); - colorPickers.push($('#property-zone-skybox-color').colpick({ - colorScheme:'dark', - layout:'hex', - color:'000000', - onShow: function (colpick) { - $('#property-zone-skybox-color').attr('active', 'true'); - }, - onHide: function (colpick) { - $('#property-zone-skybox-color').attr('active', 'false'); - }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); - $(el).colpickHide(); - emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); - } - })); - - elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url')); - - elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed')); - elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed')); - - var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction( - 'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ); - elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction); - elVoxelVolumeSizeY.addEventListener('change', voxelVolumeSizeChangeFunction); - elVoxelVolumeSizeZ.addEventListener('change', voxelVolumeSizeChangeFunction); - elVoxelSurfaceStyle.addEventListener('change', createEmitTextPropertyUpdateFunction('voxelSurfaceStyle')); - elXTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('xTextureURL')); - elYTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('yTextureURL')); - elZTextureURL.addEventListener('change', createEmitTextPropertyUpdateFunction('zTextureURL')); - - elMoveSelectionToGrid.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "moveSelectionToGrid", - })); - }); - elMoveAllToGrid.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "moveAllToGrid", - })); - }); - elResetToNaturalDimensions.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "resetToNaturalDimensions", - })); - }); - elRescaleDimensionsButton.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "rescaleDimensions", - percentage: parseInt(elRescaleDimensionsPct.value), - })); - }); - /* - FIXME: See FIXME for property-script-url. - elReloadScriptButton.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "reloadScript" - })); - }); - */ - elPreviewCameraButton.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "previewCamera" - })); - }); - - window.onblur = function() { - // Fake a change event - var ev = document.createEvent("HTMLEvents"); - ev.initEvent("change", true, true); - document.activeElement.dispatchEvent(ev); - } - - // For input and textarea elements, select all of the text on focus - // WebKit-based browsers, such as is used with QWebView, have a quirk - // where the mouseup event comes after the focus event, causing the - // text to be deselected immediately after selecting all of the text. - // To make this work we block the first mouseup event after the elements - // received focus. If we block all mouseup events the user will not - // be able to click within the selected text. - // We also check to see if the value has changed to make sure we aren't - // blocking a mouse-up event when clicking on an input spinner. - var els = document.querySelectorAll("input, textarea"); - for (var i = 0; i < els.length; i++) { - var clicked = false; - var originalText; - els[i].onfocus = function(e) { - originalText = this.value; - this.select(); - clicked = false; - }; - els[i].onmouseup = function(e) { - if (!clicked && originalText == this.value) { - e.preventDefault(); - } - clicked = true; - }; - } - }); - - // Collapsible sections - var elCollapsible = document.getElementsByClassName("section-header"); - - var toggleCollapsedEvent = function (event) { - var element = event.target; - if (element.nodeName !== "DIV") { - element = element.parentNode; - } - var isCollapsed = element.getAttribute("collapsed") !== "true"; - element.setAttribute("collapsed", isCollapsed ? "true" : "false"); - element.getElementsByTagName("span")[0].textContent = isCollapsed ? "L" : "M"; - }; - - for (var i = 0, length = elCollapsible.length; i < length; i++) { - var element = elCollapsible[i]; - element.addEventListener("click", toggleCollapsedEvent, true); - }; - - - // Textarea scrollbars - var elTextareas = document.getElementsByTagName("TEXTAREA"); - - var textareaOnChangeEvent = function (event) { - setTextareaScrolling(event.target); - } - - for (var i = 0, length = elTextareas.length; i < length; i++) { - var element = elTextareas[i]; - setTextareaScrolling(element); - element.addEventListener("input", textareaOnChangeEvent, false); - element.addEventListener("change", textareaOnChangeEvent, false); - /* FIXME: Detect and update textarea scrolling attribute on resize. Unfortunately textarea doesn't have a resize - event; mouseup is a partial stand-in but doesn't handle resizing if mouse moves outside textarea rectangle. */ - element.addEventListener("mouseup", textareaOnChangeEvent, false); - }; - - // Dropdowns - // For each dropdown the following replacement is created in place of the oriringal dropdown... - // Structure created: - //
      - //
      display textcarat
      - //
      - //
        - //
      • 0) { - var el = elDropdowns[0]; - el.parentNode.removeChild(el); - elDropdowns = document.getElementsByTagName("select"); - } - - 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); -} - diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 490579e909..5898f85e90 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -492,8 +492,6 @@ function loaded() { var elYTextureURL = document.getElementById("property-y-texture-url"); var elZTextureURL = document.getElementById("property-z-texture-url"); - var elPreviewCameraButton = document.getElementById("preview-camera-button"); - if (window.EventBridge !== undefined) { var properties; EventBridge.scriptEventReceived.connect(function(data) { @@ -1133,12 +1131,6 @@ function loaded() { })); }); */ - elPreviewCameraButton.addEventListener("click", function() { - EventBridge.emitWebEvent(JSON.stringify({ - type: "action", - action: "previewCamera" - })); - }); window.onblur = function() { // Fake a change event From afe76c69d21ad158f5452465c833b91ce2e26e9e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 10 Aug 2016 10:41:16 +1200 Subject: [PATCH 70/78] Fix crash when adding new attachment --- libraries/avatars/src/AvatarData.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index dee0d1cb20..d0c7b3912c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -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); } From 8e56e0bf18782af197a0dc475486141fa081f262 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 10 Aug 2016 10:41:37 +1200 Subject: [PATCH 71/78] Fix QML warning --- interface/resources/qml/hifi/dialogs/attachments/Attachment.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml index 04e3934535..6d371741ea 100644 --- a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml +++ b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml @@ -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: { From 2360e90d395c5e9906188cfa3070b1913efc3909 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Aug 2016 15:48:31 -0700 Subject: [PATCH 72/78] simplify valid check for rotation --- scripts/system/controllers/teleport.js | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 5ec429fae0..5a1ae7e5ee 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -234,17 +234,12 @@ function Teleporter() { this.rightRay = function() { 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) : MyAvatar.headOrientation; - - var rightFinal = Quat.multiply(rightRotation, Quat.angleAxis(-90, { - x: 1, - y: 0, - z: 0 - })); + 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, - direction: Quat.getUp(pose.valid ? rightRotation : rightFinal), + direction: Quat.getUp(rightRotation), }; this.rightPickRay = rightPickRay; @@ -287,17 +282,12 @@ function Teleporter() { this.leftRay = function() { 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) : MyAvatar.headOrientation; - - var leftFinal = Quat.multiply(leftRotation, Quat.angleAxis(-90, { - x: 1, - y: 0, - z: 0 - })); + 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, - direction: Quat.getUp(pose.valid ? leftRotation : leftFinal), + direction: Quat.getUp(leftRotation), }; this.leftPickRay = leftPickRay; From 50a4c8b4965fc7d6957554d7dbff221fa2949b33 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Aug 2016 18:02:56 -0700 Subject: [PATCH 73/78] mini mirror fades with overlays --- interface/src/ui/ApplicationOverlay.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 6d5df31766..888529da5c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -28,6 +28,8 @@ #include "Util.h" #include "ui/Stats.h" #include "ui/AvatarInputs.h" +#include "OffscreenUi.h" +#include 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()->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); } } From 9e20d922416e5278518fe3e097e1a77b0612a6e1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Aug 2016 10:35:18 -0700 Subject: [PATCH 74/78] CR changes --- libraries/gpu/src/gpu/Shader.h | 2 +- libraries/render-utils/src/AnimDebugDraw.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index a741eafd40..dcec023013 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -58,7 +58,7 @@ public: 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) {} + _name(name), _location(location), _element(element), _resourceType(resourceType), _size(size) {} Slot(const std::string& name) : _name(name) {} Slot& operator= (const Slot& s) { diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index f1443f7e4d..b905928423 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -7,6 +7,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "animdebugdraw_vert.h" #include "animdebugdraw_frag.h" #include @@ -15,8 +17,6 @@ #include "GLMHelpers.h" #include "DebugDraw.h" -#include - #include "AnimDebugDraw.h" struct Vertex { From e35d453b37782f27e98a5b5e2d77f716b009632e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Aug 2016 10:36:37 -0700 Subject: [PATCH 75/78] ...missing space --- libraries/gpu/src/gpu/Shader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index dcec023013..ebe0bc83df 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -58,7 +58,7 @@ public: 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) {} + _name(name), _location(location), _element(element), _resourceType(resourceType), _size(size) {} Slot(const std::string& name) : _name(name) {} Slot& operator= (const Slot& s) { From d8545bc7a3bbfd319ef11212d580bbed4d990d67 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Aug 2016 13:49:35 -0700 Subject: [PATCH 76/78] fix procedural transparency --- .../src/RenderableShapeEntityItem.cpp | 5 ----- .../procedural/src/procedural/Procedural.cpp | 21 +++++++++++++++---- .../procedural/src/procedural/Procedural.h | 10 ++++++--- .../src/procedural/ProceduralSkybox.cpp | 3 ++- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 73c4d99b5e..e14def114d 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -91,11 +91,6 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { _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(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); } gpu::Batch& batch = *args->_batch; diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index cd9edb6621..79a90ef72d 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -63,7 +63,19 @@ QJsonValue Procedural::getProceduralData(const QString& proceduralJson) { return doc.object()[PROCEDURAL_USER_DATA_KEY]; } -Procedural::Procedural() : _state { std::make_shared() } { +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; } @@ -230,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); } @@ -268,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); @@ -277,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(); diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index c2939e4a01..fdca85bbae 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -43,15 +43,17 @@ public: glm::vec4 getColor(const glm::vec4& entityColor); quint64 getFadeStartTime() { return _fadeStartTime; } - bool isFading() { return _isFading; } + 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::StatePointer _transparentState { std::make_shared() }; enum StandardUniforms { DATE, @@ -89,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; @@ -113,6 +116,7 @@ private: quint64 _fadeStartTime; bool _hasStartedFade { false }; bool _isFading { false }; + bool _doesFade { true }; }; #endif diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 9e9a26d902..843df3aa8d 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -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() { From 5bac88c00431b60f3c9484d28d7c204663e48964 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Aug 2016 10:52:36 -0700 Subject: [PATCH 77/78] default domain-server permissions to connect for standard --- domain-server/src/DomainServerSettingsManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 47187fac5c..c7944bbcad 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -532,9 +532,12 @@ void DomainServerSettingsManager::unpackPermissions() { // we don't have permissions for one of the standard groups, so we'll add them now NodePermissionsPointer perms { new NodePermissions(standardKey) }; - // the localhost user is granted all permissions by default if (standardKey == NodePermissions::standardNameLocalhost) { + // the localhost user is granted all permissions by default perms->setAll(true); + } else { + // anonymous, logged in, and friend users get connect permissions by default + perms->set(NodePermissions::Permission::canConnectToDomain); } // add the permissions to the standard map From 0f988fb209cdc93a6a848495a6f66e7346e23fc9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 11 Aug 2016 13:05:16 -0700 Subject: [PATCH 78/78] don't always mark _shaderDirty when user data changes unless url actually changes --- libraries/procedural/src/procedural/Procedural.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 79a90ef72d..27662e96d0 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -115,6 +115,11 @@ bool Procedural::parseUrl(const QUrl& shaderUrl) { return false; } + // If the URL hasn't changed, don't mark the shader as dirty + if (_shaderUrl == shaderUrl) { + return true; + } + _shaderUrl = shaderUrl; _shaderDirty = true;