mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 12:12:39 +02:00
Merge pull request #16258 from samcake/yellow
DEV-1815: Investigating rendering issues with opacity map and adding tools to debug resource caches
This commit is contained in:
commit
e8f1eecc5b
45 changed files with 1376 additions and 177 deletions
|
@ -106,8 +106,8 @@
|
|||
#include <MessagesClient.h>
|
||||
#include <hfm/ModelFormatRegistry.h>
|
||||
#include <model-networking/ModelCacheScriptingInterface.h>
|
||||
#include <material-networking/MaterialCacheScriptingInterface.h>
|
||||
#include <material-networking/TextureCacheScriptingInterface.h>
|
||||
#include <material-networking/MaterialCache.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <NetworkingConstants.h>
|
||||
|
@ -886,6 +886,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<TextureCache>();
|
||||
DependencyManager::set<MaterialCache>();
|
||||
DependencyManager::set<TextureCacheScriptingInterface>();
|
||||
DependencyManager::set<MaterialCacheScriptingInterface>();
|
||||
DependencyManager::set<FramebufferCache>();
|
||||
DependencyManager::set<AnimationCache>();
|
||||
DependencyManager::set<AnimationCacheScriptingInterface>();
|
||||
|
@ -2906,6 +2907,7 @@ Application::~Application() {
|
|||
DependencyManager::destroy<AnimationCacheScriptingInterface>();
|
||||
DependencyManager::destroy<AnimationCache>();
|
||||
DependencyManager::destroy<FramebufferCache>();
|
||||
DependencyManager::destroy<MaterialCacheScriptingInterface>();
|
||||
DependencyManager::destroy<MaterialCache>();
|
||||
DependencyManager::destroy<TextureCacheScriptingInterface>();
|
||||
DependencyManager::destroy<TextureCache>();
|
||||
|
@ -3431,6 +3433,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
// Caches
|
||||
surfaceContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCacheScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("TextureCache", DependencyManager::get<TextureCacheScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("MaterialCache", DependencyManager::get<MaterialCacheScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("ModelCache", DependencyManager::get<ModelCacheScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
|
||||
|
||||
|
@ -7461,6 +7464,7 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
|
|||
// Caches
|
||||
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCacheScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("TextureCache", DependencyManager::get<TextureCacheScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("MaterialCache", DependencyManager::get<MaterialCacheScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("ModelCache", DependencyManager::get<ModelCacheScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
|
||||
|
||||
|
|
|
@ -108,15 +108,6 @@ protected:
|
|||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
||||
virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; }
|
||||
|
||||
template <typename F, typename T>
|
||||
T withReadLockResult(const std::function<T()>& f) {
|
||||
T result;
|
||||
withReadLock([&] {
|
||||
result = f();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace scriptable {
|
|||
* @property {string} emissiveMap
|
||||
* @property {string} albedoMap
|
||||
* @property {string} opacityMap
|
||||
* @property {string} opacityMapMode
|
||||
* @property {number|string} opacityCutoff
|
||||
* @property {string} metallicMap
|
||||
* @property {string} specularMap
|
||||
* @property {string} roughnessMap
|
||||
|
@ -84,6 +86,8 @@ namespace scriptable {
|
|||
QString emissiveMap;
|
||||
QString albedoMap;
|
||||
QString opacityMap;
|
||||
QString opacityMapMode;
|
||||
float opacityCutoff;
|
||||
QString metallicMap;
|
||||
QString specularMap;
|
||||
QString roughnessMap;
|
||||
|
@ -94,7 +98,6 @@ namespace scriptable {
|
|||
QString lightMap;
|
||||
QString scatteringMap;
|
||||
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms;
|
||||
|
||||
bool defaultFallthrough;
|
||||
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
|
||||
|
||||
|
|
|
@ -420,6 +420,18 @@ namespace scriptable {
|
|||
obj.setProperty("opacityMap", material.opacityMap);
|
||||
}
|
||||
|
||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT | graphics::MaterialKey::OPACITY_MASK_MAP_BIT)) {
|
||||
obj.setProperty("opacityMapMode", FALLTHROUGH);
|
||||
} else if (material.key.getOpacityMapMode() != graphics::Material::DEFAULT_OPACITY_MAP_MODE) {
|
||||
obj.setProperty("opacityMapMode", material.opacityMapMode);
|
||||
}
|
||||
|
||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT)) {
|
||||
obj.setProperty("opacityCutoff", FALLTHROUGH);
|
||||
} else if (material.key.isOpacityCutoff()) {
|
||||
obj.setProperty("opacityCutoff", material.opacityCutoff);
|
||||
}
|
||||
|
||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OCCLUSION_MAP_BIT)) {
|
||||
obj.setProperty("occlusionMap", FALLTHROUGH);
|
||||
} else if (!material.occlusionMap.isEmpty()) {
|
||||
|
|
|
@ -26,6 +26,7 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const
|
|||
roughness = material.roughness;
|
||||
metallic = material.metallic;
|
||||
scattering = material.scattering;
|
||||
opacityCutoff = material.opacityCutoff;
|
||||
unlit = material.unlit;
|
||||
emissive = material.emissive;
|
||||
albedo = material.albedo;
|
||||
|
@ -41,6 +42,8 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const
|
|||
occlusionMap = material.occlusionMap;
|
||||
lightMap = material.lightMap;
|
||||
scatteringMap = material.scatteringMap;
|
||||
opacityMapMode = material.opacityMapMode;
|
||||
|
||||
|
||||
defaultFallthrough = material.defaultFallthrough;
|
||||
propertyFallthroughs = material.propertyFallthroughs;
|
||||
|
@ -55,9 +58,12 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint
|
|||
name = material->getName().c_str();
|
||||
model = material->getModel().c_str();
|
||||
opacity = material->getOpacity();
|
||||
|
||||
opacityMapMode = QString(graphics::MaterialKey::getOpacityMapModeName(material->getOpacityMapMode()).c_str());
|
||||
roughness = material->getRoughness();
|
||||
metallic = material->getMetallic();
|
||||
scattering = material->getScattering();
|
||||
opacityCutoff = material->getOpacityCutoff();
|
||||
unlit = material->isUnlit();
|
||||
emissive = material->getEmissive();
|
||||
albedo = material->getAlbedo();
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include <Transform.h>
|
||||
|
||||
#include "GraphicsLogging.h"
|
||||
|
||||
using namespace graphics;
|
||||
using namespace gpu;
|
||||
|
||||
|
@ -22,7 +24,26 @@ const float Material::DEFAULT_OPACITY { 1.0f };
|
|||
const float Material::DEFAULT_ALBEDO { 0.5f };
|
||||
const float Material::DEFAULT_METALLIC { 0.0f };
|
||||
const float Material::DEFAULT_ROUGHNESS { 1.0f };
|
||||
const float Material::DEFAULT_SCATTERING { 0.0f };
|
||||
const float Material::DEFAULT_SCATTERING{ 0.0f };
|
||||
const MaterialKey::OpacityMapMode Material::DEFAULT_OPACITY_MAP_MODE{ MaterialKey::OPACITY_MAP_OPAQUE };
|
||||
const float Material::DEFAULT_OPACITY_CUTOFF { 0.5f };
|
||||
|
||||
|
||||
std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) {
|
||||
const std::string names[3] = { "OPACITY_MAP_OPAQUE", "OPACITY_MAP_MASK", "OPACITY_MAP_BLEND" };
|
||||
return names[mode];
|
||||
}
|
||||
|
||||
|
||||
bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, MaterialKey::OpacityMapMode& mode) {
|
||||
for (int i = OPACITY_MAP_OPAQUE; i <= OPACITY_MAP_BLEND; i++) {
|
||||
mode = (MaterialKey::OpacityMapMode) i;
|
||||
if (modeName == getOpacityMapModeName(mode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Material::Material() {
|
||||
for (int i = 0; i < NUM_TOTAL_FLAGS; i++) {
|
||||
|
@ -40,6 +61,7 @@ Material::Material(const Material& material) :
|
|||
_roughness(material._roughness),
|
||||
_metallic(material._metallic),
|
||||
_scattering(material._scattering),
|
||||
_opacityCutoff(material._opacityCutoff),
|
||||
_texcoordTransforms(material._texcoordTransforms),
|
||||
_lightmapParams(material._lightmapParams),
|
||||
_materialParams(material._materialParams),
|
||||
|
@ -50,7 +72,7 @@ Material::Material(const Material& material) :
|
|||
}
|
||||
|
||||
Material& Material::operator=(const Material& material) {
|
||||
QMutexLocker locker(&_textureMapsMutex);
|
||||
std::lock_guard<std::recursive_mutex> locker(_textureMapsMutex);
|
||||
|
||||
_name = material._name;
|
||||
_model = material._model;
|
||||
|
@ -61,6 +83,7 @@ Material& Material::operator=(const Material& material) {
|
|||
_roughness = material._roughness;
|
||||
_metallic = material._metallic;
|
||||
_scattering = material._scattering;
|
||||
_opacityCutoff = material._opacityCutoff;
|
||||
_texcoordTransforms = material._texcoordTransforms;
|
||||
_lightmapParams = material._lightmapParams;
|
||||
_materialParams = material._materialParams;
|
||||
|
@ -109,8 +132,22 @@ void Material::setScattering(float scattering) {
|
|||
_scattering = scattering;
|
||||
}
|
||||
|
||||
void Material::setOpacityCutoff(float opacityCutoff) {
|
||||
opacityCutoff = glm::clamp(opacityCutoff, 0.0f, 1.0f);
|
||||
_key.setOpacityCutoff(opacityCutoff != DEFAULT_OPACITY_CUTOFF);
|
||||
_opacityCutoff = opacityCutoff;
|
||||
}
|
||||
|
||||
void Material::setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode) {
|
||||
_key.setOpacityMapMode(opacityMapMode);
|
||||
}
|
||||
|
||||
MaterialKey::OpacityMapMode Material::getOpacityMapMode() const {
|
||||
return _key.getOpacityMapMode();
|
||||
}
|
||||
|
||||
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
|
||||
QMutexLocker locker(&_textureMapsMutex);
|
||||
std::lock_guard<std::recursive_mutex> locker(_textureMapsMutex);
|
||||
|
||||
if (textureMap) {
|
||||
_key.setMapChannel(channel, true);
|
||||
|
@ -139,7 +176,14 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur
|
|||
|
||||
}
|
||||
|
||||
void Material::resetOpacityMap() const {
|
||||
bool Material::resetOpacityMap() const {
|
||||
// If OpacityMapMode explicit then nothing need to change here.
|
||||
if (_key.isOpacityMapMode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Else, the legacy behavior is to interpret the albedo texture assigned to tune the opacity map mode value
|
||||
auto previous = _key.getOpacityMapMode();
|
||||
// Clear the previous flags
|
||||
_key.setOpacityMaskMap(false);
|
||||
_key.setTranslucentMap(false);
|
||||
|
@ -163,10 +207,16 @@ void Material::resetOpacityMap() const {
|
|||
}
|
||||
}
|
||||
}
|
||||
auto newious = _key.getOpacityMapMode();
|
||||
if (previous != newious) {
|
||||
//opacity change detected for this material
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const TextureMapPointer Material::getTextureMap(MapChannel channel) const {
|
||||
QMutexLocker locker(&_textureMapsMutex);
|
||||
std::lock_guard<std::recursive_mutex> locker(_textureMapsMutex);
|
||||
|
||||
auto result = _textureMaps.find(channel);
|
||||
if (result != _textureMaps.end()) {
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
#ifndef hifi_model_Material_h
|
||||
#define hifi_model_Material_h
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
#include <mutex>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
@ -44,6 +43,8 @@ public:
|
|||
OPACITY_VAL_BIT,
|
||||
OPACITY_MASK_MAP_BIT, // Opacity Map and Opacity MASK map are mutually exclusive
|
||||
OPACITY_TRANSLUCENT_MAP_BIT,
|
||||
OPACITY_MAP_MODE_BIT, // Opacity map mode bit is set if the value has set explicitely and not deduced from the textures assigned
|
||||
OPACITY_CUTOFF_VAL_BIT,
|
||||
SCATTERING_VAL_BIT,
|
||||
|
||||
// THe map bits must be in the same sequence as the enum names for the map channels
|
||||
|
@ -73,6 +74,15 @@ public:
|
|||
NUM_MAP_CHANNELS,
|
||||
};
|
||||
|
||||
enum OpacityMapMode {
|
||||
OPACITY_MAP_OPAQUE = 0,
|
||||
OPACITY_MAP_MASK,
|
||||
OPACITY_MAP_BLEND,
|
||||
};
|
||||
static std::string getOpacityMapModeName(OpacityMapMode mode);
|
||||
// find the enum value from a string, return true if match found
|
||||
static bool getOpacityMapModeFromName(const std::string& modeName, OpacityMapMode& mode);
|
||||
|
||||
// The signature is the Flags
|
||||
Flags _flags;
|
||||
|
||||
|
@ -94,6 +104,27 @@ public:
|
|||
Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT); return (*this); }
|
||||
|
||||
Builder& withTranslucentFactor() { _flags.set(OPACITY_VAL_BIT); return (*this); }
|
||||
Builder& withTranslucentMap() { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT); return (*this); }
|
||||
Builder& withMaskMap() { _flags.set(OPACITY_MASK_MAP_BIT); return (*this); }
|
||||
Builder& withOpacityMapMode(OpacityMapMode mode) {
|
||||
switch (mode) {
|
||||
case OPACITY_MAP_OPAQUE:
|
||||
_flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
|
||||
_flags.reset(OPACITY_MASK_MAP_BIT);
|
||||
break;
|
||||
case OPACITY_MAP_MASK:
|
||||
_flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
|
||||
_flags.set(OPACITY_MASK_MAP_BIT);
|
||||
break;
|
||||
case OPACITY_MAP_BLEND:
|
||||
_flags.set(OPACITY_TRANSLUCENT_MAP_BIT);
|
||||
_flags.reset(OPACITY_MASK_MAP_BIT);
|
||||
break;
|
||||
};
|
||||
_flags.set(OPACITY_MAP_MODE_BIT); // Intentionally set the mode!
|
||||
return (*this);
|
||||
}
|
||||
Builder& withOpacityCutoff() { _flags.set(OPACITY_CUTOFF_VAL_BIT); return (*this); }
|
||||
|
||||
Builder& withScattering() { _flags.set(SCATTERING_VAL_BIT); return (*this); }
|
||||
|
||||
|
@ -102,9 +133,6 @@ public:
|
|||
Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); }
|
||||
Builder& withRoughnessMap() { _flags.set(ROUGHNESS_MAP_BIT); return (*this); }
|
||||
|
||||
Builder& withTranslucentMap() { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT); return (*this); }
|
||||
Builder& withMaskMap() { _flags.set(OPACITY_MASK_MAP_BIT); return (*this); }
|
||||
|
||||
Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
|
||||
Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); }
|
||||
Builder& withLightMap() { _flags.set(LIGHT_MAP_BIT); return (*this); }
|
||||
|
@ -151,6 +179,9 @@ public:
|
|||
void setOpacityMaskMap(bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); }
|
||||
bool isOpacityMaskMap() const { return _flags[OPACITY_MASK_MAP_BIT]; }
|
||||
|
||||
void setOpacityCutoff(bool value) { _flags.set(OPACITY_CUTOFF_VAL_BIT, value); }
|
||||
bool isOpacityCutoff() const { return _flags[OPACITY_CUTOFF_VAL_BIT]; }
|
||||
|
||||
void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); }
|
||||
bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; }
|
||||
|
||||
|
@ -171,6 +202,26 @@ public:
|
|||
|
||||
|
||||
// Translucency and Opacity Heuristics are combining several flags:
|
||||
void setOpacityMapMode(OpacityMapMode mode) {
|
||||
switch (mode) {
|
||||
case OPACITY_MAP_OPAQUE:
|
||||
_flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
|
||||
_flags.reset(OPACITY_MASK_MAP_BIT);
|
||||
break;
|
||||
case OPACITY_MAP_MASK:
|
||||
_flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
|
||||
_flags.set(OPACITY_MASK_MAP_BIT);
|
||||
break;
|
||||
case OPACITY_MAP_BLEND:
|
||||
_flags.set(OPACITY_TRANSLUCENT_MAP_BIT);
|
||||
_flags.reset(OPACITY_MASK_MAP_BIT);
|
||||
break;
|
||||
};
|
||||
_flags.set(OPACITY_MAP_MODE_BIT); // Intentionally set the mode!
|
||||
}
|
||||
bool isOpacityMapMode() const { return _flags[OPACITY_MAP_MODE_BIT]; }
|
||||
OpacityMapMode getOpacityMapMode() const { return (isOpacityMaskMap() ? OPACITY_MAP_MASK : (isTranslucentMap() ? OPACITY_MAP_BLEND : OPACITY_MAP_OPAQUE)); }
|
||||
|
||||
bool isTranslucent() const { return isTranslucentFactor() || isTranslucentMap(); }
|
||||
bool isOpaque() const { return !isTranslucent(); }
|
||||
bool isSurfaceOpaque() const { return isOpaque() && !isOpacityMaskMap(); }
|
||||
|
@ -229,6 +280,12 @@ public:
|
|||
Builder& withoutMaskMap() { _value.reset(MaterialKey::OPACITY_MASK_MAP_BIT); _mask.set(MaterialKey::OPACITY_MASK_MAP_BIT); return (*this); }
|
||||
Builder& withMaskMap() { _value.set(MaterialKey::OPACITY_MASK_MAP_BIT); _mask.set(MaterialKey::OPACITY_MASK_MAP_BIT); return (*this); }
|
||||
|
||||
Builder& withoutOpacityMapMode() { _value.reset(MaterialKey::OPACITY_MAP_MODE_BIT); _mask.set(MaterialKey::OPACITY_MAP_MODE_BIT); return (*this); }
|
||||
Builder& withOpacityMapMode() { _value.set(MaterialKey::OPACITY_MAP_MODE_BIT); _mask.set(MaterialKey::OPACITY_MAP_MODE_BIT); return (*this); }
|
||||
|
||||
Builder& withoutOpacityCutoff() { _value.reset(MaterialKey::OPACITY_CUTOFF_VAL_BIT); _mask.set(MaterialKey::OPACITY_CUTOFF_VAL_BIT); return (*this); }
|
||||
Builder& withOpacityCutoff() { _value.set(MaterialKey::OPACITY_CUTOFF_VAL_BIT); _mask.set(MaterialKey::OPACITY_CUTOFF_VAL_BIT); return (*this); }
|
||||
|
||||
Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); }
|
||||
Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); }
|
||||
|
||||
|
@ -283,6 +340,14 @@ public:
|
|||
void setOpacity(float opacity);
|
||||
float getOpacity() const { return _opacity; }
|
||||
|
||||
static const MaterialKey::OpacityMapMode DEFAULT_OPACITY_MAP_MODE;
|
||||
void setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode);
|
||||
MaterialKey::OpacityMapMode getOpacityMapMode() const;
|
||||
|
||||
static const float DEFAULT_OPACITY_CUTOFF;
|
||||
void setOpacityCutoff(float opacityCutoff);
|
||||
float getOpacityCutoff() const { return _opacityCutoff; }
|
||||
|
||||
void setUnlit(bool value);
|
||||
bool isUnlit() const { return _key.isUnlit(); }
|
||||
|
||||
|
@ -310,7 +375,8 @@ public:
|
|||
|
||||
// Albedo maps cannot have opacity detected until they are loaded
|
||||
// This method allows const changing of the key/schemaBuffer without touching the map
|
||||
void resetOpacityMap() const;
|
||||
// return true if the opacity changed, flase otherwise
|
||||
bool resetOpacityMap() const;
|
||||
|
||||
// conversion from legacy material properties to PBR equivalent
|
||||
static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; }
|
||||
|
@ -357,6 +423,7 @@ private:
|
|||
float _roughness { DEFAULT_ROUGHNESS };
|
||||
float _metallic { DEFAULT_METALLIC };
|
||||
float _scattering { DEFAULT_SCATTERING };
|
||||
float _opacityCutoff { DEFAULT_OPACITY_CUTOFF };
|
||||
std::array<glm::mat4, NUM_TEXCOORD_TRANSFORMS> _texcoordTransforms;
|
||||
glm::vec2 _lightmapParams { 0.0, 1.0 };
|
||||
glm::vec2 _materialParams { 0.0, 1.0 };
|
||||
|
@ -365,7 +432,7 @@ private:
|
|||
bool _defaultFallthrough { false };
|
||||
std::unordered_map<uint, bool> _propertyFallthroughs { NUM_TOTAL_FLAGS };
|
||||
|
||||
mutable QMutex _textureMapsMutex { QMutex::Recursive };
|
||||
mutable std::recursive_mutex _textureMapsMutex;
|
||||
};
|
||||
typedef std::shared_ptr<Material> MaterialPointer;
|
||||
|
||||
|
@ -425,18 +492,8 @@ public:
|
|||
|
||||
float _metallic { Material::DEFAULT_METALLIC }; // Not Metallic
|
||||
float _scattering { Material::DEFAULT_SCATTERING }; // Scattering info
|
||||
#if defined(__clang__)
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
glm::vec2 _spare { 0.0f }; // Padding
|
||||
|
||||
float _opacityCutoff { Material::DEFAULT_OPACITY_CUTOFF }; // Opacity cutoff applyed when using opacityMap as Mask
|
||||
uint32_t _key { 0 }; // a copy of the materialKey
|
||||
#if defined(__clang__)
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
glm::vec3 _spare2 { 0.0f };
|
||||
|
||||
// for alignment beauty, Material size == Mat4x4
|
||||
|
||||
// Texture Coord Transform Array
|
||||
glm::mat4 _texcoordTransforms[Material::NUM_TEXCOORD_TRANSFORMS];
|
||||
|
|
|
@ -49,8 +49,7 @@ struct TexMapArray {
|
|||
struct Material {
|
||||
vec4 _emissiveOpacity;
|
||||
vec4 _albedoRoughness;
|
||||
vec4 _metallicScatteringSpare2;
|
||||
vec4 _keySpare3;
|
||||
vec4 _metallicScatteringOpacityCutoffKey;
|
||||
};
|
||||
|
||||
LAYOUT_STD140(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer {
|
||||
|
@ -72,10 +71,11 @@ vec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; }
|
|||
float getMaterialRoughness(Material m) { return m._albedoRoughness.a; }
|
||||
float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
|
||||
|
||||
float getMaterialMetallic(Material m) { return m._metallicScatteringSpare2.x; }
|
||||
float getMaterialScattering(Material m) { return m._metallicScatteringSpare2.y; }
|
||||
float getMaterialMetallic(Material m) { return m._metallicScatteringOpacityCutoffKey.x; }
|
||||
float getMaterialScattering(Material m) { return m._metallicScatteringOpacityCutoffKey.y; }
|
||||
float getMaterialOpacityCutoff(Material m) { return m._metallicScatteringOpacityCutoffKey.z; }
|
||||
|
||||
BITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._keySpare3.x); }
|
||||
BITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._metallicScatteringOpacityCutoffKey.w); }
|
||||
|
||||
const BITFIELD EMISSIVE_VAL_BIT = 0x00000001;
|
||||
const BITFIELD UNLIT_VAL_BIT = 0x00000002;
|
||||
|
@ -85,16 +85,18 @@ const BITFIELD GLOSSY_VAL_BIT = 0x00000010;
|
|||
const BITFIELD OPACITY_VAL_BIT = 0x00000020;
|
||||
const BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;
|
||||
const BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;
|
||||
const BITFIELD SCATTERING_VAL_BIT = 0x00000100;
|
||||
const BITFIELD OPACITY_MAP_MODE_BIT = 0x00000100;
|
||||
const BITFIELD OPACITY_CUTOFF_VAL_BIT = 0x00000200;
|
||||
const BITFIELD SCATTERING_VAL_BIT = 0x00000400;
|
||||
|
||||
|
||||
const BITFIELD EMISSIVE_MAP_BIT = 0x00000200;
|
||||
const BITFIELD ALBEDO_MAP_BIT = 0x00000400;
|
||||
const BITFIELD METALLIC_MAP_BIT = 0x00000800;
|
||||
const BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;
|
||||
const BITFIELD NORMAL_MAP_BIT = 0x00002000;
|
||||
const BITFIELD OCCLUSION_MAP_BIT = 0x00004000;
|
||||
const BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;
|
||||
const BITFIELD SCATTERING_MAP_BIT = 0x00010000;
|
||||
const BITFIELD EMISSIVE_MAP_BIT = 0x00000800;
|
||||
const BITFIELD ALBEDO_MAP_BIT = 0x00001000;
|
||||
const BITFIELD METALLIC_MAP_BIT = 0x00002000;
|
||||
const BITFIELD ROUGHNESS_MAP_BIT = 0x00004000;
|
||||
const BITFIELD NORMAL_MAP_BIT = 0x00008000;
|
||||
const BITFIELD OCCLUSION_MAP_BIT = 0x00010000;
|
||||
const BITFIELD LIGHTMAP_MAP_BIT = 0x00020000;
|
||||
const BITFIELD SCATTERING_MAP_BIT = 0x00040000;
|
||||
|
||||
<@endif@>
|
||||
|
|
|
@ -214,14 +214,22 @@ vec3 fetchLightMap(vec2 uv) {
|
|||
}
|
||||
<@endfunc@>
|
||||
|
||||
<@func evalMaterialOpacity(fetchedOpacity, materialOpacity, matKey, opacity)@>
|
||||
<@func evalMaterialOpacityMask(fetchedOpacity, materialOpacityCutoff, opacity)@>
|
||||
{
|
||||
const float OPACITY_MASK_THRESHOLD = 0.5;
|
||||
<$opacity$> = mix(1.0,
|
||||
mix(<$fetchedOpacity$>,
|
||||
step(OPACITY_MASK_THRESHOLD, <$fetchedOpacity$>),
|
||||
float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)),
|
||||
float((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0)) * <$materialOpacity$>;
|
||||
// This path only valid for opaque or texel opaque material
|
||||
<$opacity$> = step(<$materialOpacityCutoff$>, <$fetchedOpacity$>);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@>
|
||||
{
|
||||
// This path only valid for transparent material
|
||||
// Assert that float((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0)) == 1.0
|
||||
<$opacity$> = mix(<$fetchedOpacity$>,
|
||||
step(<$materialOpacityCutoff$>, <$fetchedOpacity$>),
|
||||
float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0))
|
||||
* <$materialOpacity$>;
|
||||
}
|
||||
<@endfunc@>
|
||||
|
||||
|
|
|
@ -139,6 +139,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
|
||||
* value for transparency.
|
||||
* <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be:
|
||||
* <code>"OPACITY_MAP_OPAQUE"</code> for ignoring the opacity map information.
|
||||
* <code>"OPACITY_MAP_MASK"</code> for using the opacity map as a mask, where only the texel greater than opacityCutoff are visible and rendered opaque.
|
||||
* <code>"OPACITY_MAP_BLEND"</code> for using the opacity map for alpha blending the material surface with the background.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} opacityCutoff - The opacity cutoff threshold used to determine the opaque texels of the Opacity map
|
||||
* when opacityMapMode is "OPACITY_MAP_MASK", range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not
|
||||
* both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
|
@ -258,6 +266,24 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
} else if (value.isDouble()) {
|
||||
material->setMetallic(value.toDouble());
|
||||
}
|
||||
} else if (key == "opacityMapMode") {
|
||||
auto value = materialJSON.value(key);
|
||||
auto valueString = (value.isString() ? value.toString() : "");
|
||||
if (valueString == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_MAP_MODE_BIT);
|
||||
} else {
|
||||
graphics::MaterialKey::OpacityMapMode mode;
|
||||
if (graphics::MaterialKey::getOpacityMapModeFromName(valueString.toStdString(), mode)) {
|
||||
material->setOpacityMapMode(mode);
|
||||
}
|
||||
}
|
||||
} else if (key == "opacityCutoff") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isString() && value.toString() == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_CUTOFF_VAL_BIT);
|
||||
} else if (value.isDouble()) {
|
||||
material->setOpacityCutoff(value.toDouble());
|
||||
}
|
||||
} else if (key == "scattering") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isString() && value.toString() == FALLTHROUGH) {
|
||||
|
@ -748,13 +774,14 @@ bool NetworkMaterial::isMissingTexture() {
|
|||
return false;
|
||||
}
|
||||
|
||||
void NetworkMaterial::checkResetOpacityMap() {
|
||||
bool NetworkMaterial::checkResetOpacityMap() {
|
||||
// If material textures are loaded, check the material translucency
|
||||
// FIXME: This should not be done here. The opacity map should already be reset in Material::setTextureMap.
|
||||
// However, currently that code can be called before the albedo map is defined, so resetOpacityMap will fail.
|
||||
// Geometry::areTexturesLoaded() is called repeatedly until it returns true, so we do the check here for now
|
||||
const auto& albedoTexture = _textures[NetworkMaterial::MapChannel::ALBEDO_MAP];
|
||||
if (albedoTexture.texture) {
|
||||
resetOpacityMap();
|
||||
return resetOpacityMap();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
void setLightMap(const QUrl& url);
|
||||
|
||||
bool isMissingTexture();
|
||||
void checkResetOpacityMap();
|
||||
bool checkResetOpacityMap();
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// MaterialCacheScriptingInterface.cpp
|
||||
// libraries/mmodel-networking/src/model-networking
|
||||
//
|
||||
// Created by Sam Gateau on 17 September 2019.
|
||||
// Copyright 2019 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 "MaterialCacheScriptingInterface.h"
|
||||
|
||||
MaterialCacheScriptingInterface::MaterialCacheScriptingInterface() :
|
||||
ScriptableResourceCache::ScriptableResourceCache(DependencyManager::get<MaterialCache>())
|
||||
{ }
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// MaterialCacheScriptingInterface.h
|
||||
// libraries/material-networking/src/material-networking
|
||||
//
|
||||
// Created by Sam Gateau on 17 September 2019.
|
||||
// Copyright 2019 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
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef hifi_MaterialCacheScriptingInterface_h
|
||||
#define hifi_MaterialCacheScriptingInterface_h
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <ResourceCache.h>
|
||||
|
||||
#include "MaterialCache.h"
|
||||
|
||||
class MaterialCacheScriptingInterface : public ScriptableResourceCache, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
// Properties are copied over from ResourceCache (see ResourceCache.h for reason).
|
||||
|
||||
/**jsdoc
|
||||
* The <code>TextureCache</code> API manages texture cache resources.
|
||||
*
|
||||
* @namespace TextureCache
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {number} numTotal - Total number of total resources. <em>Read-only.</em>
|
||||
* @property {number} numCached - Total number of cached resource. <em>Read-only.</em>
|
||||
* @property {number} sizeTotal - Size in bytes of all resources. <em>Read-only.</em>
|
||||
* @property {number} sizeCached - Size in bytes of all cached resources. <em>Read-only.</em>
|
||||
*
|
||||
* @borrows ResourceCache.getResourceList as getResourceList
|
||||
* @borrows ResourceCache.updateTotalSize as updateTotalSize
|
||||
* @borrows ResourceCache.prefetch as prefetch
|
||||
* @borrows ResourceCache.dirty as dirty
|
||||
*/
|
||||
|
||||
public:
|
||||
MaterialCacheScriptingInterface();
|
||||
};
|
||||
|
||||
#endif // hifi_MaterialCacheScriptingInterface_h
|
|
@ -472,7 +472,10 @@ bool Geometry::areTexturesLoaded() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
material->checkResetOpacityMap();
|
||||
bool changed = material->checkResetOpacityMap();
|
||||
if (changed) {
|
||||
qCWarning(modelnetworking) << "Material list: opacity change detected for material " << material->getName().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& materialMapping : _materialMapping) {
|
||||
|
@ -483,7 +486,10 @@ bool Geometry::areTexturesLoaded() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
materialPair.second->checkResetOpacityMap();
|
||||
bool changed = materialPair.second->checkResetOpacityMap();
|
||||
if (changed) {
|
||||
qCWarning(modelnetworking) << "Mapping list: opacity change detected for material " << materialPair.first.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,6 +148,8 @@ void ResourceCacheSharedItems::clear() {
|
|||
|
||||
ScriptableResourceCache::ScriptableResourceCache(QSharedPointer<ResourceCache> resourceCache) {
|
||||
_resourceCache = resourceCache;
|
||||
connect(&(*_resourceCache), &ResourceCache::dirty,
|
||||
this, &ScriptableResourceCache::dirty, Qt::DirectConnection);
|
||||
}
|
||||
|
||||
QVariantList ScriptableResourceCache::getResourceList() {
|
||||
|
@ -323,7 +325,11 @@ QVariantList ResourceCache::getResourceList() {
|
|||
BLOCKING_INVOKE_METHOD(this, "getResourceList",
|
||||
Q_RETURN_ARG(QVariantList, list));
|
||||
} else {
|
||||
auto resources = _resources.uniqueKeys();
|
||||
QList<QUrl> resources;
|
||||
{
|
||||
QReadLocker locker(&_resourcesLock);
|
||||
resources = _resources.uniqueKeys();
|
||||
}
|
||||
list.reserve(resources.size());
|
||||
for (auto& resource : resources) {
|
||||
list << resource;
|
||||
|
@ -510,7 +516,7 @@ void ResourceCache::updateTotalSize(const qint64& deltaSize) {
|
|||
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
|
||||
QList<QSharedPointer<Resource>> ResourceCache::getLoadingRequests() {
|
||||
return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequests();
|
||||
}
|
||||
|
|
|
@ -317,6 +317,13 @@ class ScriptableResourceCache : public QObject {
|
|||
Q_PROPERTY(size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
|
||||
|
||||
/**jsdoc
|
||||
* @property {number} numGlobalQueriesPending - Total number of global queries pending (across all resource managers). <em>Read-only.</em>
|
||||
* @property {number} numGlobalQueriesLoading - Total number of global queries loading (across all resource managers). <em>Read-only.</em>
|
||||
*/
|
||||
Q_PROPERTY(size_t numGlobalQueriesPending READ getNumGlobalQueriesPending NOTIFY dirty)
|
||||
Q_PROPERTY(size_t numGlobalQueriesLoading READ getNumGlobalQueriesLoading NOTIFY dirty)
|
||||
|
||||
public:
|
||||
ScriptableResourceCache(QSharedPointer<ResourceCache> resourceCache);
|
||||
|
||||
|
@ -390,6 +397,9 @@ private:
|
|||
size_t getSizeTotalResources() const { return _resourceCache->getSizeTotalResources(); }
|
||||
size_t getNumCachedResources() const { return _resourceCache->getNumCachedResources(); }
|
||||
size_t getSizeCachedResources() const { return _resourceCache->getSizeCachedResources(); }
|
||||
|
||||
size_t getNumGlobalQueriesPending() const { return ResourceCache::getPendingRequestCount(); }
|
||||
size_t getNumGlobalQueriesLoading() const { return ResourceCache::getLoadingRequestCount(); }
|
||||
};
|
||||
|
||||
/// Base class for resources.
|
||||
|
|
|
@ -461,6 +461,13 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
wasSet = true;
|
||||
}
|
||||
break;
|
||||
case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT:
|
||||
if (materialKey.isOpacityCutoff()) {
|
||||
schema._opacityCutoff = material->getOpacityCutoff();
|
||||
schemaKey.setOpacityCutoff(true);
|
||||
wasSet = true;
|
||||
}
|
||||
break;
|
||||
case graphics::MaterialKey::SCATTERING_VAL_BIT:
|
||||
if (materialKey.isScattering()) {
|
||||
schema._scattering = material->getScattering();
|
||||
|
@ -752,7 +759,7 @@ bool RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu:
|
|||
|
||||
// For shadows, we only need opacity mask information
|
||||
auto key = multiMaterial.getMaterialKey();
|
||||
if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE || key.isOpacityMaskMap()) {
|
||||
if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE || (key.isOpacityMaskMap() || key.isTranslucentMap())) {
|
||||
auto& schemaBuffer = multiMaterial.getSchemaBuffer();
|
||||
batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer);
|
||||
if (enableTextures) {
|
||||
|
|
|
@ -103,14 +103,14 @@ void main(void) {
|
|||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
|
||||
|
||||
<@if HIFI_USE_TRANSLUCENT@>
|
||||
float cutoff = getMaterialOpacityCutoff(mat);
|
||||
float opacity = getMaterialOpacity(mat) * _color.a;
|
||||
<@else@>
|
||||
float opacity = 1.0;
|
||||
<@endif@>
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<@if HIFI_USE_TRANSLUCENT@>
|
||||
<$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>;
|
||||
<$discardInvisible(opacity)$>;
|
||||
<@else@>
|
||||
float cutoff = getMaterialOpacityCutoff(mat);
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
<@endif@>
|
||||
|
||||
|
@ -155,15 +155,15 @@ void main(void) {
|
|||
<@endif@>
|
||||
|
||||
<@if HIFI_USE_TRANSLUCENT@>
|
||||
float cutoff = getMaterialOpacityCutoff(mat);
|
||||
float opacity = getMaterialOpacity(mat) * _color.a;
|
||||
<$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>;
|
||||
<$discardInvisible(opacity)$>;
|
||||
<@else@>
|
||||
float cutoff = getMaterialOpacityCutoff(mat);
|
||||
float opacity = 1.0;
|
||||
<@endif@>
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<@if HIFI_USE_TRANSLUCENT@>
|
||||
<$discardInvisible(opacity)$>;
|
||||
<@else@>
|
||||
<$discardTransparent(opacity)$>;
|
||||
<$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
<@endif@>
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
|
@ -217,13 +217,13 @@ void main(void) {
|
|||
_fragColor0 = color;
|
||||
<@else@>
|
||||
_fragColor0 = vec4(evalLightmappedColor(
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
fragNormalWS,
|
||||
albedo,
|
||||
lightmap),
|
||||
opacity);
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
fragNormalWS,
|
||||
albedo,
|
||||
lightmap),
|
||||
opacity);
|
||||
<@endif@>
|
||||
<@else@>
|
||||
<@if not HIFI_USE_LIGHTMAP@>
|
||||
|
@ -241,13 +241,13 @@ void main(void) {
|
|||
opacity);
|
||||
<@else@>
|
||||
_fragColor0 = vec4(evalLightmappedColor(
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
fragNormalWS,
|
||||
albedo,
|
||||
lightmap),
|
||||
opacity);
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
fragNormalWS,
|
||||
albedo,
|
||||
lightmap),
|
||||
opacity);
|
||||
<@endif@>
|
||||
<@endif@>
|
||||
<@else@>
|
||||
|
@ -315,13 +315,13 @@ void main(void) {
|
|||
opacity);
|
||||
<@else@>
|
||||
_fragColor0 = vec4(evalLightmappedColor(
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
fragNormalWS,
|
||||
albedo,
|
||||
lightmap),
|
||||
opacity);
|
||||
cam._viewInverse,
|
||||
1.0,
|
||||
DEFAULT_OCCLUSION,
|
||||
fragNormalWS,
|
||||
albedo,
|
||||
lightmap),
|
||||
opacity);
|
||||
<@endif@>
|
||||
<@endif@>
|
||||
<@endif@>
|
||||
|
|
|
@ -63,4 +63,6 @@ void EngineStats::run(const RenderContextPointer& renderContext) {
|
|||
|
||||
config->frameSetPipelineCount = _gpuStats._PSNumSetPipelines;
|
||||
config->frameSetInputFormatCount = _gpuStats._ISNumFormatChanges;
|
||||
|
||||
// These new stat values are notified with the "newStats" signal triggered by the timer
|
||||
}
|
||||
|
|
|
@ -24,42 +24,42 @@ namespace render {
|
|||
class EngineStatsConfig : public Job::Config{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(quint32 bufferCPUCount MEMBER bufferCPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 bufferGPUCount MEMBER bufferGPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 bufferCPUMemSize MEMBER bufferCPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 bufferGPUMemSize MEMBER bufferGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 bufferCPUCount MEMBER bufferCPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 bufferGPUCount MEMBER bufferGPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 bufferCPUMemSize MEMBER bufferCPUMemSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 bufferGPUMemSize MEMBER bufferGPUMemSize NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(quint32 textureCPUCount MEMBER textureCPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 textureGPUCount MEMBER textureGPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 textureResidentGPUCount MEMBER textureResidentGPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 textureFramebufferGPUCount MEMBER textureFramebufferGPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 textureResourceGPUCount MEMBER textureResourceGPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 textureExternalGPUCount MEMBER textureExternalGPUCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 textureCPUCount MEMBER textureCPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 textureGPUCount MEMBER textureGPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 textureResidentGPUCount MEMBER textureResidentGPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 textureFramebufferGPUCount MEMBER textureFramebufferGPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 textureResourceGPUCount MEMBER textureResourceGPUCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 textureExternalGPUCount MEMBER textureExternalGPUCount NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(qint64 textureCPUMemSize MEMBER textureCPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureGPUMemSize MEMBER textureGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureResidentGPUMemSize MEMBER textureResidentGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureFramebufferGPUMemSize MEMBER textureFramebufferGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureResourceGPUMemSize MEMBER textureResourceGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureExternalGPUMemSize MEMBER textureExternalGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureCPUMemSize MEMBER textureCPUMemSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 textureGPUMemSize MEMBER textureGPUMemSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 textureResidentGPUMemSize MEMBER textureResidentGPUMemSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 textureFramebufferGPUMemSize MEMBER textureFramebufferGPUMemSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 textureResourceGPUMemSize MEMBER textureResourceGPUMemSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 textureExternalGPUMemSize MEMBER textureExternalGPUMemSize NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(quint32 texturePendingGPUTransferCount MEMBER texturePendingGPUTransferCount NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 texturePendingGPUTransferSize MEMBER texturePendingGPUTransferSize NOTIFY dirty)
|
||||
Q_PROPERTY(qint64 textureResourcePopulatedGPUMemSize MEMBER textureResourcePopulatedGPUMemSize NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 texturePendingGPUTransferCount MEMBER texturePendingGPUTransferCount NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 texturePendingGPUTransferSize MEMBER texturePendingGPUTransferSize NOTIFY newStats)
|
||||
Q_PROPERTY(qint64 textureResourcePopulatedGPUMemSize MEMBER textureResourcePopulatedGPUMemSize NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(quint32 frameAPIDrawcallCount MEMBER frameAPIDrawcallCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameDrawcallCount MEMBER frameDrawcallCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameDrawcallRate MEMBER frameDrawcallRate NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameAPIDrawcallCount MEMBER frameAPIDrawcallCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 frameDrawcallCount MEMBER frameDrawcallCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 frameDrawcallRate MEMBER frameDrawcallRate NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(quint32 frameTriangleCount MEMBER frameTriangleCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameTriangleRate MEMBER frameTriangleRate NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameTriangleCount MEMBER frameTriangleCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 frameTriangleRate MEMBER frameTriangleRate NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(quint32 frameTextureCount MEMBER frameTextureCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameTextureRate MEMBER frameTextureRate NOTIFY dirty)
|
||||
Q_PROPERTY(quint64 frameTextureMemoryUsage MEMBER frameTextureMemoryUsage NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameTextureCount MEMBER frameTextureCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 frameTextureRate MEMBER frameTextureRate NOTIFY newStats)
|
||||
Q_PROPERTY(quint64 frameTextureMemoryUsage MEMBER frameTextureMemoryUsage NOTIFY newStats)
|
||||
|
||||
Q_PROPERTY(quint32 frameSetPipelineCount MEMBER frameSetPipelineCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameSetInputFormatCount MEMBER frameSetInputFormatCount NOTIFY dirty)
|
||||
Q_PROPERTY(quint32 frameSetPipelineCount MEMBER frameSetPipelineCount NOTIFY newStats)
|
||||
Q_PROPERTY(quint32 frameSetInputFormatCount MEMBER frameSetInputFormatCount NOTIFY newStats)
|
||||
|
||||
|
||||
public:
|
||||
|
@ -101,13 +101,6 @@ namespace render {
|
|||
quint32 frameSetPipelineCount{ 0 };
|
||||
|
||||
quint32 frameSetInputFormatCount{ 0 };
|
||||
|
||||
|
||||
|
||||
void emitDirty() { emit dirty(); }
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class EngineStats {
|
||||
|
|
59
scripts/developer/utilities/cache/cash.js
vendored
Normal file
59
scripts/developer/utilities/cache/cash.js
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
"use strict";
|
||||
var Page = Script.require('../lib/skit/Page.js');
|
||||
|
||||
function openView() {
|
||||
//window.closed.connect(function() { Script.stop(); });
|
||||
|
||||
|
||||
var pages = new Pages(Script.resolvePath("."));
|
||||
function fromQml(message) {
|
||||
console.log(JSON.stringify(message))
|
||||
if (message.method == "inspectResource") {
|
||||
pages.open("openResourceInspector")
|
||||
pages.sendTo("openResourceInspector", message)
|
||||
return;
|
||||
}
|
||||
if (pages.open(message.method)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function openCashWindow(window) {
|
||||
var onMousePressEvent = function (e) {
|
||||
};
|
||||
Controller.mousePressEvent.connect(onMousePressEvent);
|
||||
|
||||
var onMouseReleaseEvent = function () {
|
||||
};
|
||||
Controller.mouseReleaseEvent.connect(onMouseReleaseEvent);
|
||||
|
||||
var onMouseMoveEvent = function (e) {
|
||||
};
|
||||
Controller.mouseMoveEvent.connect(onMouseMoveEvent);
|
||||
}
|
||||
|
||||
function closeCashWindow() {
|
||||
Controller.mousePressEvent.disconnect(onMousePressEvent);
|
||||
Controller.mouseReleaseEvent.disconnect(onMouseReleaseEvent);
|
||||
Controller.mouseMoveEvent.disconnect(onMouseMoveEvent);
|
||||
pages.clear();
|
||||
}
|
||||
|
||||
|
||||
pages.addPage('Cash', 'Cash', "cash.qml", 300, 500, fromQml, openCashWindow, closeCashWindow);
|
||||
pages.addPage('openModelCacheInspector', 'Model Cache Inspector', "cash/ModelCacheInspector.qml", 300, 500, fromQml);
|
||||
pages.addPage('openMaterialCacheInspector', 'Material Cache Inspector', "cash/MaterialCacheInspector.qml", 300, 500, fromQml);
|
||||
pages.addPage('openTextureCacheInspector', 'Texture Cache Inspector', "cash/TextureCacheInspector.qml", 300, 500, fromQml);
|
||||
pages.addPage('openAnimationCacheInspector', 'Animation Cache Inspector', "cash/AnimationCacheInspector.qml", 300, 500);
|
||||
pages.addPage('openSoundCacheInspector', 'Sound Cache Inspector', "cash/SoundCacheInspector.qml", 300, 500);
|
||||
pages.addPage('openResourceInspector', 'Resource Inspector', "cash/ResourceInspector.qml", 300, 500);
|
||||
|
||||
|
||||
pages.open('Cash');
|
||||
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
|
||||
openView();
|
167
scripts/developer/utilities/cache/cash.qml
vendored
Normal file
167
scripts/developer/utilities/cache/cash.qml
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
//
|
||||
// cash.qml
|
||||
//
|
||||
// Created by Sam Gateau on 17/9/2019
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import controlsUit 1.0 as HifiControls
|
||||
|
||||
import "../lib/prop" as Prop
|
||||
import "cash"
|
||||
import "../lib/plotperf"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
id: root;
|
||||
|
||||
Prop.Global { id: global;}
|
||||
color: global.color
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
anchors.fill: parent
|
||||
contentWidth: parent.width
|
||||
clip: true
|
||||
|
||||
Column {
|
||||
id: column
|
||||
width: parent.width
|
||||
|
||||
Prop.PropFolderPanel {
|
||||
label: "Resource Queries Inspector"
|
||||
isUnfold: true
|
||||
panelFrameData: Component {
|
||||
Column {
|
||||
PlotPerf {
|
||||
title: "Global Queries"
|
||||
height: 80
|
||||
valueScale: 1
|
||||
valueUnit: ""
|
||||
plots: [
|
||||
{
|
||||
object: ModelCache,
|
||||
prop: "numGlobalQueriesPending",
|
||||
label: "Pending",
|
||||
color: "#1AC567"
|
||||
},
|
||||
{
|
||||
object: ModelCache,
|
||||
prop: "numGlobalQueriesLoading",
|
||||
label: "Loading",
|
||||
color: "#FEC567"
|
||||
},
|
||||
{
|
||||
object: ModelCache,
|
||||
prop: "numLoading",
|
||||
label: "Model Loading",
|
||||
color: "#C5FE67"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prop.PropFolderPanel {
|
||||
label: "Cache Inspectors"
|
||||
isUnfold: true
|
||||
panelFrameData: Component {
|
||||
Column {
|
||||
Prop.PropButton {
|
||||
text: "Model"
|
||||
onClicked: {
|
||||
sendToScript({method: "openModelCacheInspector"});
|
||||
}
|
||||
width:column.width
|
||||
}
|
||||
Prop.PropButton {
|
||||
text: "Material"
|
||||
onClicked: {
|
||||
sendToScript({method: "openMaterialCacheInspector"});
|
||||
}
|
||||
width:column.width
|
||||
}
|
||||
Prop.PropButton {
|
||||
text: "Texture"
|
||||
onClicked: {
|
||||
sendToScript({method: "openTextureCacheInspector"});
|
||||
}
|
||||
width:column.width
|
||||
}
|
||||
Prop.PropButton {
|
||||
text: "Animation"
|
||||
onClicked: {
|
||||
sendToScript({method: "openAnimationCacheInspector"});
|
||||
}
|
||||
width:column.width
|
||||
}
|
||||
Prop.PropButton {
|
||||
text: "Sound"
|
||||
onClicked: {
|
||||
sendToScript({method: "openSoundCacheInspector"});
|
||||
}
|
||||
width:column.width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Prop.PropFolderPanel {
|
||||
label: "Stats"
|
||||
isUnfold: true
|
||||
panelFrameData: Component { Column {
|
||||
PlotPerf {
|
||||
title: "Resources"
|
||||
height: 200
|
||||
valueScale: 1
|
||||
valueUnit: ""
|
||||
plots: [
|
||||
{
|
||||
object: TextureCache,
|
||||
prop: "numTotal",
|
||||
label: "Textures",
|
||||
color: "#1AC567"
|
||||
},
|
||||
{
|
||||
object: TextureCache,
|
||||
prop: "numCached",
|
||||
label: "Textures Cached",
|
||||
color: "#FEC567"
|
||||
},
|
||||
{
|
||||
object: ModelCache,
|
||||
prop: "numTotal",
|
||||
label: "Models",
|
||||
color: "#FED959"
|
||||
},
|
||||
{
|
||||
object: ModelCache,
|
||||
prop: "numCached",
|
||||
label: "Models Cached",
|
||||
color: "#FEFE59"
|
||||
},
|
||||
{
|
||||
object: MaterialCache,
|
||||
prop: "numTotal",
|
||||
label: "Materials",
|
||||
color: "#00B4EF"
|
||||
},
|
||||
{
|
||||
object: MaterialCache,
|
||||
prop: "numCached",
|
||||
label: "Materials Cached",
|
||||
color: "#FFB4EF"
|
||||
}
|
||||
]
|
||||
}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
scripts/developer/utilities/cache/cash/AnimationCacheInspector.qml
vendored
Normal file
21
scripts/developer/utilities/cache/cash/AnimationCacheInspector.qml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// AnimationCacheInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
ResourceCacheInspector {
|
||||
id: root;
|
||||
anchors.fill: parent.fill
|
||||
cache: AnimationCache
|
||||
cacheResourceName: "Animation"
|
||||
}
|
21
scripts/developer/utilities/cache/cash/MaterialCacheInspector.qml
vendored
Normal file
21
scripts/developer/utilities/cache/cash/MaterialCacheInspector.qml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// MaterialCacheInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
ResourceCacheInspector {
|
||||
id: root;
|
||||
anchors.fill: parent.fill
|
||||
cache: MaterialCache
|
||||
cacheResourceName: "Material"
|
||||
}
|
21
scripts/developer/utilities/cache/cash/ModelCacheInspector.qml
vendored
Normal file
21
scripts/developer/utilities/cache/cash/ModelCacheInspector.qml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// ModelCacheInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
ResourceCacheInspector {
|
||||
id: root;
|
||||
anchors.fill: parent.fill
|
||||
cache: ModelCache
|
||||
cacheResourceName: "Model"
|
||||
}
|
367
scripts/developer/utilities/cache/cash/ResourceCacheInspector.qml
vendored
Normal file
367
scripts/developer/utilities/cache/cash/ResourceCacheInspector.qml
vendored
Normal file
|
@ -0,0 +1,367 @@
|
|||
//
|
||||
// ResourceCacheInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQml.Models 2.12
|
||||
|
||||
import "../../lib/skit/qml" as Skit
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
Prop.Global { id: global }
|
||||
|
||||
anchors.fill: parent.fill
|
||||
property var cache: {}
|
||||
property string cacheResourceName: ""
|
||||
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case "resetItemList":
|
||||
resetItemListFromCache()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function requestResourceDetails(resourceURL) {
|
||||
sendToScript({method: "inspectResource", params: {url: resourceURL, semantic: cacheResourceName}});
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
resetItemListFromCache();
|
||||
}
|
||||
|
||||
function fetchItemsList() {
|
||||
var theList;
|
||||
if (cache !== undefined) {
|
||||
theList = cache.getResourceList();
|
||||
} else {
|
||||
theList = ["ResourceCacheInspector.cache is undefined"];
|
||||
}
|
||||
var theListString = new Array(theList.length)
|
||||
for (var i in theList) {
|
||||
theListString[i] = (theList[i].toString())
|
||||
}
|
||||
return theListString;
|
||||
}
|
||||
|
||||
function resetItemListFromCache() {
|
||||
resetItemList(fetchItemsList())
|
||||
}
|
||||
|
||||
property var needFreshList : false
|
||||
|
||||
function updateItemListFromCache() {
|
||||
needFreshList = true
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
interval: 2000; running: true; repeat: true
|
||||
onTriggered: pullFreshValues()
|
||||
}
|
||||
|
||||
function pullFreshValues() {
|
||||
if (needFreshList) {
|
||||
updateItemList(fetchItemsList())
|
||||
needFreshList = false
|
||||
}
|
||||
}
|
||||
|
||||
property alias resourceItemsModel: visualModel.model
|
||||
property var currentItemsList: new Array();
|
||||
|
||||
function packItemEntry(item, identifier) {
|
||||
var entry = { "identifier": identifier, "name": "", "scheme": "", "host": "", "pathDir": "", "url": item}
|
||||
if (item.length > 0) {
|
||||
// Detect scheme:
|
||||
var schemePos = item.search(":")
|
||||
entry.scheme = item.substring(0, schemePos)
|
||||
if (schemePos < 0) schemePos = 0
|
||||
else schemePos += 1
|
||||
|
||||
// path pos is probably after schemePos
|
||||
var pathPos = schemePos
|
||||
|
||||
// try to detect //userinfo@host:port
|
||||
var token = item.substr(schemePos, 2);
|
||||
if (token.search("//") == 0) {
|
||||
pathPos += 2
|
||||
}
|
||||
item = item.substring(pathPos, item.length)
|
||||
// item is now everything after scheme:[//]
|
||||
var splitted = item.split('/')
|
||||
|
||||
// odd ball, the rest of the url has no other'/' ?
|
||||
// in theory this means it s just the host info ?
|
||||
// we are assuming that path ALWAYS starts with a slash
|
||||
entry.host = splitted[0]
|
||||
|
||||
if (splitted.length > 1) {
|
||||
entry.name = splitted[splitted.length - 1]
|
||||
|
||||
// if splitted is longer than 2 then there should be a path dir
|
||||
if (splitted.length > 2) {
|
||||
for (var i = 1; i < splitted.length - 1; i++) {
|
||||
entry.pathDir += '/' + splitted[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return entry
|
||||
}
|
||||
|
||||
|
||||
function resetItemList(itemList) {
|
||||
currentItemsList = []
|
||||
resourceItemsModel.clear()
|
||||
for (var i in itemList) {
|
||||
var item = itemList[i]
|
||||
currentItemsList.push(item)
|
||||
resourceItemsModel.append(packItemEntry(item, currentItemsList.length -1))
|
||||
}
|
||||
// At the end of it, force an update
|
||||
visualModel.forceUpdate()
|
||||
}
|
||||
|
||||
function updateItemList(newItemList) {
|
||||
resetItemList(newItemList)
|
||||
}
|
||||
|
||||
property var itemFields: ['identifier', 'name', 'scheme', 'host', 'pathDir', 'url']
|
||||
|
||||
|
||||
Column {
|
||||
id: header
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: totalCount.height
|
||||
id: headerTop
|
||||
|
||||
Prop.PropButton {
|
||||
id: refreshButton
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Refresh"
|
||||
color: needFreshList ? global.colorOrangeAccent : global.fontColor
|
||||
onPressed: { pullFreshValues() }
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
anchors.left: refreshButton.right
|
||||
anchors.right: parent.right
|
||||
id: headerCountLane
|
||||
columns: 3
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Prop.PropScalar {
|
||||
id: itemCount
|
||||
label: "Count"
|
||||
object: root.cache
|
||||
property: "numTotal"
|
||||
integral: true
|
||||
readOnly: true
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Prop.PropScalar {
|
||||
id: totalCount
|
||||
label: "Count"
|
||||
object: root.cache
|
||||
property: "numTotal"
|
||||
integral: true
|
||||
readOnly: true
|
||||
onSourceValueVarChanged: { updateItemListFromCache() }
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Prop.PropScalar {
|
||||
id: cachedCount
|
||||
label: "Cached"
|
||||
object: root.cache
|
||||
property: "numCached"
|
||||
integral: true
|
||||
readOnly: true
|
||||
onSourceValueVarChanged: { updateItemListFromCache() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: orderSelector.height
|
||||
|
||||
Prop.PropText {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 50
|
||||
id: orderSelectorLabel
|
||||
text: "Sort by"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
Prop.PropComboBox {
|
||||
anchors.left: orderSelectorLabel.right
|
||||
width: 80
|
||||
id: orderSelector
|
||||
model: itemFields
|
||||
currentIndex: 1
|
||||
|
||||
property var isSchemeVisible: (currentIndex == 2 || filterFieldSelector.currentIndex == 2)
|
||||
property var isHostVisible: (currentIndex == 3 || filterFieldSelector.currentIndex == 3)
|
||||
property var isPathDirVisible: (currentIndex == 4 || filterFieldSelector.currentIndex == 4)
|
||||
property var isURLVisible: (currentIndex == 5 || filterFieldSelector.currentIndex == 5)
|
||||
}
|
||||
|
||||
Prop.PropTextField {
|
||||
anchors.left: orderSelector.right
|
||||
anchors.right: filterFieldSelector.left
|
||||
id: nameFilter
|
||||
placeholderText: qsTr("Filter by " + itemFields[filterFieldSelector.currentIndex] + "...")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Prop.PropComboBox {
|
||||
anchors.right: parent.right
|
||||
id: filterFieldSelector
|
||||
model: itemFields
|
||||
currentIndex: 1
|
||||
width: 80
|
||||
opacity: (nameFilter.text.length > 0) ? 1.0 : 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: resouceItemDelegate
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
property bool held: false
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
height: item.height
|
||||
onPressed: {held = true}
|
||||
onReleased: {held = false}
|
||||
onDoubleClicked: { requestResourceDetails(model.url) }
|
||||
Rectangle {
|
||||
id: item
|
||||
width: parent.width
|
||||
height: global.slimHeight
|
||||
color: dragArea.held ? global.colorBackHighlight : (index % 2 ? global.colorBackShadow : global.colorBack)
|
||||
Row {
|
||||
id: itemRow
|
||||
anchors.verticalCenter : parent.verticalCenter
|
||||
Prop.PropText {
|
||||
id: itemIdentifier
|
||||
text: model.identifier
|
||||
width: 30
|
||||
}
|
||||
Prop.PropSplitter {
|
||||
visible: orderSelector.isSchemeVisible
|
||||
size:8
|
||||
}
|
||||
Prop.PropLabel {
|
||||
visible: orderSelector.isSchemeVisible
|
||||
text: model.scheme
|
||||
width: 30
|
||||
}
|
||||
Prop.PropSplitter {
|
||||
visible: orderSelector.isHostVisible
|
||||
size:8
|
||||
}
|
||||
Prop.PropLabel {
|
||||
visible: orderSelector.isHostVisible
|
||||
text: model.host
|
||||
width: 150
|
||||
}
|
||||
Prop.PropSplitter {
|
||||
visible: orderSelector.isPathDirVisible
|
||||
size:8
|
||||
}
|
||||
Prop.PropLabel {
|
||||
visible: orderSelector.isPathDirVisible
|
||||
text: model.pathDir
|
||||
}
|
||||
Prop.PropSplitter {
|
||||
size:8
|
||||
}
|
||||
Prop.PropLabel {
|
||||
visible: !orderSelector.isURLVisible
|
||||
text: model.name
|
||||
}
|
||||
Prop.PropLabel {
|
||||
visible: orderSelector.isURLVisible
|
||||
text: model.url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Skit.SortFilterModel {
|
||||
id: visualModel
|
||||
model: ListModel {}
|
||||
|
||||
property int sortOrder: orderSelector.currentIndex
|
||||
|
||||
property var lessThanArray: [
|
||||
function(left, right) { return left.index < right.index },
|
||||
function(left, right) { return left.name < right.name },
|
||||
function(left, right) { return left.scheme < right.scheme },
|
||||
function(left, right) { return left.host < right.host },
|
||||
function(left, right) { return left.pathDir < right.pathDir },
|
||||
function(left, right) { return left.url < right.url }
|
||||
];
|
||||
lessThan: lessThanArray[sortOrder]
|
||||
|
||||
property int filterField: filterFieldSelector.currentIndex
|
||||
onFilterFieldChanged: { refreshFilter() }
|
||||
property var textFilter: nameFilter.text
|
||||
onTextFilterChanged: { refreshFilter() }
|
||||
|
||||
function filterToken(itemWord, token) { return (itemWord.search(token) > -1) }
|
||||
property var acceptItemArray: [
|
||||
function(item) { return true },
|
||||
function(item) { return filterToken(item.identifier.toString(), textFilter) },
|
||||
function(item) { return filterToken(item.name, textFilter) },
|
||||
function(item) { return filterToken(item.scheme, textFilter) },
|
||||
function(item) { return filterToken(item.host, textFilter) },
|
||||
function(item) { return filterToken(item.pathDir, textFilter) },
|
||||
function(item) { return filterToken(item.url, textFilter) }
|
||||
]
|
||||
|
||||
function refreshFilter() {
|
||||
//console.log("refreshFilter! token = " + textFilter + " field = " + filterField)
|
||||
acceptItem = acceptItemArray[(textFilter.length != 0) * + (1 + filterField)]
|
||||
}
|
||||
|
||||
delegate: resouceItemDelegate
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.top: header.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
clip: true
|
||||
|
||||
id: listView
|
||||
model: visualModel
|
||||
}
|
||||
}
|
58
scripts/developer/utilities/cache/cash/ResourceInspector.qml
vendored
Normal file
58
scripts/developer/utilities/cache/cash/ResourceInspector.qml
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// ResourceInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-24
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQml.Models 2.12
|
||||
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
Item {
|
||||
id: root;
|
||||
Prop.Global { id: global }
|
||||
|
||||
anchors.fill: parent.fill
|
||||
property var cache: {}
|
||||
property string cacheResourceName: ""
|
||||
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case "inspectResource":
|
||||
inspectResource(message.params.url, message.params.semantic)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function inspectResource(url, semantic) {
|
||||
console.log("inspectResource :" + url + " as " + semantic)
|
||||
info.text = "url: " + url + "\nsemantic: " + semantic + "\n";
|
||||
|
||||
if (semantic == "Texture") {
|
||||
var res = TextureCache.prefetch(url, 0)
|
||||
info.text += JSON.stringify(res);
|
||||
} else if (semantic == "Model") {
|
||||
var res = ModelCache.prefetch(url)
|
||||
info.text += JSON.stringify(res);
|
||||
}
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: info
|
||||
anchors.fill: parent
|
||||
text: "Click an object to get material JSON"
|
||||
width: root.width
|
||||
font.pointSize: 10
|
||||
color: "#FFFFFF"
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
21
scripts/developer/utilities/cache/cash/SoundCacheInspector.qml
vendored
Normal file
21
scripts/developer/utilities/cache/cash/SoundCacheInspector.qml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// SoundCacheInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
ResourceCacheInspector {
|
||||
id: root;
|
||||
anchors.fill: parent.fill
|
||||
cache: SoundCache
|
||||
cacheResourceName: "Sound"
|
||||
}
|
21
scripts/developer/utilities/cache/cash/TextureCacheInspector.qml
vendored
Normal file
21
scripts/developer/utilities/cache/cash/TextureCacheInspector.qml
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// TextureCacheInspector.qml
|
||||
//
|
||||
// Created by Sam Gateau on 2019-09-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../lib/prop" as Prop
|
||||
|
||||
ResourceCacheInspector {
|
||||
id: root;
|
||||
anchors.fill: parent.fill
|
||||
cache: TextureCache
|
||||
cacheResourceName: "Texture"
|
||||
}
|
6
scripts/developer/utilities/cache/cash/qmldir
vendored
Normal file
6
scripts/developer/utilities/cache/cash/qmldir
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
ResourceCacheInspector 1.0 ResourceCacheInspector.qml
|
||||
TextureCacheInspector 1.0 TextureCacheInspector.qml
|
||||
MaterialCacheInspector 1.0 MaterialCacheInspector.qml
|
||||
ModelCacheInspector 1.0 ModelCacheInspector.qml
|
||||
AnimationCacheInspector 1.0 AnimationCacheInspector.qml
|
||||
SoundCacheInspector 1.0 SoundCacheInspector.qml
|
|
@ -91,12 +91,12 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
Original.ScrollView {
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
ListView {
|
||||
id: theView
|
||||
model: jobsModel
|
||||
delegate: objRecursiveDelegate
|
||||
}
|
||||
|
||||
id: theView
|
||||
model: jobsModel
|
||||
delegate: objRecursiveDelegate
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@ PropItem {
|
|||
id: root
|
||||
|
||||
property alias enums : valueCombo.model
|
||||
property alias currentIndex : valueCombo.currentIndex
|
||||
|
||||
PropComboBox {
|
||||
id: valueCombo
|
||||
|
|
|
@ -25,19 +25,16 @@ Item {
|
|||
//
|
||||
function defaultGet() { var v = root.object[root.property]; return v; }
|
||||
function defaultSet(value) { root.object[root.property] = value; }
|
||||
// function defaultSetReadOnly(value) { log ( "read only " + property + ", NOT setting to " + value); }
|
||||
// function defaultSetReadOnly(value) {}
|
||||
// property var valueVarSetter: (root.readOnly ? defaultSetReadOnly : defaultSet)
|
||||
property var valueVarSetter: defaultSet
|
||||
function defaultSetReadOnly(value) {}
|
||||
|
||||
property var valueVarSetter: (readOnly ? defaultSetReadOnly : defaultSet)
|
||||
property var valueVarGetter: defaultGet
|
||||
|
||||
// PropItem is stretching horizontally accross its parent
|
||||
// Fixed height
|
||||
height: global.lineHeight
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: global.lineHeight
|
||||
anchors.leftMargin: global.horizontalMargin
|
||||
anchors.rightMargin: global.horizontalMargin
|
||||
|
||||
// LabelControl And SplitterControl are on the left side of the PropItem
|
||||
property bool showLabel: true
|
||||
|
|
|
@ -32,9 +32,7 @@ PropItem {
|
|||
property var sourceValueVar: root.valueVarGetter()
|
||||
|
||||
function applyValueVarFromWidgets(value) {
|
||||
if (!root.readOnly) {
|
||||
root.valueVarSetter(value)
|
||||
}
|
||||
root.valueVarSetter(value)
|
||||
}
|
||||
|
||||
PropLabel {
|
||||
|
@ -58,6 +56,7 @@ PropItem {
|
|||
|
||||
MouseArea{
|
||||
id: mousearea
|
||||
enabled: !root.readOnly
|
||||
anchors.fill: parent
|
||||
onDoubleClicked: { sliderControl.visible = !sliderControl.visible }
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
Module Prop
|
||||
Global 1.0 style/Global.qml
|
||||
PropText 1.0 style/PiText.qml
|
||||
PropTextField 1.0 style/PiTextField.qml
|
||||
PropLabel 1.0 style/PiLabel.qml
|
||||
PropSplitter 1.0 style/PiSplitter.qml
|
||||
PropButton 1.0 style/PiButton.qml
|
||||
PropComboBox 1.0 style/PiComboBox.qml
|
||||
PropCanvasIcon 1.0 style/PiCanvasIcon.qml
|
||||
PropCheckBox 1.0 style/PiCheckBox.qml
|
||||
|
|
35
scripts/developer/utilities/lib/prop/style/PiButton.qml
Normal file
35
scripts/developer/utilities/lib/prop/style/PiButton.qml
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// Prop/style/PiButton.qml
|
||||
//
|
||||
// Created by Sam Gateau on 17/09/2019
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
Button {
|
||||
Global { id: global }
|
||||
id: control
|
||||
text: ""
|
||||
spacing: 0
|
||||
property alias color: theContentItem.color
|
||||
|
||||
contentItem: PiText {
|
||||
id: theContentItem
|
||||
text: control.text
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: global.fontColor
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: control.down ? global.colorBackHighlight : global.colorBackShadow
|
||||
opacity: enabled ? 1 : 0.3
|
||||
border.color: control.down ? global.colorBorderHighight : (control.hovered ? global.colorBorderHighight : global.colorBorderLight)
|
||||
border.width: global.valueBorderWidth
|
||||
radius: global.valueBorderRadius
|
||||
}
|
||||
}
|
|
@ -16,7 +16,9 @@ ComboBox {
|
|||
id: valueCombo
|
||||
|
||||
height: global.slimHeight
|
||||
|
||||
width: 120
|
||||
implicitHeight: global.slimHeight
|
||||
|
||||
|
||||
// look
|
||||
flat: true
|
||||
|
@ -51,8 +53,6 @@ ComboBox {
|
|||
}
|
||||
|
||||
background: Rectangle {
|
||||
implicitWidth: 120
|
||||
implicitHeight: 40
|
||||
color: global.colorBack
|
||||
border.color: valueCombo.popup.visible ? global.colorBorderLighter : global.colorBorderLight
|
||||
border.width: global.valueBorderWidth
|
||||
|
|
31
scripts/developer/utilities/lib/prop/style/PiTextField.qml
Normal file
31
scripts/developer/utilities/lib/prop/style/PiTextField.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Prop/style/PiTextField.qml
|
||||
//
|
||||
// Created by Sam Gateau on 9/24/2019
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
TextField {
|
||||
id: control
|
||||
Global { id: global }
|
||||
implicitHeight: global.slimHeight
|
||||
implicitWidth: 200
|
||||
|
||||
placeholderText: qsTr("Enter description")
|
||||
|
||||
color: global.fontColor
|
||||
font.pixelSize: global.fontSize
|
||||
font.family: global.fontFamily
|
||||
font.weight: global.fontWeight
|
||||
|
||||
background: Rectangle {
|
||||
color: (control.text.length > 0) ? global.colorBackHighlight : global.colorBackShadow
|
||||
border.color: (control.text.length > 0) ? global.colorBorderHighight : "transparent"
|
||||
}
|
||||
}
|
|
@ -10,11 +10,12 @@
|
|||
"use strict";
|
||||
|
||||
(function() {
|
||||
function Page(title, qmlurl, width, height, onViewCreated, onViewClosed) {
|
||||
function Page(title, qmlurl, width, height, onFromQml, onViewCreated, onViewClosed) {
|
||||
this.title = title;
|
||||
this.qml = qmlurl;
|
||||
this.qmlurl = qmlurl;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.onFromQml = onFromQml;
|
||||
this.onViewCreated = onViewCreated;
|
||||
this.onViewClosed = onViewClosed;
|
||||
|
||||
|
@ -30,6 +31,9 @@ Page.prototype.killView = function () {
|
|||
//this.window.closed.disconnect(function () {
|
||||
// this.killView();
|
||||
//});
|
||||
if (this.onFromQml) {
|
||||
this.window.fromQml.disconnect(this.onFromQml)
|
||||
}
|
||||
this.window.close();
|
||||
this.window = false;
|
||||
}
|
||||
|
@ -39,12 +43,15 @@ Page.prototype.createView = function () {
|
|||
var that = this;
|
||||
if (!this.window) {
|
||||
print("Page: New window for page:" + this.title);
|
||||
this.window = Desktop.createWindow(Script.resolvePath(this.qml), {
|
||||
this.window = Desktop.createWindow(this.qmlurl, {
|
||||
title: this.title,
|
||||
presentationMode: Desktop.PresentationMode.NATIVE,
|
||||
size: {x: this.width, y: this.height}
|
||||
});
|
||||
this.onViewCreated(this.window);
|
||||
if (this.onFromQml) {
|
||||
this.window.fromQml.connect(this.onFromQml)
|
||||
}
|
||||
this.window.closed.connect(function () {
|
||||
that.killView();
|
||||
that.onViewClosed();
|
||||
|
@ -53,11 +60,13 @@ Page.prototype.createView = function () {
|
|||
};
|
||||
|
||||
|
||||
Pages = function () {
|
||||
Pages = function (relativePath) {
|
||||
print(relativePath)
|
||||
this._relativePath = relativePath
|
||||
this._pages = {};
|
||||
};
|
||||
|
||||
Pages.prototype.addPage = function (command, title, qmlurl, width, height, onViewCreated, onViewClosed) {
|
||||
Pages.prototype.addPage = function (command, title, qmlurl, width, height, onFromQml, onViewCreated, onViewClosed) {
|
||||
if (onViewCreated === undefined) {
|
||||
// Workaround for bad linter
|
||||
onViewCreated = function(window) {};
|
||||
|
@ -66,7 +75,7 @@ Pages.prototype.addPage = function (command, title, qmlurl, width, height, onVie
|
|||
// Workaround for bad linter
|
||||
onViewClosed = function() {};
|
||||
}
|
||||
this._pages[command] = new Page(title, qmlurl, width, height, onViewCreated, onViewClosed);
|
||||
this._pages[command] = new Page(title, Script.resolvePath(this._relativePath + qmlurl), width, height, onFromQml, onViewCreated, onViewClosed);
|
||||
};
|
||||
|
||||
Pages.prototype.open = function (command) {
|
||||
|
@ -87,4 +96,12 @@ Pages.prototype.clear = function () {
|
|||
this._pages = {};
|
||||
};
|
||||
|
||||
Pages.prototype.sendTo = function (command, message) {
|
||||
if (!this._pages[command]) {
|
||||
print("Pages: unknown command = " + command);
|
||||
return;
|
||||
}
|
||||
this._pages[command].window.sendToQml(message);
|
||||
};
|
||||
|
||||
}());
|
93
scripts/developer/utilities/lib/skit/qml/SortFilterModel.qml
Normal file
93
scripts/developer/utilities/lib/skit/qml/SortFilterModel.qml
Normal file
|
@ -0,0 +1,93 @@
|
|||
import QtQuick 2.9
|
||||
import QtQml.Models 2.3
|
||||
|
||||
DelegateModel {
|
||||
id: delegateModel
|
||||
|
||||
property var lessThan: function(left, right) { return true; }
|
||||
property var acceptItem: function(item) { return true; }
|
||||
|
||||
function insertPosition(lessThanFunctor, item) {
|
||||
var lower = 0
|
||||
var upper = visibleItems.count
|
||||
while (lower < upper) {
|
||||
var middle = Math.floor(lower + (upper - lower) / 2)
|
||||
var result = lessThanFunctor(item.model, visibleItems.get(middle).model);
|
||||
if (result) {
|
||||
upper = middle
|
||||
} else {
|
||||
lower = middle + 1
|
||||
}
|
||||
}
|
||||
return lower
|
||||
}
|
||||
|
||||
function sortAndFilter(lessThanFunctor, acceptItemFunctor) {
|
||||
while (unsortedItems.count > 0) {
|
||||
var item = unsortedItems.get(0)
|
||||
|
||||
if (acceptItemFunctor(item.model)) {
|
||||
var index = insertPosition(lessThanFunctor, item)
|
||||
|
||||
item.groups = ["items","visible"]
|
||||
visibleItems.move(item.visibleIndex, index)
|
||||
} else {
|
||||
item.groups = ["items"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Private bool to track when items changed and view is dirty
|
||||
property bool itemsDirty: true
|
||||
function update() {
|
||||
console.log("SortFilterMode: update and sort and filter items !!" + items.count);
|
||||
if (items.count > 0) {
|
||||
items.setGroups(0, items.count, ["items","unsorted"]);
|
||||
}
|
||||
|
||||
sortAndFilter(lessThan, acceptItem)
|
||||
itemsDirty = false;
|
||||
itemsUpdated()
|
||||
}
|
||||
|
||||
signal itemsUpdated()
|
||||
|
||||
function updateOnItemsChanged() {
|
||||
itemsDirty = true;
|
||||
if (isAutoUpdateOnChanged) {
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
property bool isAutoUpdateOnChanged: false
|
||||
function setAutoUpdateOnChanged(enabled) {
|
||||
isAutoUpdateOnChanged = enabled
|
||||
if (enabled) {
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
function forceUpdate() {
|
||||
update();
|
||||
}
|
||||
items.onChanged: updateOnItemsChanged()
|
||||
onLessThanChanged: update()
|
||||
onAcceptItemChanged: update()
|
||||
|
||||
groups: [
|
||||
DelegateModelGroup {
|
||||
id: visibleItems
|
||||
|
||||
name: "visible"
|
||||
includeByDefault: false
|
||||
},
|
||||
DelegateModelGroup {
|
||||
id: unsortedItems
|
||||
|
||||
name: "unsorted"
|
||||
includeByDefault: false
|
||||
}
|
||||
]
|
||||
|
||||
filterOnGroup: "visible"
|
||||
}
|
1
scripts/developer/utilities/lib/skit/qml/qmldir
Normal file
1
scripts/developer/utilities/lib/skit/qml/qmldir
Normal file
|
@ -0,0 +1 @@
|
|||
SortFilterModel 1.0 SortFilterModel.qml
|
|
@ -1,14 +1,13 @@
|
|||
|
||||
|
||||
var MaterialInspector = Script.require('./materialInspector.js');
|
||||
var Page = Script.require('./luci/Page.js');
|
||||
|
||||
var Page = Script.require('../lib/skit/Page.js');
|
||||
|
||||
|
||||
function openView() {
|
||||
//window.closed.connect(function() { Script.stop(); });
|
||||
var pages = new Pages(Script.resolvePath("."));
|
||||
|
||||
|
||||
var pages = new Pages();
|
||||
function fromQml(message) {
|
||||
if (pages.open(message.method)) {
|
||||
return;
|
||||
|
@ -17,12 +16,6 @@ function openView() {
|
|||
|
||||
var luciWindow
|
||||
function openLuciWindow(window) {
|
||||
if (luciWindow !== undefined) {
|
||||
activeWindow.fromQml.disconnect(fromQml);
|
||||
}
|
||||
if (window !== undefined) {
|
||||
window.fromQml.connect(fromQml);
|
||||
}
|
||||
luciWindow = window;
|
||||
|
||||
|
||||
|
@ -57,9 +50,6 @@ function openView() {
|
|||
}
|
||||
|
||||
function closeLuciWindow() {
|
||||
if (luciWindow !== undefined) {
|
||||
activeWindow.fromQml.disconnect(fromQml);
|
||||
}
|
||||
luciWindow = {};
|
||||
|
||||
Controller.mousePressEvent.disconnect(onMousePressEvent);
|
||||
|
@ -68,10 +58,10 @@ function openView() {
|
|||
pages.clear();
|
||||
}
|
||||
|
||||
pages.addPage('Luci', 'Luci', '../luci.qml', 300, 420, openLuciWindow, closeLuciWindow);
|
||||
pages.addPage('openEngineInspectorView', 'Render Engine Inspector', '../engineInspector.qml', 300, 400);
|
||||
pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400);
|
||||
pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow, MaterialInspector.setWindow);
|
||||
pages.addPage('Luci', 'Luci', 'luci.qml', 300, 420, fromQml, openLuciWindow, closeLuciWindow);
|
||||
pages.addPage('openEngineInspectorView', 'Render Engine Inspector', 'engineInspector.qml', 300, 400);
|
||||
pages.addPage('openEngineLODView', 'Render LOD', 'lod.qml', 300, 400);
|
||||
pages.addPage('openMaterialInspectorView', 'Material Inspector', 'materialInspector.qml', 300, 400, null, MaterialInspector.setWindow, MaterialInspector.setWindow);
|
||||
|
||||
pages.open('Luci');
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ function fromQml(message) {
|
|||
|
||||
var SELECT_LIST = "luci_materialInspector_SelectionList";
|
||||
Selection.enableListHighlight(SELECT_LIST, {
|
||||
outlineUnoccludedColor: { red: 255, green: 255, blue: 255 }
|
||||
outlineUnoccludedColor: { red: 125, green: 255, blue: 225 }
|
||||
});
|
||||
function setSelectedObject(id, type) {
|
||||
Selection.clearSelectedItemsList(SELECT_LIST);
|
||||
|
|
|
@ -51,6 +51,12 @@ void RenderThread::initialize(QWindow* window) {
|
|||
_backend = _gpuContext->getBackend();
|
||||
_context.doneCurrent();
|
||||
_context.moveToThread(_thread);
|
||||
|
||||
if (!_presentPipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
_presentPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
#else
|
||||
auto size = window->size();
|
||||
_extent = vk::Extent2D{ (uint32_t)size.width(), (uint32_t)size.height() };
|
||||
|
@ -169,15 +175,28 @@ void RenderThread::renderFrame(gpu::FramePointer& frame) {
|
|||
}
|
||||
|
||||
#ifdef USE_GL
|
||||
static gpu::BatchPointer batch = nullptr;
|
||||
if (!batch) {
|
||||
batch = std::make_shared<gpu::Batch>();
|
||||
batch->setPipeline(_presentPipeline);
|
||||
batch->setFramebuffer(nullptr);
|
||||
batch->setResourceTexture(0, frame->framebuffer->getRenderBuffer(0));
|
||||
batch->setViewportTransform(ivec4(uvec2(0), ivec2(windowSize.width(), windowSize.height())));
|
||||
batch->draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
_gpuContext->executeBatch(*batch);
|
||||
|
||||
// Keep this raw gl code here for reference
|
||||
//glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||
/* glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(
|
||||
0, 0, fboSize.x, fboSize.y,
|
||||
0, 0, windowSize.width(), windowSize.height(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
*/
|
||||
(void)CHECK_GL_ERROR();
|
||||
_context.swapBuffers();
|
||||
_context.doneCurrent();
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
uint32_t _externalTexture{ 0 };
|
||||
void move(const glm::vec3& v);
|
||||
glm::mat4 _correction;
|
||||
|
||||
gpu::PipelinePointer _presentPipeline;
|
||||
|
||||
void resize(const QSize& newSize);
|
||||
void setup() override;
|
||||
|
|
Loading…
Reference in a new issue