mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' of github.com:highfidelity/hifi into friction
This commit is contained in:
commit
3167dc9a35
74 changed files with 1775 additions and 323 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <Assignment.h>
|
||||
#include <CrashAnnotations.h>
|
||||
#include <LogHandler.h>
|
||||
#include <LogUtils.h>
|
||||
#include <LimitedNodeList.h>
|
||||
|
@ -144,6 +145,7 @@ AssignmentClient::~AssignmentClient() {
|
|||
}
|
||||
|
||||
void AssignmentClient::aboutToQuit() {
|
||||
crash::annotations::setShutdownState(true);
|
||||
stopAssignmentClient();
|
||||
}
|
||||
|
||||
|
@ -173,6 +175,7 @@ void AssignmentClient::sendStatusPacketToACM() {
|
|||
|
||||
void AssignmentClient::sendAssignmentRequest() {
|
||||
if (!_currentAssignment && !_isAssigned) {
|
||||
crash::annotations::setShutdownState(false);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
|
@ -289,6 +292,8 @@ void AssignmentClient::handleAuthenticationRequest() {
|
|||
}
|
||||
|
||||
void AssignmentClient::assignmentCompleted() {
|
||||
crash::annotations::setShutdownState(true);
|
||||
|
||||
// we expect that to be here the previous assignment has completely cleaned up
|
||||
assert(_currentAssignment.isNull());
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <AccountManager.h>
|
||||
#include <AssetClient.h>
|
||||
#include <BuildInfo.h>
|
||||
#include <CrashAnnotations.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <HifiConfigVariantMap.h>
|
||||
#include <HTTPConnection.h>
|
||||
|
@ -185,6 +186,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
qDebug() << "[VERSION] BUILD_GLOBAL_SERVICES:" << BuildInfo::BUILD_GLOBAL_SERVICES;
|
||||
qDebug() << "[VERSION] We will be using this name to find ICE servers:" << _iceServerAddr;
|
||||
|
||||
connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit);
|
||||
|
||||
// make sure we have a fresh AccountManager instance
|
||||
// (need this since domain-server can restart itself and maintain static variables)
|
||||
|
@ -432,6 +434,10 @@ DomainServer::~DomainServer() {
|
|||
DependencyManager::destroy<LimitedNodeList>();
|
||||
}
|
||||
|
||||
void DomainServer::aboutToQuit() {
|
||||
crash::annotations::setShutdownState(true);
|
||||
}
|
||||
|
||||
void DomainServer::queuedQuit(QString quitMessage, int exitCode) {
|
||||
if (!quitMessage.isEmpty()) {
|
||||
qWarning() << qPrintable(quitMessage);
|
||||
|
|
|
@ -136,6 +136,8 @@ private slots:
|
|||
void tokenGrantFinished();
|
||||
void profileRequestFinished();
|
||||
|
||||
void aboutToQuit();
|
||||
|
||||
signals:
|
||||
void iceServerChanged();
|
||||
void userConnected();
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <BuildInfo.h>
|
||||
#include <CrashAnnotations.h>
|
||||
#include <LogHandler.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <BuildInfo.h>
|
||||
|
||||
#include "DomainServer.h"
|
||||
|
||||
|
@ -32,6 +33,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
// use a do-while to handle domain-server restart
|
||||
do {
|
||||
crash::annotations::setShutdownState(false);
|
||||
DomainServer domainServer(argc, argv);
|
||||
currentExitCode = domainServer.exec();
|
||||
} while (currentExitCode == DomainServer::EXIT_CODE_REBOOT);
|
||||
|
@ -39,4 +41,3 @@ int main(int argc, char* argv[]) {
|
|||
qInfo() << "Quitting.";
|
||||
return currentExitCode;
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2802,7 +2802,7 @@
|
|||
"children": [
|
||||
],
|
||||
"data": {
|
||||
"endFrame": 92,
|
||||
"endFrame": 84,
|
||||
"loopFlag": false,
|
||||
"startFrame": 1,
|
||||
"timeScale": 1,
|
||||
|
@ -2815,7 +2815,7 @@
|
|||
"children": [
|
||||
],
|
||||
"data": {
|
||||
"endFrame": 158,
|
||||
"endFrame": 100,
|
||||
"loopFlag": false,
|
||||
"startFrame": 1,
|
||||
"timeScale": 1,
|
||||
|
@ -4610,9 +4610,9 @@
|
|||
{
|
||||
"easingType": "easeInOutQuad",
|
||||
"id": "idle",
|
||||
"interpDuration": 10,
|
||||
"interpTarget": 10,
|
||||
"interpType": "snapshotPrev",
|
||||
"interpDuration": 20,
|
||||
"interpTarget": 20,
|
||||
"interpType": "evaluateBoth",
|
||||
"transitions": [
|
||||
{
|
||||
"state": "WALKFWD",
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
@ -8494,6 +8498,8 @@ void Application::toggleLogDialog() {
|
|||
Qt::WindowFlags flags = _logDialog->windowFlags() | Qt::Tool;
|
||||
_logDialog->setWindowFlags(flags);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(keepOnTop)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -3514,6 +3514,12 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
float timeScale = deltaTime * FPS;
|
||||
|
||||
bool faceForward = false;
|
||||
bool isMovingFwdBwd = getDriveKey(TRANSLATE_Z) != 0.0f;
|
||||
bool isMovingSideways = getDriveKey(TRANSLATE_X) != 0.0f;
|
||||
bool isCameraYawing = getDriveKey(DELTA_YAW) + getDriveKey(STEP_YAW) + getDriveKey(YAW) != 0.0f;
|
||||
bool isRotatingWhileSeated = !isCameraYawing && isMovingSideways && _characterController.getSeated();
|
||||
glm::quat previousOrientation = getWorldOrientation();
|
||||
|
||||
if (!computeLookAt) {
|
||||
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
|
||||
_lookAtCameraTarget = eyesPosition + getWorldOrientation() * Vectors::FRONT;
|
||||
|
@ -3536,9 +3542,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
_lookAtPitch = _previousLookAtPitch;
|
||||
}
|
||||
}
|
||||
bool isMovingFwdBwd = getDriveKey(TRANSLATE_Z) != 0.0f;
|
||||
bool isMovingSideways = getDriveKey(TRANSLATE_X) != 0.0f;
|
||||
bool isRotatingWhileSeated = isMovingSideways && _characterController.getSeated();
|
||||
|
||||
faceForward = isMovingFwdBwd || (isMovingSideways && !isRotatingWhileSeated);
|
||||
// Blend the avatar orientation with the camera look at if moving forward.
|
||||
if (faceForward || _shouldTurnToFaceCamera) {
|
||||
|
@ -3623,8 +3627,12 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
|||
if (frontBackDot < 0.0f) {
|
||||
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
|
||||
cameraVector = (ajustedYawVector * _lookAtPitch) * Vectors::FRONT;
|
||||
if (frontBackDot < -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE))) {
|
||||
_shouldTurnToFaceCamera = true;
|
||||
if (!isRotatingWhileSeated) {
|
||||
if (frontBackDot < -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE))) {
|
||||
_shouldTurnToFaceCamera = true;
|
||||
}
|
||||
} else {
|
||||
setWorldOrientation(previousOrientation);
|
||||
}
|
||||
} else if (frontBackDot > glm::sin(glm::radians(REORIENT_ANGLE))) {
|
||||
_shouldTurnToFaceCamera = false;
|
||||
|
|
|
@ -60,25 +60,13 @@ const int AudioClient::MIN_BUFFER_FRAMES = 1;
|
|||
|
||||
const int AudioClient::MAX_BUFFER_FRAMES = 20;
|
||||
|
||||
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100;
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
static const int CHECK_INPUT_READS_MSECS = 2000;
|
||||
static const int MIN_READS_TO_CONSIDER_INPUT_ALIVE = 10;
|
||||
#endif
|
||||
|
||||
static const auto DEFAULT_POSITION_GETTER = []{ return Vectors::ZERO; };
|
||||
static const auto DEFAULT_ORIENTATION_GETTER = [] { return Quaternions::IDENTITY; };
|
||||
|
||||
static const int DEFAULT_BUFFER_FRAMES = 1;
|
||||
|
||||
// OUTPUT_CHANNEL_COUNT is audio pipeline output format, which is always 2 channel.
|
||||
// _outputFormat.channelCount() is device output format, which may be 1 or multichannel.
|
||||
static const int OUTPUT_CHANNEL_COUNT = 2;
|
||||
|
||||
static const bool DEFAULT_STARVE_DETECTION_ENABLED = true;
|
||||
static const int STARVE_DETECTION_THRESHOLD = 3;
|
||||
static const int STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds
|
||||
const AudioClient::AudioPositionGetter AudioClient::DEFAULT_POSITION_GETTER = []{ return Vectors::ZERO; };
|
||||
const AudioClient::AudioOrientationGetter AudioClient::DEFAULT_ORIENTATION_GETTER = [] { return Quaternions::IDENTITY; };
|
||||
|
||||
Setting::Handle<bool> dynamicJitterBufferEnabled("dynamicJitterBuffersEnabled",
|
||||
InboundAudioStream::DEFAULT_DYNAMIC_JITTER_BUFFER_ENABLED);
|
||||
|
@ -272,55 +260,7 @@ static inline float convertToFloat(int16_t sample) {
|
|||
return (float)sample * (1 / 32768.0f);
|
||||
}
|
||||
|
||||
AudioClient::AudioClient() :
|
||||
AbstractAudioInterface(),
|
||||
_gate(this),
|
||||
_audioInput(NULL),
|
||||
_dummyAudioInput(NULL),
|
||||
_desiredInputFormat(),
|
||||
_inputFormat(),
|
||||
_numInputCallbackBytes(0),
|
||||
_audioOutput(NULL),
|
||||
_desiredOutputFormat(),
|
||||
_outputFormat(),
|
||||
_outputFrameSize(0),
|
||||
_numOutputCallbackBytes(0),
|
||||
_loopbackAudioOutput(NULL),
|
||||
_loopbackOutputDevice(NULL),
|
||||
_inputRingBuffer(0),
|
||||
_localInjectorsStream(0, 1),
|
||||
_receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES),
|
||||
_isStereoInput(false),
|
||||
_outputStarveDetectionStartTimeMsec(0),
|
||||
_outputStarveDetectionCount(0),
|
||||
_outputBufferSizeFrames("audioOutputBufferFrames", DEFAULT_BUFFER_FRAMES),
|
||||
_sessionOutputBufferSizeFrames(_outputBufferSizeFrames.get()),
|
||||
_outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", DEFAULT_STARVE_DETECTION_ENABLED),
|
||||
_lastRawInputLoudness(0.0f),
|
||||
_lastSmoothedRawInputLoudness(0.0f),
|
||||
_lastInputLoudness(0.0f),
|
||||
_timeSinceLastClip(-1.0f),
|
||||
_muted(false),
|
||||
_shouldEchoLocally(false),
|
||||
_shouldEchoToServer(false),
|
||||
_isNoiseGateEnabled(true),
|
||||
_isAECEnabled(true),
|
||||
_reverb(false),
|
||||
_reverbOptions(&_scriptReverbOptions),
|
||||
_inputToNetworkResampler(NULL),
|
||||
_networkToOutputResampler(NULL),
|
||||
_localToOutputResampler(NULL),
|
||||
_loopbackResampler(NULL),
|
||||
_audioLimiter(AudioConstants::SAMPLE_RATE, OUTPUT_CHANNEL_COUNT),
|
||||
_outgoingAvatarAudioSequenceNumber(0),
|
||||
_audioOutputIODevice(_localInjectorsStream, _receivedAudioStream, this),
|
||||
_stats(&_receivedAudioStream),
|
||||
_positionGetter(DEFAULT_POSITION_GETTER),
|
||||
#if defined(Q_OS_ANDROID)
|
||||
_checkInputTimer(this),
|
||||
_isHeadsetPluggedIn(false),
|
||||
#endif
|
||||
_orientationGetter(DEFAULT_ORIENTATION_GETTER) {
|
||||
AudioClient::AudioClient() {
|
||||
|
||||
// avoid putting a lock in the device callback
|
||||
assert(_localSamplesAvailable.is_lock_free());
|
||||
|
|
|
@ -80,6 +80,9 @@ class QIODevice;
|
|||
class Transform;
|
||||
class NLPacket;
|
||||
|
||||
#define DEFAULT_STARVE_DETECTION_ENABLED true
|
||||
#define DEFAULT_BUFFER_FRAMES 1
|
||||
|
||||
class AudioClient : public AbstractAudioInterface, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
@ -292,6 +295,16 @@ protected:
|
|||
virtual void customDeleter() override;
|
||||
|
||||
private:
|
||||
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES{ 100 };
|
||||
// OUTPUT_CHANNEL_COUNT is audio pipeline output format, which is always 2 channel.
|
||||
// _outputFormat.channelCount() is device output format, which may be 1 or multichannel.
|
||||
static const int OUTPUT_CHANNEL_COUNT{ 2 };
|
||||
static const int STARVE_DETECTION_THRESHOLD{ 3 };
|
||||
static const int STARVE_DETECTION_PERIOD{ 10 * 1000 }; // 10 Seconds
|
||||
|
||||
static const AudioPositionGetter DEFAULT_POSITION_GETTER;
|
||||
static const AudioOrientationGetter DEFAULT_ORIENTATION_GETTER;
|
||||
|
||||
friend class CheckDevicesThread;
|
||||
friend class LocalInjectorsThread;
|
||||
|
||||
|
@ -307,9 +320,9 @@ private:
|
|||
float gainForSource(float distance, float volume);
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
QTimer _checkInputTimer;
|
||||
QTimer _checkInputTimer{ this };
|
||||
long _inputReadsSinceLastCheck = 0l;
|
||||
bool _isHeadsetPluggedIn;
|
||||
bool _isHeadsetPluggedIn { false };
|
||||
#endif
|
||||
|
||||
class Gate {
|
||||
|
@ -336,68 +349,68 @@ private:
|
|||
bool _isSimulatingJitter{ false };
|
||||
};
|
||||
|
||||
Gate _gate;
|
||||
Gate _gate{ this };
|
||||
|
||||
Mutex _injectorsMutex;
|
||||
QAudioInput* _audioInput;
|
||||
QTimer* _dummyAudioInput;
|
||||
QAudioInput* _audioInput{ nullptr };
|
||||
QTimer* _dummyAudioInput{ nullptr };
|
||||
QAudioFormat _desiredInputFormat;
|
||||
QAudioFormat _inputFormat;
|
||||
QIODevice* _inputDevice;
|
||||
int _numInputCallbackBytes;
|
||||
QAudioOutput* _audioOutput;
|
||||
QIODevice* _inputDevice{ nullptr };
|
||||
int _numInputCallbackBytes{ 0 };
|
||||
QAudioOutput* _audioOutput{ nullptr };
|
||||
std::atomic<bool> _audioOutputInitialized { false };
|
||||
QAudioFormat _desiredOutputFormat;
|
||||
QAudioFormat _outputFormat;
|
||||
int _outputFrameSize;
|
||||
int _numOutputCallbackBytes;
|
||||
QAudioOutput* _loopbackAudioOutput;
|
||||
QIODevice* _loopbackOutputDevice;
|
||||
AudioRingBuffer _inputRingBuffer;
|
||||
LocalInjectorsStream _localInjectorsStream;
|
||||
int _outputFrameSize{ 0 };
|
||||
int _numOutputCallbackBytes{ 0 };
|
||||
QAudioOutput* _loopbackAudioOutput{ nullptr };
|
||||
QIODevice* _loopbackOutputDevice{ nullptr };
|
||||
AudioRingBuffer _inputRingBuffer{ 0 };
|
||||
LocalInjectorsStream _localInjectorsStream{ 0 , 1 };
|
||||
// In order to use _localInjectorsStream as a lock-free pipe,
|
||||
// use it with a single producer/consumer, and track available samples and injectors
|
||||
std::atomic<int> _localSamplesAvailable { 0 };
|
||||
std::atomic<bool> _localInjectorsAvailable { false };
|
||||
MixedProcessedAudioStream _receivedAudioStream;
|
||||
bool _isStereoInput;
|
||||
MixedProcessedAudioStream _receivedAudioStream{ RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES };
|
||||
bool _isStereoInput{ false };
|
||||
std::atomic<bool> _enablePeakValues { false };
|
||||
|
||||
quint64 _outputStarveDetectionStartTimeMsec;
|
||||
int _outputStarveDetectionCount;
|
||||
quint64 _outputStarveDetectionStartTimeMsec{ 0 };
|
||||
int _outputStarveDetectionCount { 0 };
|
||||
|
||||
Setting::Handle<int> _outputBufferSizeFrames;
|
||||
int _sessionOutputBufferSizeFrames;
|
||||
Setting::Handle<bool> _outputStarveDetectionEnabled;
|
||||
Setting::Handle<int> _outputBufferSizeFrames{"audioOutputBufferFrames", DEFAULT_BUFFER_FRAMES};
|
||||
int _sessionOutputBufferSizeFrames{ _outputBufferSizeFrames.get() };
|
||||
Setting::Handle<bool> _outputStarveDetectionEnabled{ "audioOutputStarveDetectionEnabled", DEFAULT_STARVE_DETECTION_ENABLED};
|
||||
|
||||
StDev _stdev;
|
||||
QElapsedTimer _timeSinceLastReceived;
|
||||
float _lastRawInputLoudness; // before mute/gate
|
||||
float _lastSmoothedRawInputLoudness;
|
||||
float _lastInputLoudness; // after mute/gate
|
||||
float _timeSinceLastClip;
|
||||
float _lastRawInputLoudness{ 0.0f }; // before mute/gate
|
||||
float _lastSmoothedRawInputLoudness{ 0.0f };
|
||||
float _lastInputLoudness{ 0.0f }; // after mute/gate
|
||||
float _timeSinceLastClip{ -1.0f };
|
||||
int _totalInputAudioSamples;
|
||||
|
||||
bool _muted;
|
||||
bool _shouldEchoLocally;
|
||||
bool _shouldEchoToServer;
|
||||
bool _isNoiseGateEnabled;
|
||||
bool _muted{ false };
|
||||
bool _shouldEchoLocally{ false };
|
||||
bool _shouldEchoToServer{ false };
|
||||
bool _isNoiseGateEnabled{ true };
|
||||
bool _warnWhenMuted;
|
||||
bool _isAECEnabled;
|
||||
bool _isAECEnabled{ true };
|
||||
|
||||
bool _reverb;
|
||||
bool _reverb{ false };
|
||||
AudioEffectOptions _scriptReverbOptions;
|
||||
AudioEffectOptions _zoneReverbOptions;
|
||||
AudioEffectOptions* _reverbOptions;
|
||||
AudioEffectOptions* _reverbOptions{ &_scriptReverbOptions };
|
||||
AudioReverb _sourceReverb { AudioConstants::SAMPLE_RATE };
|
||||
AudioReverb _listenerReverb { AudioConstants::SAMPLE_RATE };
|
||||
AudioReverb _localReverb { AudioConstants::SAMPLE_RATE };
|
||||
|
||||
// possible streams needed for resample
|
||||
AudioSRC* _inputToNetworkResampler;
|
||||
AudioSRC* _networkToOutputResampler;
|
||||
AudioSRC* _localToOutputResampler;
|
||||
AudioSRC* _loopbackResampler;
|
||||
AudioSRC* _inputToNetworkResampler{ nullptr };
|
||||
AudioSRC* _networkToOutputResampler{ nullptr };
|
||||
AudioSRC* _localToOutputResampler{ nullptr };
|
||||
AudioSRC* _loopbackResampler{ nullptr };
|
||||
|
||||
// for network audio (used by network audio thread)
|
||||
int16_t _networkScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC];
|
||||
|
@ -416,7 +429,7 @@ private:
|
|||
int16_t _localScratchBuffer[AudioConstants::NETWORK_FRAME_SAMPLES_AMBISONIC];
|
||||
float* _localOutputMixBuffer { NULL };
|
||||
Mutex _localAudioMutex;
|
||||
AudioLimiter _audioLimiter;
|
||||
AudioLimiter _audioLimiter{ AudioConstants::SAMPLE_RATE, OUTPUT_CHANNEL_COUNT };
|
||||
|
||||
// Adds Reverb
|
||||
void configureReverb();
|
||||
|
@ -445,17 +458,17 @@ private:
|
|||
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const;
|
||||
int calculateNumberOfFrameSamples(int numBytes) const;
|
||||
|
||||
quint16 _outgoingAvatarAudioSequenceNumber;
|
||||
quint16 _outgoingAvatarAudioSequenceNumber{ 0 };
|
||||
|
||||
AudioOutputIODevice _audioOutputIODevice;
|
||||
AudioOutputIODevice _audioOutputIODevice{ _localInjectorsStream, _receivedAudioStream, this };
|
||||
|
||||
AudioIOStats _stats;
|
||||
AudioIOStats _stats{ &_receivedAudioStream };
|
||||
|
||||
AudioGate* _audioGate { nullptr };
|
||||
bool _audioGateOpen { true };
|
||||
|
||||
AudioPositionGetter _positionGetter;
|
||||
AudioOrientationGetter _orientationGetter;
|
||||
AudioPositionGetter _positionGetter{ DEFAULT_POSITION_GETTER };
|
||||
AudioOrientationGetter _orientationGetter{ DEFAULT_ORIENTATION_GETTER };
|
||||
|
||||
glm::vec3 avatarBoundingBoxCorner;
|
||||
glm::vec3 avatarBoundingBoxScale;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -21,8 +21,10 @@ const uint32_t MAX_RANGE_QUERY_DEPTH = 1;
|
|||
static bool timeElapsed = true;
|
||||
#else
|
||||
const uint32_t MAX_RANGE_QUERY_DEPTH = 10000;
|
||||
#if !defined(USE_GLES)
|
||||
static bool timeElapsed = false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(USE_GLES)
|
||||
static bool hasTimerExtension() {
|
||||
|
|
|
@ -17,34 +17,6 @@
|
|||
|
||||
namespace gpu { namespace gles {
|
||||
|
||||
|
||||
// returns the FOV from the projection matrix
|
||||
static inline vec4 extractFov( const glm::mat4& m) {
|
||||
static const std::array<vec4, 4> CLIPS{ {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ -1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, -1, 0, 1 }
|
||||
} };
|
||||
|
||||
glm::mat4 mt = glm::transpose(m);
|
||||
vec4 v, result;
|
||||
// Left
|
||||
v = mt * CLIPS[0];
|
||||
result.x = -atanf(v.z / v.x);
|
||||
// Right
|
||||
v = mt * CLIPS[1];
|
||||
result.y = atanf(v.z / v.x);
|
||||
// Down
|
||||
v = mt * CLIPS[2];
|
||||
result.z = -atanf(v.z / v.y);
|
||||
// Up
|
||||
v = mt * CLIPS[3];
|
||||
result.w = atanf(v.z / v.y);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
class GLESFramebuffer : public gl::GLFramebuffer {
|
||||
using Parent = gl::GLFramebuffer;
|
||||
static GLuint allocate() {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -214,6 +214,8 @@ bool OffscreenSurface::eventFilter(QObject* originalDestination, QEvent* event)
|
|||
fakeMouseEventType = QEvent::MouseButtonRelease;
|
||||
fakeMouseButtons = Qt::NoButton;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
// Same case as OffscreenUi.cpp::eventFilter: touch events are always being accepted so we now use mouse events and consider one touch, touchPoints()[0].
|
||||
QMouseEvent fakeMouseEvent(fakeMouseEventType, originalEvent->touchPoints()[0].pos(), fakeMouseButton, fakeMouseButtons, Qt::NoModifier);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace shader {
|
|||
const Dialect DEFAULT_DIALECT = Dialect::glsl310es;
|
||||
|
||||
const std::vector<Dialect>& allDialects() {
|
||||
static const std::vector<Dialect> ALL_DIALECTS{ { Dialect::glsl310es } };
|
||||
static const std::vector<Dialect> ALL_DIALECTS{ Dialect::glsl310es };
|
||||
return ALL_DIALECTS;
|
||||
}
|
||||
|
||||
|
|
27
libraries/shared/src/CrashAnnotations.cpp
Normal file
27
libraries/shared/src/CrashAnnotations.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// CrashAnnotations.cpp
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Clement Brisset on 9/26/19.
|
||||
// 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 "SharedUtil.h"
|
||||
|
||||
// Global variables specifically tuned to work with ptrace module for crash collection
|
||||
// Do not move/rename unless you update the ptrace module with it.
|
||||
bool crash_annotation_isShuttingDown = false;
|
||||
|
||||
namespace crash {
|
||||
namespace annotations {
|
||||
|
||||
void setShutdownState(bool isShuttingDown) {
|
||||
crash_annotation_isShuttingDown = isShuttingDown;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
};
|
23
libraries/shared/src/CrashAnnotations.h
Normal file
23
libraries/shared/src/CrashAnnotations.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// CrashAnnotations.h
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Clement Brisset on 9/26/19.
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef hifi_CrashAnnotations_h
|
||||
#define hifi_CrashAnnotations_h
|
||||
|
||||
namespace crash {
|
||||
namespace annotations {
|
||||
|
||||
void setShutdownState(bool isShuttingDown);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif // hifi_CrashAnnotations_h
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
@ -364,4 +366,30 @@ inline int fastLrintf(float x) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// returns the FOV from the projection matrix
|
||||
inline glm::vec4 extractFov( const glm::mat4& m) {
|
||||
static const std::array<glm::vec4, 4> CLIPS{ {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ -1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, -1, 0, 1 }
|
||||
} };
|
||||
|
||||
glm::mat4 mt = glm::transpose(m);
|
||||
glm::vec4 v, result;
|
||||
// Left
|
||||
v = mt * CLIPS[0];
|
||||
result.x = -atanf(v.z / v.x);
|
||||
// Right
|
||||
v = mt * CLIPS[1];
|
||||
result.y = atanf(v.z / v.x);
|
||||
// Down
|
||||
v = mt * CLIPS[2];
|
||||
result.z = -atanf(v.z / v.y);
|
||||
// Up
|
||||
v = mt * CLIPS[3];
|
||||
result.w = atanf(v.z / v.y);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // hifi_GLMHelpers_h
|
||||
|
|
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);
|
||||
|
|
222
tools/ci-scripts/notarize
Executable file
222
tools/ci-scripts/notarize
Executable file
|
@ -0,0 +1,222 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Sign, Notarize, and Staple a notarization ticket to the app.
|
||||
|
||||
function usage {
|
||||
echo "usage: $0 datt bundle_path [entitlements]"
|
||||
exit -1
|
||||
}
|
||||
|
||||
apple_id=""
|
||||
developer_id_key_label="Mac Developer ID Application: High Fidelity Inc"
|
||||
k_password_label="com.highfidelity.mac-signing-appleid"
|
||||
k_password_service="AC_PASSWORD"
|
||||
|
||||
# Check for supported Mac OS Version (10.14 or greater)
|
||||
if [ ! -x /usr/bin/sw_vers ]; then
|
||||
echo "Can't find sw_vers, is this Mac OS?"
|
||||
exit -1
|
||||
fi
|
||||
set +e
|
||||
/usr/bin/sw_vers -productVersion | \
|
||||
awk -F'.' '{ if ($1 == 10 && $2 >= 14) { exit 0 } else { exit 1 } }'
|
||||
is_supported=$?
|
||||
set -e
|
||||
if [[ $is_supported -eq 1 ]]; then
|
||||
echo "Must use Mac OS 10.14 or greater"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Check for Xcode
|
||||
if [ ! -x /usr/bin/xcode-select ]; then
|
||||
echo "Xcode is not installed"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
function set_apple_id {
|
||||
if [[ "$apple_id" != "" ]]; then return; fi # already set
|
||||
|
||||
apple_id=$(security find-generic-password \
|
||||
-l $k_password_label -s $k_password_service | \
|
||||
grep acct | awk -F'=' '{ print $2 }' | tr -d '"')
|
||||
if [ "$apple_id" == "" ]; then
|
||||
echo "couldn't find Apple ID in keychain"
|
||||
exit -1
|
||||
fi
|
||||
}
|
||||
|
||||
function ensure_developer_id_key_is_present {
|
||||
set +e
|
||||
security find-key -l "$developer_id_key_label" > /dev/null 2>&1
|
||||
success=$?
|
||||
set -e
|
||||
if [[ $success == 1 ]]; then
|
||||
echo "The Developer ID Key is not in your Keychain: $developer_id_key_label"
|
||||
exit -1
|
||||
fi
|
||||
}
|
||||
|
||||
function sign {
|
||||
bundle_path="$1"
|
||||
entitlements="$2"
|
||||
|
||||
ensure_developer_id_key_is_present
|
||||
if [ "$entitlements" != "" ]; then
|
||||
codesign --force \
|
||||
--deep \
|
||||
--sign "Developer ID Application: High Fidelity Inc" \
|
||||
--timestamp \
|
||||
--options runtime \
|
||||
--entitlements "$entitlements" \
|
||||
"$bundle_path"
|
||||
else
|
||||
codesign --force \
|
||||
--deep \
|
||||
--sign "Developer ID Application: High Fidelity Inc" \
|
||||
--timestamp \
|
||||
--options runtime \
|
||||
"$bundle_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# The `notarize` function sets `result_uuid` on return.
|
||||
result_uuid=""
|
||||
|
||||
function notarize {
|
||||
local bundle_path=$1
|
||||
|
||||
local bundle_id=$(/usr/libexec/PlistBuddy -c Print:CFBundleIdentifier \
|
||||
"$bundle_path"/Contents/Info.plist)
|
||||
if [ "$bundle_id" == "" ]; then
|
||||
echo "couldn't find bundle id in bundle's Info.plist: $bundle_path"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
set_apple_id
|
||||
|
||||
if [ -e "$bundle_path.zip" ]; then
|
||||
echo "zip already exists, moving it out of the way"
|
||||
mv "$bundle_path.zip"{,.$(uuidgen)}
|
||||
fi
|
||||
|
||||
local local_bundle_path=$(basename "$bundle_path")
|
||||
(cd "$bundle_path/.."; \
|
||||
zip -r --symlinks "$local_bundle_path.zip" "$local_bundle_path" \
|
||||
>/dev/null 2>&1)
|
||||
|
||||
# `result_uuid` is intentionally global
|
||||
result_uuid=$(xcrun altool --notarize-app \
|
||||
--primary-bundle-id $bundle_id \
|
||||
--username $apple_id --password "@keychain:$k_password_service" \
|
||||
--file "$bundle_path.zip" 2>&1 | tee /dev/tty | \
|
||||
awk -F'=' '{ if (/^RequestUUID/) print $2 }' | sed 's/^ //')
|
||||
}
|
||||
|
||||
function is_notarization_complete {
|
||||
set_apple_id
|
||||
|
||||
set +e
|
||||
local status_code=$(xcrun altool --notarization-info $result_uuid \
|
||||
--username $apple_id --password "@keychain:$k_password_service" 2>&1 | \
|
||||
awk '{ if (/Status Code/) print $3 }')
|
||||
set -e
|
||||
# Status Code is only set when a job is complete.
|
||||
if [[ "$status_code" -ne "" ]]; then
|
||||
return 1
|
||||
fi
|
||||
return $status_code
|
||||
}
|
||||
|
||||
command=$1
|
||||
|
||||
case $command in
|
||||
# Utility to add your Apple ID to the keychain
|
||||
add_password)
|
||||
echo -n "Apple ID: "
|
||||
read appleid_name
|
||||
if [ "$appleid_name" == "" ]; then
|
||||
echo "Apple ID was empty!"
|
||||
exit -1
|
||||
fi
|
||||
security add-generic-password \
|
||||
-a "$appleid_name" \
|
||||
-s "$k_password_service" \
|
||||
-l "$k_password_label" \
|
||||
-j "Apple ID used for High Fidelity's code signing" \
|
||||
-w
|
||||
;;
|
||||
|
||||
# Sign a bundle with the Developer ID Application cert
|
||||
sign)
|
||||
bundle_path=$2
|
||||
if [ "$bundle_path" == "" ]; then
|
||||
echo "usage: $0 $command bundle_path"
|
||||
exit -1
|
||||
fi
|
||||
if [ ! -d "$bundle_path" ]; then
|
||||
echo "bundle_path doesn't exist"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
sign "$bundle_path" "$3"
|
||||
;;
|
||||
|
||||
# Submit a bundle to Apple for notarization
|
||||
notarize)
|
||||
bundle_path=$2
|
||||
if [ "$bundle_path" == "" ]; then
|
||||
echo "usage: $0 $command bundle_path"
|
||||
exit -1
|
||||
fi
|
||||
if [ ! -d "$bundle_path" ]; then
|
||||
echo "bundle_path doesn't exist"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
notarize "$bundle_path"
|
||||
;;
|
||||
|
||||
# Check the notarization logs
|
||||
logs)
|
||||
result_uuid=$2
|
||||
if [ "$result_uuid" == "" ]; then
|
||||
echo "usage: $0 $command result_uuid"
|
||||
exit -1
|
||||
fi
|
||||
set_apple_id
|
||||
|
||||
xcrun altool --notarization-info $result_uuid \
|
||||
--username $apple_id --password "@keychain:$k_password_service"
|
||||
;;
|
||||
|
||||
# Do all the things.
|
||||
datt)
|
||||
bundle_path=$2
|
||||
if [ "$bundle_path" == "" ]; then
|
||||
echo "usage: $0 bundle_path [entitlements]"
|
||||
exit -1
|
||||
fi
|
||||
if [ ! -d "$bundle_path" ]; then
|
||||
echo "bundle_path doesn't exist"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
sign "$bundle_path" "$3"
|
||||
notarize "$bundle_path"
|
||||
|
||||
# TODO: is_notarization_complete needs to recognize notarization
|
||||
# while :; do
|
||||
# echo "sleeping..."
|
||||
# sleep 27
|
||||
# is_notarization_complete
|
||||
# [[ $? == 1 ]] && break
|
||||
# done
|
||||
# xcrun stapler staple "$bundle_path"
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
|
||||
esac
|
|
@ -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