mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 12:12:32 +02:00
Merge remote-tracking branch 'upstream/master' into android
This commit is contained in:
commit
bdfa1273ba
63 changed files with 919 additions and 820 deletions
|
@ -343,7 +343,6 @@ void Agent::scriptRequestFinished() {
|
||||||
|
|
||||||
void Agent::executeScript() {
|
void Agent::executeScript() {
|
||||||
_scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload);
|
_scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload);
|
||||||
_scriptEngine->setParent(this); // be the parent of the script engine so it gets moved when we do
|
|
||||||
|
|
||||||
DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(_scriptEngine);
|
DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(_scriptEngine);
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ Column {
|
||||||
'include_actions=' + actions,
|
'include_actions=' + actions,
|
||||||
'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'),
|
'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'),
|
||||||
'require_online=true',
|
'require_online=true',
|
||||||
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
|
'protocol=' + encodeURIComponent(Window.protocolSignature()),
|
||||||
'page=' + pageNumber
|
'page=' + pageNumber
|
||||||
];
|
];
|
||||||
var url = metaverseBase + 'user_stories?' + options.join('&');
|
var url = metaverseBase + 'user_stories?' + options.join('&');
|
||||||
|
|
|
@ -392,7 +392,6 @@ Item {
|
||||||
width: 118;
|
width: 118;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
wrapMode: Text.WordWrap;
|
wrapMode: Text.WordWrap;
|
||||||
font.bold: true;
|
|
||||||
// Alignment
|
// Alignment
|
||||||
horizontalAlignment: Text.AlignRight;
|
horizontalAlignment: Text.AlignRight;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import "."
|
||||||
Overlay {
|
Overlay {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
Image {
|
AnimatedImage {
|
||||||
id: image
|
id: image
|
||||||
property bool scaleFix: true
|
property bool scaleFix: true
|
||||||
property real xStart: 0
|
property real xStart: 0
|
||||||
|
|
|
@ -610,8 +610,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
reportAndQuit("--protocolVersion", [&](FILE* fp) {
|
reportAndQuit("--protocolVersion", [&](FILE* fp) {
|
||||||
DependencyManager::set<AddressManager>();
|
auto version = protocolVersionsSignatureBase64();
|
||||||
auto version = DependencyManager::get<AddressManager>()->protocolVersion();
|
|
||||||
fputs(version.toLatin1().data(), fp);
|
fputs(version.toLatin1().data(), fp);
|
||||||
});
|
});
|
||||||
reportAndQuit("--version", [&](FILE* fp) {
|
reportAndQuit("--version", [&](FILE* fp) {
|
||||||
|
@ -2148,6 +2147,11 @@ void Application::cleanupBeforeQuit() {
|
||||||
DependencyManager::destroy<AudioInjectorManager>();
|
DependencyManager::destroy<AudioInjectorManager>();
|
||||||
DependencyManager::destroy<AudioScriptingInterface>();
|
DependencyManager::destroy<AudioScriptingInterface>();
|
||||||
|
|
||||||
|
// The PointerManager must be destroyed before the PickManager because when a Pointer is deleted,
|
||||||
|
// it accesses the PickManager to delete its associated Pick
|
||||||
|
DependencyManager::destroy<PointerManager>();
|
||||||
|
DependencyManager::destroy<PickManager>();
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Application::cleanupBeforeQuit() complete";
|
qCDebug(interfaceapp) << "Application::cleanupBeforeQuit() complete";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4420,8 +4424,9 @@ void Application::updateLOD(float deltaTime) const {
|
||||||
float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
|
float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
|
||||||
float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
|
float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
|
||||||
float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
|
float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
|
||||||
float maxRenderTime = glm::max(gpuTime, glm::max(presentTime, engineRunTime));
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
DependencyManager::get<LODManager>()->autoAdjustLOD(maxRenderTime, deltaTime);
|
lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime);
|
||||||
|
lodManager->autoAdjustLOD(deltaTime);
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<LODManager>()->resetLODAdjust();
|
DependencyManager::get<LODManager>()->resetLODAdjust();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,43 +26,50 @@ Setting::Handle<float> hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DO
|
||||||
LODManager::LODManager() {
|
LODManager::LODManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
float LODManager::getLODDecreaseFPS() {
|
float LODManager::getLODDecreaseFPS() const {
|
||||||
if (qApp->isHMDMode()) {
|
if (qApp->isHMDMode()) {
|
||||||
return getHMDLODDecreaseFPS();
|
return getHMDLODDecreaseFPS();
|
||||||
}
|
}
|
||||||
return getDesktopLODDecreaseFPS();
|
return getDesktopLODDecreaseFPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
float LODManager::getLODIncreaseFPS() {
|
float LODManager::getLODIncreaseFPS() const {
|
||||||
if (qApp->isHMDMode()) {
|
if (qApp->isHMDMode()) {
|
||||||
return getHMDLODIncreaseFPS();
|
return getHMDLODIncreaseFPS();
|
||||||
}
|
}
|
||||||
return getDesktopLODIncreaseFPS();
|
return getDesktopLODIncreaseFPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use a "time-weighted running average" of the renderTime and compare it against min/max thresholds
|
// We use a "time-weighted running average" of the maxRenderTime and compare it against min/max thresholds
|
||||||
// to determine if we should adjust the level of detail (LOD).
|
// to determine if we should adjust the level of detail (LOD).
|
||||||
//
|
//
|
||||||
// A time-weighted running average has a timescale which determines how fast the average tracks the measured
|
// A time-weighted running average has a timescale which determines how fast the average tracks the measured
|
||||||
// value in real-time. Given a step-function in the mesured value, and assuming measurements happen
|
// value in real-time. Given a step-function in the mesured value, and assuming measurements happen
|
||||||
// faster than the runningAverage is computed, the error between the value and its runningAverage will be
|
// faster than the runningAverage is computed, the error between the value and its runningAverage will be
|
||||||
// reduced by 1/e every timescale of real-time that passes.
|
// reduced by 1/e every timescale of real-time that passes.
|
||||||
const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.1f; // sec
|
const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.08f; // sec
|
||||||
//
|
//
|
||||||
// Assuming the measured value is affected by logic invoked by the runningAverage bumping up against its
|
// Assuming the measured value is affected by logic invoked by the runningAverage bumping up against its
|
||||||
// thresholds, we expect the adjustment to introduce a step-function. We want the runningAverage to settle
|
// thresholds, we expect the adjustment to introduce a step-function. We want the runningAverage to settle
|
||||||
// to the new value BEFORE we test it aginst its thresholds again. Hence we test on a period that is a few
|
// to the new value BEFORE we test it aginst its thresholds again. Hence we test on a period that is a few
|
||||||
// multiples of the running average timescale:
|
// multiples of the running average timescale:
|
||||||
const uint64_t LOD_AUTO_ADJUST_PERIOD = 5 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec
|
const uint64_t LOD_AUTO_ADJUST_PERIOD = 4 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec
|
||||||
|
|
||||||
const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f;
|
const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f;
|
||||||
const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f;
|
const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f;
|
||||||
|
|
||||||
void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
void LODManager::setRenderTimes(float presentTime, float engineRunTime, float gpuTime) {
|
||||||
// compute time-weighted running average renderTime
|
_presentTime = presentTime;
|
||||||
|
_engineRunTime = engineRunTime;
|
||||||
|
_gpuTime = gpuTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
|
float maxRenderTime = glm::max(glm::max(_presentTime, _engineRunTime), _gpuTime);
|
||||||
|
// compute time-weighted running average maxRenderTime
|
||||||
// Note: we MUST clamp the blend to 1.0 for stability
|
// Note: we MUST clamp the blend to 1.0 for stability
|
||||||
float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
|
float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
|
||||||
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * renderTime; // msec
|
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec
|
||||||
if (!_automaticLODAdjust) {
|
if (!_automaticLODAdjust) {
|
||||||
// early exit
|
// early exit
|
||||||
return;
|
return;
|
||||||
|
@ -84,6 +91,10 @@ void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
||||||
<< "targetFPS =" << getLODDecreaseFPS()
|
<< "targetFPS =" << getLODDecreaseFPS()
|
||||||
<< "octreeSizeScale =" << _octreeSizeScale;
|
<< "octreeSizeScale =" << _octreeSizeScale;
|
||||||
emit LODDecreased();
|
emit LODDecreased();
|
||||||
|
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
|
||||||
|
// to provide an FPS just above the decrease threshold. It will drift close to its
|
||||||
|
// true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
|
||||||
|
_avgRenderTime = (float)MSECS_PER_SECOND / (getLODDecreaseFPS() + 1.0f);
|
||||||
}
|
}
|
||||||
_decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
|
_decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
|
||||||
}
|
}
|
||||||
|
@ -105,6 +116,10 @@ void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
||||||
<< "targetFPS =" << getLODDecreaseFPS()
|
<< "targetFPS =" << getLODDecreaseFPS()
|
||||||
<< "octreeSizeScale =" << _octreeSizeScale;
|
<< "octreeSizeScale =" << _octreeSizeScale;
|
||||||
emit LODIncreased();
|
emit LODIncreased();
|
||||||
|
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
|
||||||
|
// to provide an FPS just below the increase threshold. It will drift close to its
|
||||||
|
// true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
|
||||||
|
_avgRenderTime = (float)MSECS_PER_SECOND / (getLODIncreaseFPS() - 1.0f);
|
||||||
}
|
}
|
||||||
_increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
|
_increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
|
||||||
}
|
}
|
||||||
|
@ -119,11 +134,6 @@ void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
||||||
if (lodToolsDialog) {
|
if (lodToolsDialog) {
|
||||||
lodToolsDialog->reloadSliders();
|
lodToolsDialog->reloadSliders();
|
||||||
}
|
}
|
||||||
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
|
|
||||||
// to be at middle of target zone. It will drift close to its true value within
|
|
||||||
// about three few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
|
|
||||||
float expectedFPS = 0.5f * (getLODIncreaseFPS() + getLODDecreaseFPS());
|
|
||||||
_avgRenderTime = MSECS_PER_SECOND / expectedFPS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +141,18 @@ void LODManager::resetLODAdjust() {
|
||||||
_decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD;
|
_decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float LODManager::getLODLevel() const {
|
||||||
|
// simpleLOD is a linearized and normalized number that represents how much LOD is being applied.
|
||||||
|
// It ranges from:
|
||||||
|
// 1.0 = normal (max) level of detail
|
||||||
|
// 0.0 = min level of detail
|
||||||
|
// In other words: as LOD "drops" the value of simpleLOD will also "drop", and it cannot go lower than 0.0.
|
||||||
|
const float LOG_MIN_LOD_RATIO = logf(ADJUST_LOD_MIN_SIZE_SCALE / ADJUST_LOD_MAX_SIZE_SCALE);
|
||||||
|
float power = logf(_octreeSizeScale / ADJUST_LOD_MAX_SIZE_SCALE);
|
||||||
|
float simpleLOD = (LOG_MIN_LOD_RATIO - power) / LOG_MIN_LOD_RATIO;
|
||||||
|
return simpleLOD;
|
||||||
|
}
|
||||||
|
|
||||||
const float MIN_DECREASE_FPS = 0.5f;
|
const float MIN_DECREASE_FPS = 0.5f;
|
||||||
|
|
||||||
void LODManager::setDesktopLODDecreaseFPS(float fps) {
|
void LODManager::setDesktopLODDecreaseFPS(float fps) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ class AABox;
|
||||||
class LODManager : public QObject, public Dependency {
|
class LODManager : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE void setAutomaticLODAdjust(bool value) { _automaticLODAdjust = value; }
|
Q_INVOKABLE void setAutomaticLODAdjust(bool value) { _automaticLODAdjust = value; }
|
||||||
Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; }
|
Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; }
|
||||||
|
@ -49,34 +49,56 @@ public:
|
||||||
Q_INVOKABLE void setHMDLODDecreaseFPS(float value);
|
Q_INVOKABLE void setHMDLODDecreaseFPS(float value);
|
||||||
Q_INVOKABLE float getHMDLODDecreaseFPS() const;
|
Q_INVOKABLE float getHMDLODDecreaseFPS() const;
|
||||||
Q_INVOKABLE float getHMDLODIncreaseFPS() const;
|
Q_INVOKABLE float getHMDLODIncreaseFPS() const;
|
||||||
|
|
||||||
// User Tweakable LOD Items
|
// User Tweakable LOD Items
|
||||||
Q_INVOKABLE QString getLODFeedbackText();
|
Q_INVOKABLE QString getLODFeedbackText();
|
||||||
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
||||||
Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; }
|
Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||||
|
|
||||||
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||||
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||||
|
|
||||||
Q_INVOKABLE float getLODDecreaseFPS();
|
Q_INVOKABLE float getLODDecreaseFPS() const;
|
||||||
Q_INVOKABLE float getLODIncreaseFPS();
|
Q_INVOKABLE float getLODIncreaseFPS() const;
|
||||||
|
|
||||||
|
Q_PROPERTY(float presentTime READ getPresentTime)
|
||||||
|
Q_PROPERTY(float engineRunTime READ getEngineRunTime)
|
||||||
|
Q_PROPERTY(float gpuTime READ getGPUTime)
|
||||||
|
Q_PROPERTY(float avgRenderTime READ getAverageRenderTime)
|
||||||
|
Q_PROPERTY(float fps READ getMaxTheoreticalFPS)
|
||||||
|
Q_PROPERTY(float lodLevel READ getLODLevel)
|
||||||
|
|
||||||
|
Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS)
|
||||||
|
Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS)
|
||||||
|
|
||||||
|
float getPresentTime() const { return _presentTime; }
|
||||||
|
float getEngineRunTime() const { return _engineRunTime; }
|
||||||
|
float getGPUTime() const { return _gpuTime; }
|
||||||
|
|
||||||
static bool shouldRender(const RenderArgs* args, const AABox& bounds);
|
static bool shouldRender(const RenderArgs* args, const AABox& bounds);
|
||||||
void autoAdjustLOD(float renderTime, float realTimeDelta);
|
void setRenderTimes(float presentTime, float engineRunTime, float gpuTime);
|
||||||
|
void autoAdjustLOD(float realTimeDelta);
|
||||||
|
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
void resetLODAdjust();
|
void resetLODAdjust();
|
||||||
|
|
||||||
|
float getAverageRenderTime() const { return _avgRenderTime; };
|
||||||
|
float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; };
|
||||||
|
float getLODLevel() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void LODIncreased();
|
void LODIncreased();
|
||||||
void LODDecreased();
|
void LODDecreased();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LODManager();
|
LODManager();
|
||||||
|
|
||||||
bool _automaticLODAdjust = true;
|
bool _automaticLODAdjust = true;
|
||||||
float _avgRenderTime { 0.0f };
|
float _presentTime { 0.0f }; // msec
|
||||||
|
float _engineRunTime { 0.0f }; // msec
|
||||||
|
float _gpuTime { 0.0f }; // msec
|
||||||
|
float _avgRenderTime { 0.0f }; // msec
|
||||||
float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME };
|
float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME };
|
||||||
float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME };
|
float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME };
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "Ledger.h"
|
#include "Ledger.h"
|
||||||
#include "CommerceLogging.h"
|
#include "CommerceLogging.h"
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
|
#include <AddressManager.h>
|
||||||
|
|
||||||
// inventory answers {status: 'success', data: {assets: [{id: "guid", title: "name", preview: "url"}....]}}
|
// inventory answers {status: 'success', data: {assets: [{id: "guid", title: "name", preview: "url"}....]}}
|
||||||
// balance answers {status: 'success', data: {balance: integer}}
|
// balance answers {status: 'success', data: {balance: integer}}
|
||||||
|
@ -122,24 +123,33 @@ QString hfcString(const QJsonValue& sentValue, const QJsonValue& receivedValue)
|
||||||
int sent = sentValue.toInt();
|
int sent = sentValue.toInt();
|
||||||
int received = receivedValue.toInt();
|
int received = receivedValue.toInt();
|
||||||
if (sent <= 0 && received <= 0) {
|
if (sent <= 0 && received <= 0) {
|
||||||
return QString("-");
|
return QString("0 HFC");
|
||||||
}
|
}
|
||||||
QString result;
|
QString result;
|
||||||
if (sent > 0) {
|
if (sent > 0) {
|
||||||
result += QString("<font color='#B70A37'>-%1 HFC</font>").arg(sent);
|
result += QString("<font color='#B70A37'><b>-%1 HFC</b></font>").arg(sent);
|
||||||
if (received > 0) {
|
if (received > 0) {
|
||||||
result += QString("<br>");
|
result += QString("<br>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (received > 0) {
|
if (received > 0) {
|
||||||
result += QString("<font color='#3AA38F'>%1 HFC</font>").arg(received);
|
result += QString("<font color='#3AA38F'><b>%1 HFC</b></font>").arg(received);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
static const QString USER_PAGE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/users/";
|
static const QString USER_PAGE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/users/";
|
||||||
QString userLink(const QString& username) {
|
static const QString PLACE_PAGE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/places/";
|
||||||
|
static const QStringList KNOWN_USERS(QStringList() << "highfidelity" << "marketplace");
|
||||||
|
QString userLink(const QString& username, const QString& placename) {
|
||||||
if (username.isEmpty()) {
|
if (username.isEmpty()) {
|
||||||
return QString("someone");
|
if (placename.isEmpty()) {
|
||||||
|
return QString("someone");
|
||||||
|
} else {
|
||||||
|
return QString("someone <a href=\"%1%2\">nearby</a>").arg(PLACE_PAGE_BASE_URL, placename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (KNOWN_USERS.contains(username)) {
|
||||||
|
return username;
|
||||||
}
|
}
|
||||||
return QString("<a href=\"%1%2\">%2</a>").arg(USER_PAGE_BASE_URL, username);
|
return QString("<a href=\"%1%2\">%2</a>").arg(USER_PAGE_BASE_URL, username);
|
||||||
}
|
}
|
||||||
|
@ -153,13 +163,13 @@ QString transactionString(const QJsonObject& valueObject) {
|
||||||
QDateTime createdAt(QDateTime::fromSecsSinceEpoch(dateInteger, Qt::UTC));
|
QDateTime createdAt(QDateTime::fromSecsSinceEpoch(dateInteger, Qt::UTC));
|
||||||
QString result;
|
QString result;
|
||||||
|
|
||||||
if (sentCerts <= 0 && receivedCerts <= 0) {
|
if (sentCerts <= 0 && receivedCerts <= 0 && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) {
|
||||||
// this is an hfc transfer.
|
// this is an hfc transfer.
|
||||||
if (sent > 0) {
|
if (sent > 0) {
|
||||||
QString recipient = userLink(valueObject["recipient_name"].toString());
|
QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString());
|
||||||
result += QString("Money sent to %1").arg(recipient);
|
result += QString("Money sent to %1").arg(recipient);
|
||||||
} else {
|
} else {
|
||||||
QString sender = userLink(valueObject["sender_name"].toString());
|
QString sender = userLink(valueObject["sender_name"].toString(), valueObject["place_name"].toString());
|
||||||
result += QString("Money from %1").arg(sender);
|
result += QString("Money from %1").arg(sender);
|
||||||
}
|
}
|
||||||
if (!message.isEmpty()) {
|
if (!message.isEmpty()) {
|
||||||
|
@ -168,8 +178,8 @@ QString transactionString(const QJsonObject& valueObject) {
|
||||||
} else {
|
} else {
|
||||||
result += valueObject["message"].toString();
|
result += valueObject["message"].toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// no matter what we append a smaller date to the bottom of this...
|
// no matter what we append a smaller date to the bottom of this...
|
||||||
|
|
||||||
result += QString("<br><font size='-2' color='#1080B8'>%1").arg(createdAt.toLocalTime().toString(Qt::DefaultLocaleShortDate));
|
result += QString("<br><font size='-2' color='#1080B8'>%1").arg(createdAt.toLocalTime().toString(Qt::DefaultLocaleShortDate));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -310,6 +320,7 @@ void Ledger::transferHfcToNode(const QString& hfc_key, const QString& nodeID, co
|
||||||
transaction["node_id"] = nodeID;
|
transaction["node_id"] = nodeID;
|
||||||
transaction["quantity"] = amount;
|
transaction["quantity"] = amount;
|
||||||
transaction["message"] = optionalMessage;
|
transaction["message"] = optionalMessage;
|
||||||
|
transaction["place_name"] = DependencyManager::get<AddressManager>()->getPlaceName();
|
||||||
QJsonDocument transactionDoc{ transaction };
|
QJsonDocument transactionDoc{ transaction };
|
||||||
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
||||||
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_node", "transferHfcToNodeSuccess", "transferHfcToNodeFailure");
|
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_node", "transferHfcToNodeSuccess", "transferHfcToNodeFailure");
|
||||||
|
|
|
@ -390,6 +390,10 @@ QString WindowScriptingInterface::checkVersion() {
|
||||||
return QCoreApplication::applicationVersion();
|
return QCoreApplication::applicationVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString WindowScriptingInterface::protocolSignature() {
|
||||||
|
return protocolVersionsSignatureBase64();
|
||||||
|
}
|
||||||
|
|
||||||
int WindowScriptingInterface::getInnerWidth() {
|
int WindowScriptingInterface::getInnerWidth() {
|
||||||
return qApp->getDeviceSize().x;
|
return qApp->getDeviceSize().x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,6 +305,13 @@ public slots:
|
||||||
*/
|
*/
|
||||||
QString checkVersion();
|
QString checkVersion();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Get the signature for Interface's protocol version.
|
||||||
|
* @function Window.protocolSignature
|
||||||
|
* @returns {string} A string uniquely identifying the version of the metaverse protocol that Interface is using.
|
||||||
|
*/
|
||||||
|
QString protocolSignature();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Copies text to the operating system's clipboard.
|
* Copies text to the operating system's clipboard.
|
||||||
* @function Window.copyToClipboard
|
* @function Window.copyToClipboard
|
||||||
|
|
|
@ -386,8 +386,6 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -154,8 +154,6 @@ void Cube3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -132,8 +132,6 @@ void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -208,8 +208,6 @@ void Image3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -275,8 +275,6 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -306,8 +306,6 @@ vectorType ModelOverlay::mapJoints(mapFunction<itemType> function) const {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -31,8 +31,7 @@ Overlay::Overlay() :
|
||||||
_alphaPulse(0.0f),
|
_alphaPulse(0.0f),
|
||||||
_colorPulse(0.0f),
|
_colorPulse(0.0f),
|
||||||
_color(DEFAULT_OVERLAY_COLOR),
|
_color(DEFAULT_OVERLAY_COLOR),
|
||||||
_visible(true),
|
_visible(true)
|
||||||
_anchor(NO_ANCHOR)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +48,7 @@ Overlay::Overlay(const Overlay* overlay) :
|
||||||
_alphaPulse(overlay->_alphaPulse),
|
_alphaPulse(overlay->_alphaPulse),
|
||||||
_colorPulse(overlay->_colorPulse),
|
_colorPulse(overlay->_colorPulse),
|
||||||
_color(overlay->_color),
|
_color(overlay->_color),
|
||||||
_visible(overlay->_visible),
|
_visible(overlay->_visible)
|
||||||
_anchor(overlay->_anchor)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,13 +90,6 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
||||||
bool visible = properties["visible"].toBool();
|
bool visible = properties["visible"].toBool();
|
||||||
setVisible(visible);
|
setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties["anchor"].isValid()) {
|
|
||||||
QString property = properties["anchor"].toString();
|
|
||||||
if (property == "MyAvatar") {
|
|
||||||
setAnchor(MY_AVATAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSDoc for copying to @typedefs of overlay types that inherit Overlay.
|
// JSDoc for copying to @typedefs of overlay types that inherit Overlay.
|
||||||
|
@ -119,8 +110,6 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*/
|
*/
|
||||||
QVariant Overlay::getProperty(const QString& property) {
|
QVariant Overlay::getProperty(const QString& property) {
|
||||||
if (property == "type") {
|
if (property == "type") {
|
||||||
|
@ -150,9 +139,6 @@ QVariant Overlay::getProperty(const QString& property) {
|
||||||
if (property == "visible") {
|
if (property == "visible") {
|
||||||
return _visible;
|
return _visible;
|
||||||
}
|
}
|
||||||
if (property == "anchor") {
|
|
||||||
return _anchor == MY_AVATAR ? "MyAvatar" : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,6 @@ class Overlay : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Anchor {
|
|
||||||
NO_ANCHOR,
|
|
||||||
MY_AVATAR
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::shared_ptr<Overlay> Pointer;
|
typedef std::shared_ptr<Overlay> Pointer;
|
||||||
typedef render::Payload<Overlay> Payload;
|
typedef render::Payload<Overlay> Payload;
|
||||||
typedef std::shared_ptr<render::Item::PayloadInterface> PayloadPointer;
|
typedef std::shared_ptr<render::Item::PayloadInterface> PayloadPointer;
|
||||||
|
@ -63,7 +58,6 @@ public:
|
||||||
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||||
xColor getColor();
|
xColor getColor();
|
||||||
float getAlpha();
|
float getAlpha();
|
||||||
Anchor getAnchor() const { return _anchor; }
|
|
||||||
|
|
||||||
float getPulseMax() const { return _pulseMax; }
|
float getPulseMax() const { return _pulseMax; }
|
||||||
float getPulseMin() const { return _pulseMin; }
|
float getPulseMin() const { return _pulseMin; }
|
||||||
|
@ -78,7 +72,6 @@ public:
|
||||||
void setDrawHUDLayer(bool drawHUDLayer);
|
void setDrawHUDLayer(bool drawHUDLayer);
|
||||||
void setColor(const xColor& color) { _color = color; }
|
void setColor(const xColor& color) { _color = color; }
|
||||||
void setAlpha(float alpha) { _alpha = alpha; }
|
void setAlpha(float alpha) { _alpha = alpha; }
|
||||||
void setAnchor(Anchor anchor) { _anchor = anchor; }
|
|
||||||
|
|
||||||
void setPulseMax(float value) { _pulseMax = value; }
|
void setPulseMax(float value) { _pulseMax = value; }
|
||||||
void setPulseMin(float value) { _pulseMin = value; }
|
void setPulseMin(float value) { _pulseMin = value; }
|
||||||
|
@ -118,7 +111,6 @@ protected:
|
||||||
|
|
||||||
xColor _color;
|
xColor _color;
|
||||||
bool _visible; // should the overlay be drawn at all
|
bool _visible; // should the overlay be drawn at all
|
||||||
Anchor _anchor;
|
|
||||||
|
|
||||||
unsigned int _stackOrder { 0 };
|
unsigned int _stackOrder { 0 };
|
||||||
|
|
||||||
|
|
|
@ -1,190 +0,0 @@
|
||||||
//
|
|
||||||
// OverlayPanel.cpp
|
|
||||||
// interface/src/ui/overlays
|
|
||||||
//
|
|
||||||
// Created by Zander Otavka on 7/2/15.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "OverlayPanel.h"
|
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
|
|
||||||
#include <QVariant>
|
|
||||||
#include <RegisteredMetaTypes.h>
|
|
||||||
#include <DependencyManager.h>
|
|
||||||
#include <EntityScriptingInterface.h>
|
|
||||||
|
|
||||||
#include "avatar/AvatarManager.h"
|
|
||||||
#include "avatar/MyAvatar.h"
|
|
||||||
#include "Base3DOverlay.h"
|
|
||||||
|
|
||||||
PropertyBinding::PropertyBinding(QString avatar, QUuid entity) :
|
|
||||||
avatar(avatar),
|
|
||||||
entity(entity)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant propertyBindingToVariant(const PropertyBinding& value) {
|
|
||||||
QVariantMap obj;
|
|
||||||
|
|
||||||
if (value.avatar == "MyAvatar") {
|
|
||||||
obj["avatar"] = "MyAvatar";
|
|
||||||
} else if (!value.entity.isNull()) {
|
|
||||||
obj["entity"] = value.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void propertyBindingFromVariant(const QVariant& objectVar, PropertyBinding& value) {
|
|
||||||
auto object = objectVar.toMap();
|
|
||||||
auto avatar = object["avatar"];
|
|
||||||
auto entity = object["entity"];
|
|
||||||
|
|
||||||
if (avatar.isValid() && !avatar.isNull()) {
|
|
||||||
value.avatar = avatar.toString();
|
|
||||||
} else if (entity.isValid() && !entity.isNull()) {
|
|
||||||
value.entity = entity.toUuid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OverlayPanel::addChild(OverlayID childId) {
|
|
||||||
if (!_children.contains(childId)) {
|
|
||||||
_children.append(childId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OverlayPanel::removeChild(OverlayID childId) {
|
|
||||||
if (_children.contains(childId)) {
|
|
||||||
_children.removeOne(childId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant OverlayPanel::getProperty(const QString &property) {
|
|
||||||
if (property == "anchorPosition") {
|
|
||||||
return vec3toVariant(getAnchorPosition());
|
|
||||||
}
|
|
||||||
if (property == "anchorPositionBinding") {
|
|
||||||
return propertyBindingToVariant(PropertyBinding(_anchorPositionBindMyAvatar ?
|
|
||||||
"MyAvatar" : "",
|
|
||||||
_anchorPositionBindEntity));
|
|
||||||
}
|
|
||||||
if (property == "anchorRotation") {
|
|
||||||
return quatToVariant(getAnchorRotation());
|
|
||||||
}
|
|
||||||
if (property == "anchorRotationBinding") {
|
|
||||||
return propertyBindingToVariant(PropertyBinding(_anchorRotationBindMyAvatar ?
|
|
||||||
"MyAvatar" : "",
|
|
||||||
_anchorRotationBindEntity));
|
|
||||||
}
|
|
||||||
if (property == "anchorScale") {
|
|
||||||
return vec3toVariant(getAnchorScale());
|
|
||||||
}
|
|
||||||
if (property == "visible") {
|
|
||||||
return getVisible();
|
|
||||||
}
|
|
||||||
if (property == "children") {
|
|
||||||
QVariantList array;
|
|
||||||
for (int i = 0; i < _children.length(); i++) {
|
|
||||||
array.append(OverlayIDtoScriptValue(nullptr, _children[i]).toVariant());
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto value = Billboardable::getProperty(property);
|
|
||||||
if (value.isValid()) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return PanelAttachable::getProperty(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OverlayPanel::setProperties(const QVariantMap& properties) {
|
|
||||||
PanelAttachable::setProperties(properties);
|
|
||||||
Billboardable::setProperties(properties);
|
|
||||||
|
|
||||||
auto anchorPosition = properties["anchorPosition"];
|
|
||||||
if (anchorPosition.isValid()) {
|
|
||||||
setAnchorPosition(vec3FromVariant(anchorPosition));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto anchorPositionBinding = properties["anchorPositionBinding"];
|
|
||||||
if (anchorPositionBinding.isValid()) {
|
|
||||||
PropertyBinding binding = {};
|
|
||||||
propertyBindingFromVariant(anchorPositionBinding, binding);
|
|
||||||
_anchorPositionBindMyAvatar = binding.avatar == "MyAvatar";
|
|
||||||
_anchorPositionBindEntity = binding.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto anchorRotation = properties["anchorRotation"];
|
|
||||||
if (anchorRotation.isValid()) {
|
|
||||||
setAnchorRotation(quatFromVariant(anchorRotation));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto anchorRotationBinding = properties["anchorRotationBinding"];
|
|
||||||
if (anchorRotationBinding.isValid()) {
|
|
||||||
PropertyBinding binding = {};
|
|
||||||
propertyBindingFromVariant(anchorPositionBinding, binding);
|
|
||||||
_anchorRotationBindMyAvatar = binding.avatar == "MyAvatar";
|
|
||||||
_anchorRotationBindEntity = binding.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto anchorScale = properties["anchorScale"];
|
|
||||||
if (anchorScale.isValid()) {
|
|
||||||
setAnchorScale(vec3FromVariant(anchorScale));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto visible = properties["visible"];
|
|
||||||
if (visible.isValid()) {
|
|
||||||
setVisible(visible.toBool());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OverlayPanel::applyTransformTo(Transform& transform, bool force) {
|
|
||||||
if (force || usecTimestampNow() > _transformExpiry) {
|
|
||||||
PanelAttachable::applyTransformTo(transform, true);
|
|
||||||
if (!getParentPanel()) {
|
|
||||||
if (_anchorPositionBindMyAvatar) {
|
|
||||||
transform.setTranslation(DependencyManager::get<AvatarManager>()->getMyAvatar()
|
|
||||||
->getPosition());
|
|
||||||
} else if (!_anchorPositionBindEntity.isNull()) {
|
|
||||||
EntityTreePointer entityTree = DependencyManager::get<EntityScriptingInterface>()->getEntityTree();
|
|
||||||
entityTree->withReadLock([&] {
|
|
||||||
EntityItemPointer foundEntity = entityTree->findEntityByID(_anchorPositionBindEntity);
|
|
||||||
if (foundEntity) {
|
|
||||||
transform.setTranslation(foundEntity->getPosition());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
transform.setTranslation(getAnchorPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_anchorRotationBindMyAvatar) {
|
|
||||||
transform.setRotation(DependencyManager::get<AvatarManager>()->getMyAvatar()
|
|
||||||
->getOrientation());
|
|
||||||
} else if (!_anchorRotationBindEntity.isNull()) {
|
|
||||||
EntityTreePointer entityTree = DependencyManager::get<EntityScriptingInterface>()->getEntityTree();
|
|
||||||
entityTree->withReadLock([&] {
|
|
||||||
EntityItemPointer foundEntity = entityTree->findEntityByID(_anchorRotationBindEntity);
|
|
||||||
if (foundEntity) {
|
|
||||||
transform.setRotation(foundEntity->getRotation());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
transform.setRotation(getAnchorRotation());
|
|
||||||
}
|
|
||||||
|
|
||||||
transform.setScale(getAnchorScale());
|
|
||||||
|
|
||||||
transform.postTranslate(getOffsetPosition());
|
|
||||||
transform.postRotate(getOffsetRotation());
|
|
||||||
transform.postScale(getOffsetScale());
|
|
||||||
}
|
|
||||||
pointTransformAtCamera(transform, getOffsetRotation());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,86 +0,0 @@
|
||||||
//
|
|
||||||
// OverlayPanel.h
|
|
||||||
// interface/src/ui/overlays
|
|
||||||
//
|
|
||||||
// Created by Zander Otavka on 7/2/15.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_OverlayPanel_h
|
|
||||||
#define hifi_OverlayPanel_h
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
#include <QUuid>
|
|
||||||
|
|
||||||
#include "PanelAttachable.h"
|
|
||||||
#include "Billboardable.h"
|
|
||||||
#include "Overlay.h"
|
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
class PropertyBinding {
|
|
||||||
public:
|
|
||||||
PropertyBinding() {}
|
|
||||||
PropertyBinding(QString avatar, QUuid entity);
|
|
||||||
QString avatar;
|
|
||||||
QUuid entity;
|
|
||||||
};
|
|
||||||
|
|
||||||
QVariant propertyBindingToVariant(const PropertyBinding& value);
|
|
||||||
void propertyBindingFromVariant(const QVariant& object, PropertyBinding& value);
|
|
||||||
|
|
||||||
|
|
||||||
class OverlayPanel : public QObject, public PanelAttachable, public Billboardable {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<OverlayPanel> Pointer;
|
|
||||||
|
|
||||||
void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; }
|
|
||||||
|
|
||||||
// getters
|
|
||||||
glm::vec3 getAnchorPosition() const { return _anchorTransform.getTranslation(); }
|
|
||||||
glm::quat getAnchorRotation() const { return _anchorTransform.getRotation(); }
|
|
||||||
glm::vec3 getAnchorScale() const { return _anchorTransform.getScale(); }
|
|
||||||
bool getVisible() const { return _visible; }
|
|
||||||
|
|
||||||
// setters
|
|
||||||
void setAnchorPosition(const glm::vec3& position) { _anchorTransform.setTranslation(position); }
|
|
||||||
void setAnchorRotation(const glm::quat& rotation) { _anchorTransform.setRotation(rotation); }
|
|
||||||
void setAnchorScale(float scale) { _anchorTransform.setScale(scale); }
|
|
||||||
void setAnchorScale(const glm::vec3& scale) { _anchorTransform.setScale(scale); }
|
|
||||||
void setVisible(bool visible) { _visible = visible; }
|
|
||||||
|
|
||||||
const QList<OverlayID>& getChildren() { return _children; }
|
|
||||||
void addChild(OverlayID childId);
|
|
||||||
void removeChild(OverlayID childId);
|
|
||||||
OverlayID popLastChild() { return _children.takeLast(); }
|
|
||||||
|
|
||||||
void setProperties(const QVariantMap& properties);
|
|
||||||
QVariant getProperty(const QString& property);
|
|
||||||
|
|
||||||
virtual void applyTransformTo(Transform& transform, bool force = false) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Transform _anchorTransform;
|
|
||||||
|
|
||||||
bool _anchorPositionBindMyAvatar = false;
|
|
||||||
QUuid _anchorPositionBindEntity;
|
|
||||||
|
|
||||||
bool _anchorRotationBindMyAvatar = false;
|
|
||||||
QUuid _anchorRotationBindEntity;
|
|
||||||
|
|
||||||
bool _visible = true;
|
|
||||||
QList<OverlayID> _children;
|
|
||||||
|
|
||||||
QScriptEngine* _scriptEngine;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // hifi_OverlayPanel_h
|
|
|
@ -68,16 +68,10 @@ void Overlays::cleanupAllOverlays() {
|
||||||
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
||||||
_overlaysToDelete.push_back(overlay);
|
_overlaysToDelete.push_back(overlay);
|
||||||
}
|
}
|
||||||
#if OVERLAY_PANELS
|
|
||||||
_panels.clear();
|
|
||||||
#endif
|
|
||||||
cleanupOverlaysToDelete();
|
cleanupOverlaysToDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::init() {
|
void Overlays::init() {
|
||||||
#if OVERLAY_PANELS
|
|
||||||
_scriptEngine = new QScriptEngine();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::update(float deltatime) {
|
void Overlays::update(float deltatime) {
|
||||||
|
@ -300,12 +294,6 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
||||||
|
|
||||||
if (thisOverlay) {
|
if (thisOverlay) {
|
||||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); }));
|
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); }));
|
||||||
#if OVERLAY_PANELS
|
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
|
||||||
if (attachable && attachable->getParentPanel()) {
|
|
||||||
attachable->getParentPanel()->addChild(cloneId);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return cloneId;
|
return cloneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,15 +369,6 @@ void Overlays::deleteOverlay(OverlayID id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlayToDelete);
|
|
||||||
if (attachable && attachable->getParentPanel()) {
|
|
||||||
attachable->getParentPanel()->removeChild(id);
|
|
||||||
attachable->setParentPanel(nullptr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
_overlaysToDelete.push_back(overlayToDelete);
|
_overlaysToDelete.push_back(overlayToDelete);
|
||||||
emit overlayDeleted(id);
|
emit overlayDeleted(id);
|
||||||
}
|
}
|
||||||
|
@ -424,49 +403,6 @@ QObject* Overlays::getOverlayObject(OverlayID id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
OverlayID Overlays::getParentPanel(OverlayID childId) const {
|
|
||||||
Overlay::Pointer overlay = getOverlay(childId);
|
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
|
|
||||||
if (attachable) {
|
|
||||||
return _panels.key(attachable->getParentPanel());
|
|
||||||
} else if (_panels.contains(childId)) {
|
|
||||||
return _panels.key(getPanel(childId)->getParentPanel());
|
|
||||||
}
|
|
||||||
return UNKNOWN_OVERLAY_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) {
|
|
||||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(getOverlay(childId));
|
|
||||||
if (attachable) {
|
|
||||||
if (_panels.contains(panelId)) {
|
|
||||||
auto panel = getPanel(panelId);
|
|
||||||
panel->addChild(childId);
|
|
||||||
attachable->setParentPanel(panel);
|
|
||||||
} else {
|
|
||||||
auto panel = attachable->getParentPanel();
|
|
||||||
if (panel) {
|
|
||||||
panel->removeChild(childId);
|
|
||||||
attachable->setParentPanel(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (_panels.contains(childId)) {
|
|
||||||
OverlayPanel::Pointer child = getPanel(childId);
|
|
||||||
if (_panels.contains(panelId)) {
|
|
||||||
auto panel = getPanel(panelId);
|
|
||||||
panel->addChild(childId);
|
|
||||||
child->setParentPanel(panel);
|
|
||||||
} else {
|
|
||||||
auto panel = child->getParentPanel();
|
|
||||||
if (panel) {
|
|
||||||
panel->removeChild(childId);
|
|
||||||
child->setParentPanel(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||||
if (!_enabled) {
|
if (!_enabled) {
|
||||||
return UNKNOWN_OVERLAY_ID;
|
return UNKNOWN_OVERLAY_ID;
|
||||||
|
@ -717,62 +653,6 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) {
|
||||||
return QSizeF(0.0f, 0.0f);
|
return QSizeF(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) {
|
|
||||||
QWriteLocker lock(&_lock);
|
|
||||||
|
|
||||||
OverlayID thisID = QUuid::createUuid();
|
|
||||||
_panels[thisID] = panel;
|
|
||||||
|
|
||||||
return thisID;
|
|
||||||
}
|
|
||||||
|
|
||||||
OverlayID Overlays::addPanel(const QVariant& properties) {
|
|
||||||
OverlayPanel::Pointer panel = std::make_shared<OverlayPanel>();
|
|
||||||
panel->init(_scriptEngine);
|
|
||||||
panel->setProperties(properties.toMap());
|
|
||||||
return addPanel(panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Overlays::editPanel(OverlayID panelId, const QVariant& properties) {
|
|
||||||
if (_panels.contains(panelId)) {
|
|
||||||
_panels[panelId]->setProperties(properties.toMap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OverlayPropertyResult Overlays::getPanelProperty(OverlayID panelId, const QString& property) {
|
|
||||||
OverlayPropertyResult result;
|
|
||||||
if (_panels.contains(panelId)) {
|
|
||||||
OverlayPanel::Pointer thisPanel = getPanel(panelId);
|
|
||||||
QReadLocker lock(&_lock);
|
|
||||||
result.value = thisPanel->getProperty(property);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Overlays::deletePanel(OverlayID panelId) {
|
|
||||||
OverlayPanel::Pointer panelToDelete;
|
|
||||||
|
|
||||||
{
|
|
||||||
QWriteLocker lock(&_lock);
|
|
||||||
if (_panels.contains(panelId)) {
|
|
||||||
panelToDelete = _panels.take(panelId);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!panelToDelete->getChildren().isEmpty()) {
|
|
||||||
OverlayID childId = panelToDelete->popLastChild();
|
|
||||||
deleteOverlay(childId);
|
|
||||||
deletePanel(childId);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit panelDeleted(panelId);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool Overlays::isAddedOverlay(OverlayID id) {
|
bool Overlays::isAddedOverlay(OverlayID id) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
bool result;
|
bool result;
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "Overlay.h"
|
#include "Overlay.h"
|
||||||
|
|
||||||
#include "PanelAttachable.h"
|
#include "PanelAttachable.h"
|
||||||
#include "OverlayPanel.h"
|
|
||||||
|
|
||||||
class PickRay;
|
class PickRay;
|
||||||
|
|
||||||
|
@ -93,9 +92,6 @@ public:
|
||||||
void enable();
|
void enable();
|
||||||
|
|
||||||
Overlay::Pointer getOverlay(OverlayID id) const;
|
Overlay::Pointer getOverlay(OverlayID id) const;
|
||||||
#if OVERLAY_PANELS
|
|
||||||
OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// adds an overlay that's already been created
|
/// adds an overlay that's already been created
|
||||||
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
||||||
|
@ -468,30 +464,6 @@ public slots:
|
||||||
*/
|
*/
|
||||||
bool isAddedOverlay(OverlayID id);
|
bool isAddedOverlay(OverlayID id);
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
OverlayID getParentPanel(OverlayID childId) const;
|
|
||||||
void setParentPanel(OverlayID childId, OverlayID panelId);
|
|
||||||
|
|
||||||
/// adds a panel that has already been created
|
|
||||||
OverlayID addPanel(OverlayPanel::Pointer panel);
|
|
||||||
|
|
||||||
/// creates and adds a panel based on a set of properties
|
|
||||||
OverlayID addPanel(const QVariant& properties);
|
|
||||||
|
|
||||||
/// edit the properties of a panel
|
|
||||||
void editPanel(OverlayID panelId, const QVariant& properties);
|
|
||||||
|
|
||||||
/// get a property of a panel
|
|
||||||
OverlayPropertyResult getPanelProperty(OverlayID panelId, const QString& property);
|
|
||||||
|
|
||||||
/// deletes a panel and all child overlays
|
|
||||||
void deletePanel(OverlayID panelId);
|
|
||||||
|
|
||||||
/// return true if there is a panel with that id else false
|
|
||||||
bool isAddedPanel(OverlayID id) { return _panels.contains(id); }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Generate a mouse press event on an overlay.
|
* Generate a mouse press event on an overlay.
|
||||||
* @function Overlays.sendMousePressOnOverlay
|
* @function Overlays.sendMousePressOnOverlay
|
||||||
|
@ -612,10 +584,6 @@ signals:
|
||||||
*/
|
*/
|
||||||
void overlayDeleted(OverlayID id);
|
void overlayDeleted(OverlayID id);
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
void panelDeleted(OverlayID id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered when a mouse press event occurs on an overlay. Only occurs for 3D overlays (unless you use
|
* Triggered when a mouse press event occurs on an overlay. Only occurs for 3D overlays (unless you use
|
||||||
* {@link Overlays.sendMousePressOnOverlay|sendMousePressOnOverlay} for a 2D overlay).
|
* {@link Overlays.sendMousePressOnOverlay|sendMousePressOnOverlay} for a 2D overlay).
|
||||||
|
@ -732,15 +700,9 @@ private:
|
||||||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
|
||||||
#endif
|
|
||||||
QList<Overlay::Pointer> _overlaysToDelete;
|
QList<Overlay::Pointer> _overlaysToDelete;
|
||||||
unsigned int _stackOrder { 1 };
|
unsigned int _stackOrder { 1 };
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
|
||||||
QScriptEngine* _scriptEngine;
|
|
||||||
#endif
|
|
||||||
bool _enabled = true;
|
bool _enabled = true;
|
||||||
|
|
||||||
PointerEvent calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
|
PointerEvent calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
|
||||||
|
|
|
@ -65,23 +65,7 @@ namespace render {
|
||||||
}
|
}
|
||||||
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
|
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
|
||||||
if (args) {
|
if (args) {
|
||||||
if (overlay->getAnchor() == Overlay::MY_AVATAR) {
|
overlay->render(args);
|
||||||
auto batch = args->_batch;
|
|
||||||
auto avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
|
||||||
glm::quat myAvatarRotation = avatar->getWorldOrientation();
|
|
||||||
glm::vec3 myAvatarPosition = avatar->getWorldPosition();
|
|
||||||
float angle = glm::degrees(glm::angle(myAvatarRotation));
|
|
||||||
glm::vec3 axis = glm::axis(myAvatarRotation);
|
|
||||||
float myAvatarScale = avatar->getModelScale();
|
|
||||||
Transform transform = Transform();
|
|
||||||
transform.setTranslation(myAvatarPosition);
|
|
||||||
transform.setRotation(glm::angleAxis(angle, axis));
|
|
||||||
transform.setScale(myAvatarScale);
|
|
||||||
batch->setModelTransform(transform);
|
|
||||||
overlay->render(args);
|
|
||||||
} else {
|
|
||||||
overlay->render(args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay) {
|
template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay) {
|
||||||
|
|
|
@ -13,18 +13,8 @@
|
||||||
|
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
#include "OverlayPanel.h"
|
|
||||||
|
|
||||||
bool PanelAttachable::getParentVisible() const {
|
bool PanelAttachable::getParentVisible() const {
|
||||||
#if OVERLAY_PANELS
|
|
||||||
if (getParentPanel()) {
|
|
||||||
return getParentPanel()->getVisible() && getParentPanel()->getParentVisible();
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSDoc for copying to @typedefs of overlay types that inherit PanelAttachable.
|
// JSDoc for copying to @typedefs of overlay types that inherit PanelAttachable.
|
||||||
|
@ -67,15 +57,6 @@ bool PanelAttachable::applyTransformTo(Transform& transform, bool force) {
|
||||||
if (force || usecTimestampNow() > _transformExpiry) {
|
if (force || usecTimestampNow() > _transformExpiry) {
|
||||||
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
||||||
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
||||||
#if OVERLAY_PANELS
|
|
||||||
if (getParentPanel()) {
|
|
||||||
getParentPanel()->applyTransformTo(transform, true);
|
|
||||||
transform.postTranslate(getOffsetPosition());
|
|
||||||
transform.postRotate(getOffsetRotation());
|
|
||||||
transform.postScale(getOffsetScale());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
#ifndef hifi_PanelAttachable_h
|
#ifndef hifi_PanelAttachable_h
|
||||||
#define hifi_PanelAttachable_h
|
#define hifi_PanelAttachable_h
|
||||||
|
|
||||||
#define OVERLAY_PANELS 0
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
@ -44,18 +42,12 @@ class OverlayPanel;
|
||||||
class PanelAttachable {
|
class PanelAttachable {
|
||||||
public:
|
public:
|
||||||
// getters
|
// getters
|
||||||
#if OVERLAY_PANELS
|
|
||||||
std::shared_ptr<OverlayPanel> getParentPanel() const { return _parentPanel; }
|
|
||||||
#endif
|
|
||||||
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
||||||
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
||||||
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
||||||
bool getParentVisible() const;
|
bool getParentVisible() const;
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
#if OVERLAY_PANELS
|
|
||||||
void setParentPanel(std::shared_ptr<OverlayPanel> panel) { _parentPanel = panel; }
|
|
||||||
#endif
|
|
||||||
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
||||||
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
||||||
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
||||||
|
@ -71,9 +63,6 @@ protected:
|
||||||
quint64 _transformExpiry = 0;
|
quint64 _transformExpiry = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if OVERLAY_PANELS
|
|
||||||
std::shared_ptr<OverlayPanel> _parentPanel = nullptr;
|
|
||||||
#endif
|
|
||||||
Transform _offset;
|
Transform _offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -127,8 +127,6 @@ const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -128,8 +128,6 @@ void Shape3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -47,8 +47,6 @@ Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -224,8 +224,6 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -484,8 +484,6 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||||
* used.)
|
* used.)
|
||||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
|
||||||
* rotating as you move your avatar.
|
|
||||||
*
|
*
|
||||||
* @property {string} name="" - A friendly name for the overlay.
|
* @property {string} name="" - A friendly name for the overlay.
|
||||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||||
|
|
|
@ -328,13 +328,15 @@ void Avatar::updateAvatarEntities() {
|
||||||
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
||||||
if (!recentlyDettachedAvatarEntities.empty()) {
|
if (!recentlyDettachedAvatarEntities.empty()) {
|
||||||
// only lock this thread when absolutely necessary
|
// only lock this thread when absolutely necessary
|
||||||
|
AvatarEntityMap avatarEntityData;
|
||||||
_avatarEntitiesLock.withReadLock([&] {
|
_avatarEntitiesLock.withReadLock([&] {
|
||||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
avatarEntityData = _avatarEntityData;
|
||||||
if (!_avatarEntityData.contains(entityID)) {
|
|
||||||
entityTree->deleteEntity(entityID, true, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||||
|
if (!avatarEntityData.contains(entityID)) {
|
||||||
|
entityTree->deleteEntity(entityID, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remove stale data hashes
|
// remove stale data hashes
|
||||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||||
|
|
|
@ -2086,6 +2086,10 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
||||||
|
|
||||||
EntityDynamicPointer action = _objectActions[actionID];
|
EntityDynamicPointer action = _objectActions[actionID];
|
||||||
auto removedActionType = action->getType();
|
auto removedActionType = action->getType();
|
||||||
|
action->setOwnerEntity(nullptr);
|
||||||
|
action->setIsMine(false);
|
||||||
|
_objectActions.remove(actionID);
|
||||||
|
|
||||||
if ((removedActionType == DYNAMIC_TYPE_HOLD || removedActionType == DYNAMIC_TYPE_FAR_GRAB) && !stillHasGrabActions()) {
|
if ((removedActionType == DYNAMIC_TYPE_HOLD || removedActionType == DYNAMIC_TYPE_FAR_GRAB) && !stillHasGrabActions()) {
|
||||||
_dirtyFlags &= ~Simulation::NO_BOOTSTRAPPING;
|
_dirtyFlags &= ~Simulation::NO_BOOTSTRAPPING;
|
||||||
_dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
_dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
||||||
|
@ -2101,9 +2105,6 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
||||||
// because they should have been set correctly when the action was added
|
// because they should have been set correctly when the action was added
|
||||||
// and/or when children were linked
|
// and/or when children were linked
|
||||||
}
|
}
|
||||||
action->setOwnerEntity(nullptr);
|
|
||||||
action->setIsMine(false);
|
|
||||||
_objectActions.remove(actionID);
|
|
||||||
|
|
||||||
if (simulation) {
|
if (simulation) {
|
||||||
action->removeFromSimulation(simulation);
|
action->removeFromSimulation(simulation);
|
||||||
|
|
|
@ -722,7 +722,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionless, bool, setCollisionless);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionless, bool, setCollisionless);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(ignoreForCollisions, bool, setCollisionless, getCollisionless); // legacy support
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(ignoreForCollisions, bool, setCollisionless, getCollisionless); // legacy support
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint8_t, setCollisionMask);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint8_t, setCollisionMask);
|
||||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(collidesWith, CollisionMask);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(collidesWith, CollisionMask);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(collisionsWillMove, bool, setDynamic, getDynamic); // legacy support
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(collisionsWillMove, bool, setDynamic, getDynamic); // legacy support
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(dynamic, bool, setDynamic);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(dynamic, bool, setDynamic);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isSpotlight, bool, setIsSpotlight);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(isSpotlight, bool, setIsSpotlight);
|
||||||
|
@ -737,7 +737,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lineHeight, float, setLineHeight);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(lineHeight, float, setLineHeight);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(textColor, xColor, setTextColor);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(textColor, xColor, setTextColor);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundColor, xColor, setBackgroundColor);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundColor, xColor, setBackgroundColor);
|
||||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(shapeType, ShapeType);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isEmitting, bool, setIsEmitting);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(isEmitting, bool, setIsEmitting);
|
||||||
|
@ -775,10 +775,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL);
|
||||||
|
|
||||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(hazeMode, HazeMode);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(hazeMode, HazeMode);
|
||||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(keyLightMode, KeyLightMode);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(keyLightMode, KeyLightMode);
|
||||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(ambientLightMode, AmbientLightMode);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode);
|
||||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(skyboxMode, SkyboxMode);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode);
|
||||||
|
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize);
|
||||||
|
|
|
@ -367,7 +367,7 @@ inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \
|
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S) \
|
||||||
QScriptValue P = object.property(#P); \
|
QScriptValue P = object.property(#P); \
|
||||||
if (P.isValid()) { \
|
if (P.isValid()) { \
|
||||||
QString newValue = P.toVariant().toString(); \
|
QString newValue = P.toVariant().toString(); \
|
||||||
|
|
|
@ -19,15 +19,6 @@
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
|
||||||
|
|
||||||
#if defined(Q_OS_ANDROID)
|
|
||||||
#define CPU_MIPMAPS 1
|
|
||||||
#else
|
|
||||||
#define CPU_MIPMAPS 1
|
|
||||||
#include <nvtt/nvtt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <Finally.h>
|
#include <Finally.h>
|
||||||
#include <Profile.h>
|
#include <Profile.h>
|
||||||
#include <StatTracker.h>
|
#include <StatTracker.h>
|
||||||
|
@ -37,6 +28,12 @@
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
#define CPU_MIPMAPS 1
|
||||||
|
#else
|
||||||
|
#define CPU_MIPMAPS 1
|
||||||
|
#include <nvtt/nvtt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static const glm::uvec2 SPARSE_PAGE_SIZE(128);
|
static const glm::uvec2 SPARSE_PAGE_SIZE(128);
|
||||||
static const glm::uvec2 MAX_TEXTURE_SIZE(4096);
|
static const glm::uvec2 MAX_TEXTURE_SIZE(4096);
|
||||||
|
@ -51,25 +48,21 @@ static std::atomic<bool> compressNormalTextures { false };
|
||||||
static std::atomic<bool> compressGrayscaleTextures { false };
|
static std::atomic<bool> compressGrayscaleTextures { false };
|
||||||
static std::atomic<bool> compressCubeTextures { false };
|
static std::atomic<bool> compressCubeTextures { false };
|
||||||
|
|
||||||
bool needsSparseRectification(const glm::uvec2& size) {
|
uint rectifyDimension(const uint& dimension) {
|
||||||
// Don't attempt to rectify small textures (textures less than the sparse page size in any dimension)
|
if (dimension < SPARSE_PAGE_SIZE.x) {
|
||||||
if (glm::any(glm::lessThan(size, SPARSE_PAGE_SIZE))) {
|
uint newSize = SPARSE_PAGE_SIZE.x;
|
||||||
return false;
|
while (dimension <= newSize / 2) {
|
||||||
|
newSize /= 2;
|
||||||
|
}
|
||||||
|
return newSize;
|
||||||
|
} else {
|
||||||
|
uint pages = (dimension / SPARSE_PAGE_SIZE.x) + (dimension % SPARSE_PAGE_SIZE.x == 0 ? 0 : 1);
|
||||||
|
return pages * SPARSE_PAGE_SIZE.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't rectify textures that are already an exact multiple of sparse page size
|
|
||||||
if (glm::uvec2(0) == (size % SPARSE_PAGE_SIZE)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Texture is not sparse compatible, but is bigger than the sparse page size in both dimensions, rectify!
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) {
|
glm::uvec2 rectifySize(const glm::uvec2& size) {
|
||||||
glm::uvec2 pages = ((size / SPARSE_PAGE_SIZE) + glm::clamp(size % SPARSE_PAGE_SIZE, glm::uvec2(0), glm::uvec2(1)));
|
return { rectifyDimension(size.x), rectifyDimension(size.y) };
|
||||||
glm::uvec2 result = pages * SPARSE_PAGE_SIZE;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,9 +322,12 @@ QImage processSourceImage(QImage&& srcImage, bool cubemap) {
|
||||||
++DECIMATED_TEXTURE_COUNT;
|
++DECIMATED_TEXTURE_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cubemap && needsSparseRectification(targetSize)) {
|
if (!cubemap) {
|
||||||
++RECTIFIED_TEXTURE_COUNT;
|
auto rectifiedSize = rectifySize(targetSize);
|
||||||
targetSize = rectifyToSparseSize(targetSize);
|
if (rectifiedSize != targetSize) {
|
||||||
|
++RECTIFIED_TEXTURE_COUNT;
|
||||||
|
targetSize = rectifiedSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEV_DECIMATE_TEXTURES && glm::all(glm::greaterThanEqual(targetSize / SPARSE_PAGE_SIZE, glm::uvec2(2)))) {
|
if (DEV_DECIMATE_TEXTURES && glm::all(glm::greaterThanEqual(targetSize / SPARSE_PAGE_SIZE, glm::uvec2(2)))) {
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
* Get Interface's protocol version.
|
* Get Interface's protocol version.
|
||||||
* @function location.protocolVersion
|
* @function location.protocolVersion
|
||||||
* @returns {string} A string uniquely identifying the version of the metaverse protocol that Interface is using.
|
* @returns {string} A string uniquely identifying the version of the metaverse protocol that Interface is using.
|
||||||
|
* @deprecated This function is deprecated and will be removed. Use {@link Window.protocolSignature} instead.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE QString protocolVersion();
|
Q_INVOKABLE QString protocolVersion();
|
||||||
|
|
||||||
|
|
|
@ -63,13 +63,6 @@ LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) :
|
||||||
_packetStatTimer(),
|
_packetStatTimer(),
|
||||||
_permissions(NodePermissions())
|
_permissions(NodePermissions())
|
||||||
{
|
{
|
||||||
static bool firstCall = true;
|
|
||||||
if (firstCall) {
|
|
||||||
NodeType::init();
|
|
||||||
|
|
||||||
firstCall = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qRegisterMetaType<ConnectionStep>("ConnectionStep");
|
qRegisterMetaType<ConnectionStep>("ConnectionStep");
|
||||||
auto port = (socketListenPort != INVALID_PORT) ? socketListenPort : LIMITED_NODELIST_LOCAL_PORT.get();
|
auto port = (socketListenPort != INVALID_PORT) ? socketListenPort : LIMITED_NODELIST_LOCAL_PORT.get();
|
||||||
_nodeSocket.bind(QHostAddress::AnyIPv4, port);
|
_nodeSocket.bind(QHostAddress::AnyIPv4, port);
|
||||||
|
|
|
@ -29,28 +29,25 @@ int NodePtrMetaTypeId = qRegisterMetaType<Node*>("Node*");
|
||||||
int sharedPtrNodeMetaTypeId = qRegisterMetaType<QSharedPointer<Node>>("QSharedPointer<Node>");
|
int sharedPtrNodeMetaTypeId = qRegisterMetaType<QSharedPointer<Node>>("QSharedPointer<Node>");
|
||||||
int sharedNodePtrMetaTypeId = qRegisterMetaType<SharedNodePointer>("SharedNodePointer");
|
int sharedNodePtrMetaTypeId = qRegisterMetaType<SharedNodePointer>("SharedNodePointer");
|
||||||
|
|
||||||
void NodeType::init() {
|
static const QHash<NodeType_t, QString> TYPE_NAME_HASH {
|
||||||
QHash<NodeType_t, QString>& TypeNameHash = Node::getTypeNameHash();
|
{ NodeType::DomainServer, "Domain Server" },
|
||||||
|
{ NodeType::EntityServer, "Entity Server" },
|
||||||
TypeNameHash.insert(NodeType::DomainServer, "Domain Server");
|
{ NodeType::Agent, "Agent" },
|
||||||
TypeNameHash.insert(NodeType::EntityServer, "Entity Server");
|
{ NodeType::AudioMixer, "Audio Mixer" },
|
||||||
TypeNameHash.insert(NodeType::Agent, "Agent");
|
{ NodeType::AvatarMixer, "Avatar Mixer" },
|
||||||
TypeNameHash.insert(NodeType::AudioMixer, "Audio Mixer");
|
{ NodeType::MessagesMixer, "Messages Mixer" },
|
||||||
TypeNameHash.insert(NodeType::AvatarMixer, "Avatar Mixer");
|
{ NodeType::AssetServer, "Asset Server" },
|
||||||
TypeNameHash.insert(NodeType::MessagesMixer, "Messages Mixer");
|
{ NodeType::EntityScriptServer, "Entity Script Server" },
|
||||||
TypeNameHash.insert(NodeType::AssetServer, "Asset Server");
|
{ NodeType::UpstreamAudioMixer, "Upstream Audio Mixer" },
|
||||||
TypeNameHash.insert(NodeType::EntityScriptServer, "Entity Script Server");
|
{ NodeType::UpstreamAvatarMixer, "Upstream Avatar Mixer" },
|
||||||
TypeNameHash.insert(NodeType::UpstreamAudioMixer, "Upstream Audio Mixer");
|
{ NodeType::DownstreamAudioMixer, "Downstream Audio Mixer" },
|
||||||
TypeNameHash.insert(NodeType::UpstreamAvatarMixer, "Upstream Avatar Mixer");
|
{ NodeType::DownstreamAvatarMixer, "Downstream Avatar Mixer" },
|
||||||
TypeNameHash.insert(NodeType::DownstreamAudioMixer, "Downstream Audio Mixer");
|
{ NodeType::Unassigned, "Unassigned" }
|
||||||
TypeNameHash.insert(NodeType::DownstreamAvatarMixer, "Downstream Avatar Mixer");
|
};
|
||||||
TypeNameHash.insert(NodeType::Unassigned, "Unassigned");
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
|
const QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
|
||||||
QHash<NodeType_t, QString>& TypeNameHash = Node::getTypeNameHash();
|
const auto matchedTypeName = TYPE_NAME_HASH.find(nodeType);
|
||||||
QHash<NodeType_t, QString>::iterator matchedTypeName = TypeNameHash.find(nodeType);
|
return matchedTypeName != TYPE_NAME_HASH.end() ? matchedTypeName.value() : UNKNOWN_NodeType_t_NAME;
|
||||||
return matchedTypeName != TypeNameHash.end() ? matchedTypeName.value() : UNKNOWN_NodeType_t_NAME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeType::isUpstream(NodeType_t nodeType) {
|
bool NodeType::isUpstream(NodeType_t nodeType) {
|
||||||
|
@ -84,8 +81,7 @@ NodeType_t NodeType::downstreamType(NodeType_t primaryType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType_t NodeType::fromString(QString type) {
|
NodeType_t NodeType::fromString(QString type) {
|
||||||
QHash<NodeType_t, QString>& TypeNameHash = Node::getTypeNameHash();
|
return TYPE_NAME_HASH.key(type, NodeType::Unassigned);
|
||||||
return TypeNameHash.key(type, NodeType::Unassigned);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,11 +89,6 @@ public:
|
||||||
|
|
||||||
bool isIgnoreRadiusEnabled() const { return _ignoreRadiusEnabled; }
|
bool isIgnoreRadiusEnabled() const { return _ignoreRadiusEnabled; }
|
||||||
|
|
||||||
static QHash<NodeType_t, QString>& getTypeNameHash() {
|
|
||||||
static QHash<NodeType_t, QString> TypeNameHash;
|
|
||||||
return TypeNameHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// privatize copy and assignment operator to disallow Node copying
|
// privatize copy and assignment operator to disallow Node copying
|
||||||
Node(const Node &otherNode);
|
Node(const Node &otherNode);
|
||||||
|
|
|
@ -31,8 +31,6 @@ namespace NodeType {
|
||||||
const NodeType_t DownstreamAvatarMixer = 'w';
|
const NodeType_t DownstreamAvatarMixer = 'w';
|
||||||
const NodeType_t Unassigned = 1;
|
const NodeType_t Unassigned = 1;
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
const QString& getNodeTypeName(NodeType_t nodeType);
|
const QString& getNodeTypeName(NodeType_t nodeType);
|
||||||
bool isUpstream(NodeType_t nodeType);
|
bool isUpstream(NodeType_t nodeType);
|
||||||
bool isDownstream(NodeType_t nodeType);
|
bool isDownstream(NodeType_t nodeType);
|
||||||
|
|
|
@ -319,11 +319,13 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
|
||||||
// Setup lighting model for all items;
|
// Setup lighting model for all items;
|
||||||
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
|
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
|
||||||
|
|
||||||
// Setup haze iff curretn zone has haze
|
// Setup haze iff current zone has haze
|
||||||
auto hazeStage = args->_scene->getStage<HazeStage>();
|
auto hazeStage = args->_scene->getStage<HazeStage>();
|
||||||
if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) {
|
if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) {
|
||||||
graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front());
|
graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front());
|
||||||
batch.setUniformBuffer(render::ShapePipeline::Slot::HAZE_MODEL, hazePointer->getHazeParametersBuffer());
|
if (hazePointer) {
|
||||||
|
batch.setUniformBuffer(render::ShapePipeline::Slot::HAZE_MODEL, hazePointer->getHazeParametersBuffer());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// From the lighting model define a global shapKey ORED with individiual keys
|
// From the lighting model define a global shapKey ORED with individiual keys
|
||||||
|
|
|
@ -87,7 +87,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT));
|
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK));
|
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS));
|
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("hazeParametersBuffer"), Slot::BUFFER::HAZE_MODEL));
|
slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), Slot::BUFFER::HAZE_MODEL));
|
||||||
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
|
|
77
scripts/developer/utilities/render/lod.js
Normal file
77
scripts/developer/utilities/render/lod.js
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
//
|
||||||
|
// lodi.js
|
||||||
|
// tablet-engine app
|
||||||
|
//
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var TABLET_BUTTON_NAME = "LOD";
|
||||||
|
var QMLAPP_URL = Script.resolvePath("./lod.qml");
|
||||||
|
var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg");
|
||||||
|
var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg");
|
||||||
|
|
||||||
|
var onScreen = false;
|
||||||
|
|
||||||
|
function onClicked() {
|
||||||
|
if (onScreen) {
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
} else {
|
||||||
|
tablet.loadQMLSource(QMLAPP_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
var button = tablet.addButton({
|
||||||
|
text: TABLET_BUTTON_NAME,
|
||||||
|
icon: ICON_URL,
|
||||||
|
activeIcon: ACTIVE_ICON_URL,
|
||||||
|
sortOrder: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
var hasEventBridge = false;
|
||||||
|
|
||||||
|
function wireEventBridge(on) {
|
||||||
|
if (!tablet) {
|
||||||
|
print("Warning in wireEventBridge(): 'tablet' undefined!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (on) {
|
||||||
|
if (!hasEventBridge) {
|
||||||
|
tablet.fromQml.connect(fromQml);
|
||||||
|
hasEventBridge = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hasEventBridge) {
|
||||||
|
tablet.fromQml.disconnect(fromQml);
|
||||||
|
hasEventBridge = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onScreenChanged(type, url) {
|
||||||
|
onScreen = (url === QMLAPP_URL);
|
||||||
|
button.editProperties({isActive: onScreen});
|
||||||
|
wireEventBridge(onScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromQml(message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
button.clicked.connect(onClicked);
|
||||||
|
tablet.screenChanged.connect(onScreenChanged);
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function () {
|
||||||
|
if (onScreen) {
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
}
|
||||||
|
button.clicked.disconnect(onClicked);
|
||||||
|
tablet.screenChanged.disconnect(onScreenChanged);
|
||||||
|
tablet.removeButton(button);
|
||||||
|
});
|
||||||
|
}());
|
92
scripts/developer/utilities/render/lod.qml
Normal file
92
scripts/developer/utilities/render/lod.qml
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// lod.qml
|
||||||
|
// scripts/developer/utilities/render
|
||||||
|
//
|
||||||
|
// Created by Andrew Meadows on 2018.01.10
|
||||||
|
// Copyright 2018 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.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import "../lib/plotperf"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: lodIU
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: stats
|
||||||
|
spacing: 8
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
function evalEvenHeight() {
|
||||||
|
// Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ?
|
||||||
|
return (height - spacing * (children.length - 1)) / children.length
|
||||||
|
}
|
||||||
|
|
||||||
|
PlotPerf {
|
||||||
|
title: "Load Indicators"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: LODManager
|
||||||
|
valueScale: 1
|
||||||
|
valueUnit: "ms"
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "presentTime",
|
||||||
|
label: "present",
|
||||||
|
color: "#FFFF00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "engineRunTime",
|
||||||
|
label: "engineRun",
|
||||||
|
color: "#FF00FF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "gpuTime",
|
||||||
|
label: "gpu",
|
||||||
|
color: "#00FFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PlotPerf {
|
||||||
|
title: "FPS"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: LODManager
|
||||||
|
valueScale: 1
|
||||||
|
valueUnit: "Hz"
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "lodIncreaseFPS",
|
||||||
|
label: "LOD++",
|
||||||
|
color: "#66FF66"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "fps",
|
||||||
|
label: "FPS",
|
||||||
|
color: "#FFFFFF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "lodDecreaseFPS",
|
||||||
|
label: "LOD--",
|
||||||
|
color: "#FF6666"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PlotPerf {
|
||||||
|
title: "LOD"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: LODManager
|
||||||
|
valueScale: 0.1
|
||||||
|
valueUnit: ""
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "lodLevel",
|
||||||
|
label: "LOD",
|
||||||
|
color: "#9999FF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
scripts/system/assets/images/lod-a.svg
Normal file
46
scripts/system/assets/images/lod-a.svg
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="Layer_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 50 50"
|
||||||
|
style="enable-background:new 0 0 50 50;"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="lod-a.svg"><metadata
|
||||||
|
id="metadata4241"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs4239" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="2880"
|
||||||
|
inkscape:window-height="1724"
|
||||||
|
id="namedview4237"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="14.66"
|
||||||
|
inkscape:cx="22.9339"
|
||||||
|
inkscape:cy="22.463149"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="33"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Layer_1" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:44.7959404px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 0.17382812 0.10351562 L 0.17382812 26.466797 L 12.335938 26.466797 C 12.295785 25.916449 12.273438 25.352399 12.273438 24.773438 C 12.273438 24.325519 12.298233 23.895635 12.322266 23.464844 L 5.6464844 23.464844 L 5.6464844 0.10351562 L 0.17382812 0.10351562 z M 12.322266 23.464844 L 16.9375 23.464844 C 17.131223 20.269693 18.048402 17.696004 19.695312 15.748047 C 21.57624 13.54041 24.107908 12.4375 27.291016 12.4375 C 30.474123 12.4375 32.99176 13.54041 34.84375 15.748047 C 36.522116 17.733209 37.438284 20.371891 37.607422 23.652344 C 39.352093 23.851854 40.904899 24.187106 42.263672 24.662109 C 42.242096 19.950324 40.88586 16.190967 38.1875 13.386719 C 35.46739 10.546406 31.834178 9.125 27.291016 9.125 C 22.733385 9.125 19.088094 10.546406 16.353516 13.386719 C 13.889087 15.947857 12.553913 19.312575 12.322266 23.464844 z M 42.263672 24.662109 C 42.263846 24.700089 42.267578 24.735334 42.267578 24.773438 C 42.267578 25.968111 42.179749 27.101932 42.007812 28.175781 C 42.345297 28.39193 42.664811 28.621521 42.951172 28.876953 C 44.826172 30.525965 45.763672 33.130435 45.763672 36.689453 C 45.763672 40.272198 44.826172 42.893812 42.951172 44.554688 C 41.089193 46.215563 38.146485 47.046875 34.123047 47.046875 L 29.357422 47.046875 L 29.357422 40.285156 C 28.688843 40.354889 28.004565 40.402344 27.291016 40.402344 C 26.644531 40.402344 26.021914 40.365471 25.412109 40.308594 L 25.412109 50 L 33.517578 50 C 39.142578 50 43.283203 48.926571 45.939453 46.779297 C 48.595703 44.632023 49.923828 41.268723 49.923828 36.689453 C 49.923828 32.13391 48.602214 28.787755 45.958984 26.652344 C 44.948178 25.831197 43.714341 25.169238 42.263672 24.662109 z M 25.412109 40.308594 L 25.412109 36.939453 C 23.099 36.57794 21.188155 35.53144 19.695312 33.779297 C 18.116681 31.9121 17.214144 29.470287 16.970703 26.466797 L 12.335938 26.466797 C 12.626268 30.446204 13.963889 33.678709 16.353516 36.162109 C 18.700203 38.587982 21.722877 39.964492 25.412109 40.308594 z M 16.970703 26.466797 L 25.34375 26.466797 L 25.34375 23.464844 L 16.9375 23.464844 C 16.911675 23.890786 16.896484 24.325331 16.896484 24.773438 C 16.896484 25.358829 16.926317 25.91918 16.970703 26.466797 z M 25.412109 36.939453 C 26.013434 37.033433 26.634257 37.091797 27.291016 37.091797 C 28.01543 37.091797 28.701951 37.02645 29.357422 36.912109 L 29.357422 26.386719 L 34.123047 26.386719 C 35.374898 26.386719 36.510129 26.475933 37.552734 26.636719 C 37.606917 26.036054 37.644531 25.420213 37.644531 24.773438 C 37.644531 24.389533 37.626377 24.01998 37.607422 23.652344 C 36.34394 23.507859 34.983448 23.431641 33.517578 23.431641 L 25.412109 23.431641 L 25.412109 36.939453 z M 37.552734 26.636719 C 37.288908 29.561476 36.3922 31.947799 34.84375 33.779297 C 33.413238 35.484518 31.582121 36.524034 29.357422 36.912109 L 29.357422 40.285156 C 32.945677 39.910903 35.894611 38.544976 38.1875 36.162109 C 40.223734 34.035893 41.495873 31.373159 42.007812 28.175781 C 40.833664 27.423776 39.345701 26.913222 37.552734 26.636719 z "
|
||||||
|
id="text4243" /></svg>
|
After Width: | Height: | Size: 4.9 KiB |
46
scripts/system/assets/images/lod-i.svg
Normal file
46
scripts/system/assets/images/lod-i.svg
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="Layer_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 50 50"
|
||||||
|
style="enable-background:new 0 0 50 50;"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="lod-i.svg"><metadata
|
||||||
|
id="metadata4241"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs4239" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="2880"
|
||||||
|
inkscape:window-height="1724"
|
||||||
|
id="namedview4237"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="14.66"
|
||||||
|
inkscape:cx="22.9339"
|
||||||
|
inkscape:cy="22.463149"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="33"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Layer_1" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:44.7959404px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 0.17382812 0.10351562 L 0.17382812 26.466797 L 12.335938 26.466797 C 12.295785 25.916449 12.273438 25.352399 12.273438 24.773438 C 12.273438 24.325519 12.298233 23.895635 12.322266 23.464844 L 5.6464844 23.464844 L 5.6464844 0.10351562 L 0.17382812 0.10351562 z M 12.322266 23.464844 L 16.9375 23.464844 C 17.131223 20.269693 18.048402 17.696004 19.695312 15.748047 C 21.57624 13.54041 24.107908 12.4375 27.291016 12.4375 C 30.474123 12.4375 32.99176 13.54041 34.84375 15.748047 C 36.522116 17.733209 37.438284 20.371891 37.607422 23.652344 C 39.352093 23.851854 40.904899 24.187106 42.263672 24.662109 C 42.242096 19.950324 40.88586 16.190967 38.1875 13.386719 C 35.46739 10.546406 31.834178 9.125 27.291016 9.125 C 22.733385 9.125 19.088094 10.546406 16.353516 13.386719 C 13.889087 15.947857 12.553913 19.312575 12.322266 23.464844 z M 42.263672 24.662109 C 42.263846 24.700089 42.267578 24.735334 42.267578 24.773438 C 42.267578 25.968111 42.179749 27.101932 42.007812 28.175781 C 42.345297 28.39193 42.664811 28.621521 42.951172 28.876953 C 44.826172 30.525965 45.763672 33.130435 45.763672 36.689453 C 45.763672 40.272198 44.826172 42.893812 42.951172 44.554688 C 41.089193 46.215563 38.146485 47.046875 34.123047 47.046875 L 29.357422 47.046875 L 29.357422 40.285156 C 28.688843 40.354889 28.004565 40.402344 27.291016 40.402344 C 26.644531 40.402344 26.021914 40.365471 25.412109 40.308594 L 25.412109 50 L 33.517578 50 C 39.142578 50 43.283203 48.926571 45.939453 46.779297 C 48.595703 44.632023 49.923828 41.268723 49.923828 36.689453 C 49.923828 32.13391 48.602214 28.787755 45.958984 26.652344 C 44.948178 25.831197 43.714341 25.169238 42.263672 24.662109 z M 25.412109 40.308594 L 25.412109 36.939453 C 23.099 36.57794 21.188155 35.53144 19.695312 33.779297 C 18.116681 31.9121 17.214144 29.470287 16.970703 26.466797 L 12.335938 26.466797 C 12.626268 30.446204 13.963889 33.678709 16.353516 36.162109 C 18.700203 38.587982 21.722877 39.964492 25.412109 40.308594 z M 16.970703 26.466797 L 25.34375 26.466797 L 25.34375 23.464844 L 16.9375 23.464844 C 16.911675 23.890786 16.896484 24.325331 16.896484 24.773438 C 16.896484 25.358829 16.926317 25.91918 16.970703 26.466797 z M 25.412109 36.939453 C 26.013434 37.033433 26.634257 37.091797 27.291016 37.091797 C 28.01543 37.091797 28.701951 37.02645 29.357422 36.912109 L 29.357422 26.386719 L 34.123047 26.386719 C 35.374898 26.386719 36.510129 26.475933 37.552734 26.636719 C 37.606917 26.036054 37.644531 25.420213 37.644531 24.773438 C 37.644531 24.389533 37.626377 24.01998 37.607422 23.652344 C 36.34394 23.507859 34.983448 23.431641 33.517578 23.431641 L 25.412109 23.431641 L 25.412109 36.939453 z M 37.552734 26.636719 C 37.288908 29.561476 36.3922 31.947799 34.84375 33.779297 C 33.413238 35.484518 31.582121 36.524034 29.357422 36.912109 L 29.357422 40.285156 C 32.945677 39.910903 35.894611 38.544976 38.1875 36.162109 C 40.223734 34.035893 41.495873 31.373159 42.007812 28.175781 C 40.833664 27.423776 39.345701 26.913222 37.552734 26.636719 z "
|
||||||
|
id="text4243" /></svg>
|
After Width: | Height: | Size: 4.9 KiB |
|
@ -136,7 +136,7 @@
|
||||||
'include_actions=' + actions,
|
'include_actions=' + actions,
|
||||||
'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'),
|
'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'),
|
||||||
'require_online=true',
|
'require_online=true',
|
||||||
'protocol=' + encodeURIComponent(location.protocolVersion()),
|
'protocol=' + encodeURIComponent(Window.protocolSignature()),
|
||||||
'per_page=' + count
|
'per_page=' + count
|
||||||
];
|
];
|
||||||
var url = Account.metaverseServerURL + '/api/v1/user_stories?' + options.join('&');
|
var url = Account.metaverseServerURL + '/api/v1/user_stories?' + options.join('&');
|
||||||
|
|
|
@ -163,46 +163,31 @@ class MyTestWindow : public TestWindow {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool needsSparseRectification(const uvec2& size);
|
extern uvec2 rectifySize(const uvec2& size);
|
||||||
extern uvec2 rectifyToSparseSize(const uvec2& size);
|
|
||||||
|
|
||||||
void testSparseRectify() {
|
void testSparseRectify() {
|
||||||
std::vector<std::pair<uvec2, bool>> NEEDS_SPARSE_TESTS {{
|
std::vector<std::pair<uvec2, uvec2>> SPARSE_SIZE_TESTS {
|
||||||
// Already sparse
|
// Already sparse
|
||||||
{ {1024, 1024 }, false },
|
{ {1024, 1024 }, { 1024, 1024 } },
|
||||||
{ { 128, 128 }, false },
|
{ { 128, 128 }, { 128, 128 } },
|
||||||
// Too small in one dimension
|
// Too small in one dimension
|
||||||
{ { 127, 127 }, false },
|
{ { 127, 127 }, { 128, 128 } },
|
||||||
{ { 1, 1 }, false },
|
{ { 1, 1 }, { 1, 1 } },
|
||||||
{ { 1000, 1 }, false },
|
{ { 1000, 1 }, { 1024, 1 } },
|
||||||
{ { 1024, 1 }, false },
|
{ { 1024, 1 }, { 1024, 1 } },
|
||||||
{ { 100, 100 }, false },
|
{ { 100, 100 }, { 128, 128 } },
|
||||||
// needs rectification
|
{ { 57, 510 }, { 64, 512 } },
|
||||||
{ { 1000, 1000 }, true },
|
|
||||||
{ { 1024, 1000 }, true },
|
|
||||||
} };
|
|
||||||
|
|
||||||
for (const auto& test : NEEDS_SPARSE_TESTS) {
|
|
||||||
const auto& size = test.first;
|
|
||||||
const auto& expected = test.second;
|
|
||||||
auto result = needsSparseRectification(size);
|
|
||||||
Q_ASSERT(expected == result);
|
|
||||||
result = needsSparseRectification(uvec2(size.y, size.x));
|
|
||||||
Q_ASSERT(expected == result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<uvec2, uvec2>> SPARSE_SIZE_TESTS { {
|
|
||||||
// needs rectification
|
// needs rectification
|
||||||
{ { 1000, 1000 }, { 1024, 1024 } },
|
{ { 1000, 1000 }, { 1024, 1024 } },
|
||||||
{ { 1024, 1000 }, { 1024, 1024 } },
|
{ { 1024, 1000 }, { 1024, 1024 } },
|
||||||
} };
|
};
|
||||||
|
|
||||||
for (const auto& test : SPARSE_SIZE_TESTS) {
|
for (const auto& test : SPARSE_SIZE_TESTS) {
|
||||||
const auto& size = test.first;
|
const auto& size = test.first;
|
||||||
const auto& expected = test.second;
|
const auto& expected = test.second;
|
||||||
auto result = rectifyToSparseSize(size);
|
auto result = rectifySize(size);
|
||||||
Q_ASSERT(expected == result);
|
Q_ASSERT(expected == result);
|
||||||
result = rectifyToSparseSize(uvec2(size.y, size.x));
|
result = rectifySize(uvec2(size.y, size.x));
|
||||||
Q_ASSERT(expected == uvec2(result.y, result.x));
|
Q_ASSERT(expected == uvec2(result.y, result.x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,41 @@
|
||||||
set(TARGET_NAME auto-tester)
|
set (TARGET_NAME auto-tester)
|
||||||
project(${TARGET_NAME})
|
project(${TARGET_NAME})
|
||||||
|
|
||||||
# Automatically run UIC and MOC. This replaces the older WRAP macros
|
# Automatically run UIC and MOC. This replaces the older WRAP macros
|
||||||
SET(CMAKE_AUTOUIC ON)
|
SET (CMAKE_AUTOUIC ON)
|
||||||
SET(CMAKE_AUTOMOC ON)
|
SET (CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
setup_hifi_project(Core Widgets)
|
setup_hifi_project (Core Widgets)
|
||||||
link_hifi_libraries()
|
link_hifi_libraries ()
|
||||||
|
|
||||||
# FIX: Qt was built with -reduce-relocations
|
# FIX: Qt was built with -reduce-relocations
|
||||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
SET (CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Qt includes
|
# Qt includes
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
include_directories(${Qt5Core_INCLUDE_DIRS})
|
include_directories (${Qt5Core_INCLUDE_DIRS})
|
||||||
include_directories(${Qt5Widgets_INCLUDE_DIRS})
|
include_directories (${Qt5Widgets_INCLUDE_DIRS})
|
||||||
|
|
||||||
set(QT_LIBRARIES Qt5::Core Qt5::Widgets)
|
set (QT_LIBRARIES Qt5::Core Qt5::Widgets)
|
||||||
|
|
||||||
# Find all sources files
|
|
||||||
file (GLOB_RECURSE SOURCES src/*.cpp)
|
|
||||||
file (GLOB_RECURSE HEADERS src/*.h)
|
|
||||||
file (GLOB_RECURSE UIS src/ui/*.ui)
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# Do not show Console
|
# Do not show Console
|
||||||
set_property(TARGET auto-tester PROPERTY WIN32_EXECUTABLE true)
|
set_property (TARGET auto-tester PROPERTY WIN32_EXECUTABLE true)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(PROJECT_NAME ${SOURCES} ${HEADERS} ${UIS})
|
target_zlib()
|
||||||
|
add_dependency_external_projects (quazip)
|
||||||
|
find_package (QuaZip REQUIRED)
|
||||||
|
target_include_directories( ${TARGET_NAME} SYSTEM PUBLIC ${QUAZIP_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES})
|
||||||
|
|
||||||
target_link_libraries(PROJECT_NAME ${QT_LIBRARIES})
|
package_libraries_for_deployment()
|
||||||
|
|
||||||
# Copy required dll's.
|
|
||||||
add_custom_command(TARGET auto-tester POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Core> $<TARGET_FILE_DIR:auto-tester>
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Gui> $<TARGET_FILE_DIR:auto-tester>
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Widgets> $<TARGET_FILE_DIR:auto-tester>
|
|
||||||
)
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
add_paths_to_fixup_libs (${QUAZIP_DLL_PATH})
|
||||||
|
|
||||||
find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH)
|
find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH)
|
||||||
|
|
||||||
if (NOT WINDEPLOYQT_COMMAND)
|
if (NOT WINDEPLOYQT_COMMAND)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#include "ImageComparer.h"
|
#include "ImageComparer.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -26,11 +27,6 @@ double ImageComparer::compareImages(QImage resultImage, QImage expectedImage) co
|
||||||
const double c1 = pow((K1 * L), 2);
|
const double c1 = pow((K1 * L), 2);
|
||||||
const double c2 = pow((K2 * L), 2);
|
const double c2 = pow((K2 * L), 2);
|
||||||
|
|
||||||
// Coefficients for luminosity calculation
|
|
||||||
const double R_Y = 0.212655f;
|
|
||||||
const double G_Y = 0.715158f;
|
|
||||||
const double B_Y = 0.072187f;
|
|
||||||
|
|
||||||
// First go over all full 8x8 blocks
|
// First go over all full 8x8 blocks
|
||||||
// This is done in 3 loops
|
// This is done in 3 loops
|
||||||
// 1) Read the pixels into a linear array (an optimization)
|
// 1) Read the pixels into a linear array (an optimization)
|
||||||
|
@ -116,4 +112,4 @@ double ImageComparer::compareImages(QImage resultImage, QImage expectedImage) co
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssim / windowCounter;
|
return ssim / windowCounter;
|
||||||
};
|
};
|
|
@ -13,18 +13,62 @@
|
||||||
#include <QtCore/QTextStream>
|
#include <QtCore/QTextStream>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
|
|
||||||
|
#include <quazip5/quazip.h>
|
||||||
|
#include <quazip5/JlCompress.h>
|
||||||
|
|
||||||
Test::Test() {
|
Test::Test() {
|
||||||
snapshotFilenameFormat = QRegularExpression("hifi-snap-by-.+-on-\\d\\d\\d\\d-\\d\\d-\\d\\d_\\d\\d-\\d\\d-\\d\\d.jpg");
|
snapshotFilenameFormat = QRegularExpression("hifi-snap-by-.*-on-\\d\\d\\d\\d-\\d\\d-\\d\\d_\\d\\d-\\d\\d-\\d\\d.jpg");
|
||||||
|
|
||||||
expectedImageFilenameFormat = QRegularExpression("ExpectedImage_\\d+.jpg");
|
expectedImageFilenameFormat = QRegularExpression("ExpectedImage_\\d+.jpg");
|
||||||
|
|
||||||
mismatchWindow.setModal(true);
|
mismatchWindow.setModal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Test::compareImageLists(QStringList expectedImages, QStringList resultImages) {
|
bool Test::createTestResultsFolderPathIfNeeded(QString directory) {
|
||||||
|
// The test results folder is located in the root of the tests (i.e. for recursive test evaluation)
|
||||||
|
if (testResultsFolderPath == "") {
|
||||||
|
testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER;
|
||||||
|
QDir testResultsFolder(testResultsFolderPath);
|
||||||
|
|
||||||
|
if (testResultsFolder.exists()) {
|
||||||
|
testResultsFolder.removeRecursively();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new test results folder
|
||||||
|
return QDir().mkdir(testResultsFolderPath);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Test::zipAndDeleteTestResultsFolder() {
|
||||||
|
QString zippedResultsFileName { testResultsFolderPath + ".zip" };
|
||||||
|
QFileInfo fileInfo(zippedResultsFileName);
|
||||||
|
if (!fileInfo.exists()) {
|
||||||
|
QFile::remove(zippedResultsFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir testResultsFolder(testResultsFolderPath);
|
||||||
|
if (!testResultsFolder.isEmpty()) {
|
||||||
|
JlCompress::compressDir(testResultsFolderPath + ".zip", testResultsFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
testResultsFolder.removeRecursively();
|
||||||
|
|
||||||
|
//In all cases, for the next evaluation
|
||||||
|
testResultsFolderPath = "";
|
||||||
|
index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Test::compareImageLists(QStringList expectedImages, QStringList resultImages, QString testDirectory, bool interactiveMode, QProgressBar* progressBar) {
|
||||||
|
progressBar->setMinimum(0);
|
||||||
|
progressBar->setMaximum(expectedImages.length() - 1);
|
||||||
|
progressBar->setValue(0);
|
||||||
|
progressBar->setVisible(true);
|
||||||
|
|
||||||
// Loop over both lists and compare each pair of images
|
// Loop over both lists and compare each pair of images
|
||||||
// Quit loop if user has aborted due to a failed test.
|
// Quit loop if user has aborted due to a failed test.
|
||||||
const double THRESHOLD{ 0.999 };
|
const double THRESHOLD { 0.999 };
|
||||||
bool success{ true };
|
bool success{ true };
|
||||||
bool keepOn{ true };
|
bool keepOn{ true };
|
||||||
for (int i = 0; keepOn && i < expectedImages.length(); ++i) {
|
for (int i = 0; keepOn && i < expectedImages.length(); ++i) {
|
||||||
|
@ -45,42 +89,107 @@ bool Test::compareImageLists(QStringList expectedImages, QStringList resultImage
|
||||||
}
|
}
|
||||||
|
|
||||||
if (similarityIndex < THRESHOLD) {
|
if (similarityIndex < THRESHOLD) {
|
||||||
mismatchWindow.setTestFailure(TestFailure{
|
TestFailure testFailure = TestFailure{
|
||||||
(float)similarityIndex,
|
(float)similarityIndex,
|
||||||
expectedImages[i].left(expectedImages[i].lastIndexOf("/") + 1), // path to the test (including trailing /)
|
expectedImages[i].left(expectedImages[i].lastIndexOf("/") + 1), // path to the test (including trailing /)
|
||||||
QFileInfo(expectedImages[i].toStdString().c_str()).fileName(), // filename of expected image
|
QFileInfo(expectedImages[i].toStdString().c_str()).fileName(), // filename of expected image
|
||||||
QFileInfo(resultImages[i].toStdString().c_str()).fileName() // filename of result image
|
QFileInfo(resultImages[i].toStdString().c_str()).fileName() // filename of result image
|
||||||
});
|
};
|
||||||
|
|
||||||
mismatchWindow.exec();
|
mismatchWindow.setTestFailure(testFailure);
|
||||||
|
|
||||||
switch (mismatchWindow.getUserResponse()) {
|
if (!interactiveMode) {
|
||||||
case USER_RESPONSE_PASS:
|
appendTestResultsToFile(testResultsFolderPath, testFailure, mismatchWindow.getComparisonImage());
|
||||||
break;
|
success = false;
|
||||||
case USE_RESPONSE_FAIL:
|
} else {
|
||||||
success = false;
|
mismatchWindow.exec();
|
||||||
break;
|
|
||||||
case USER_RESPONSE_ABORT:
|
switch (mismatchWindow.getUserResponse()) {
|
||||||
keepOn = false;
|
case USER_RESPONSE_PASS:
|
||||||
success = false;
|
break;
|
||||||
break;
|
case USE_RESPONSE_FAIL:
|
||||||
default:
|
appendTestResultsToFile(testResultsFolderPath, testFailure, mismatchWindow.getComparisonImage());
|
||||||
assert(false);
|
success = false;
|
||||||
break;
|
break;
|
||||||
|
case USER_RESPONSE_ABORT:
|
||||||
|
keepOn = false;
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progressBar->setValue(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progressBar->setVisible(false);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::evaluateTests() {
|
void Test::appendTestResultsToFile(QString testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) {
|
||||||
|
if (!QDir().exists(testResultsFolderPath)) {
|
||||||
|
messageBox.critical(0, "Internal error", "Folder " + testResultsFolderPath + " not found");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) };
|
||||||
|
if (!QDir().mkdir(failureFolderPath)) {
|
||||||
|
messageBox.critical(0, "Internal error", "Failed to create folder " + failureFolderPath);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
|
||||||
|
QFile descriptionFile(failureFolderPath + "/" + TEST_RESULTS_FILENAME);
|
||||||
|
if (!descriptionFile.open(QIODevice::ReadWrite)) {
|
||||||
|
messageBox.critical(0, "Internal error", "Failed to create file " + TEST_RESULTS_FILENAME);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create text file describing the failure
|
||||||
|
QTextStream stream(&descriptionFile);
|
||||||
|
stream << "Test failed in folder " << testFailure._pathname.left(testFailure._pathname.length() - 1) << endl; // remove trailing '/'
|
||||||
|
stream << "Expected image was " << testFailure._expectedImageFilename << endl;
|
||||||
|
stream << "Actual image was " << testFailure._actualImageFilename << endl;
|
||||||
|
stream << "Similarity index was " << testFailure._error << endl;
|
||||||
|
|
||||||
|
descriptionFile.close();
|
||||||
|
|
||||||
|
// Copy expected and actual images, and save the difference image
|
||||||
|
QString sourceFile;
|
||||||
|
QString destinationFile;
|
||||||
|
|
||||||
|
sourceFile = testFailure._pathname + testFailure._expectedImageFilename;
|
||||||
|
destinationFile = failureFolderPath + "/" + "Expected Image.jpg";
|
||||||
|
if (!QFile::copy(sourceFile, destinationFile)) {
|
||||||
|
messageBox.critical(0, "Internal error", "Failed to copy " + sourceFile + " to " + destinationFile);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceFile = testFailure._pathname + testFailure._actualImageFilename;
|
||||||
|
destinationFile = failureFolderPath + "/" + "Actual Image.jpg";
|
||||||
|
if (!QFile::copy(sourceFile, destinationFile)) {
|
||||||
|
messageBox.critical(0, "Internal error", "Failed to copy " + sourceFile + " to " + destinationFile);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
comparisonImage.save(failureFolderPath + "/" + "Difference Image.jpg");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Test::evaluateTests(bool interactiveMode, QProgressBar* progressBar) {
|
||||||
// Get list of JPEG images in folder, sorted by name
|
// Get list of JPEG images in folder, sorted by name
|
||||||
QString pathToImageDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly);
|
QString pathToImageDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly);
|
||||||
if (pathToImageDirectory == "") {
|
if (pathToImageDirectory == "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leave if test results folder could not be created
|
||||||
|
if (!createTestResultsFolderPathIfNeeded(pathToImageDirectory)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList sortedImageFilenames = createListOfAllJPEGimagesInDirectory(pathToImageDirectory);
|
QStringList sortedImageFilenames = createListOfAllJPEGimagesInDirectory(pathToImageDirectory);
|
||||||
|
|
||||||
// Separate images into two lists. The first is the expected images, the second is the test results
|
// Separate images into two lists. The first is the expected images, the second is the test results
|
||||||
|
@ -107,36 +216,57 @@ void Test::evaluateTests() {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = compareImageLists(expectedImages, resultImages);
|
bool success = compareImageLists(expectedImages, resultImages, pathToImageDirectory, interactiveMode, progressBar);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
messageBox.information(0, "Success", "All images are as expected");
|
messageBox.information(0, "Success", "All images are as expected");
|
||||||
} else {
|
} else {
|
||||||
messageBox.information(0, "Failure", "One or more images are not as expected");
|
messageBox.information(0, "Failure", "One or more images are not as expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zipAndDeleteTestResultsFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Test::isAValidDirectory(QString pathname) {
|
||||||
|
// Only process directories
|
||||||
|
QDir dir(pathname);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore '.', '..' directories
|
||||||
|
if (pathname[pathname.length() - 1] == '.') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two criteria are used to decide if a folder contains valid test results.
|
// Two criteria are used to decide if a folder contains valid test results.
|
||||||
// 1) a 'test'js' file exists in the folder
|
// 1) a 'test'js' file exists in the folder
|
||||||
// 2) the folder has the same number of actual and expected images
|
// 2) the folder has the same number of actual and expected images
|
||||||
void Test::evaluateTestsRecursively() {
|
void Test::evaluateTestsRecursively(bool interactiveMode, QProgressBar* progressBar) {
|
||||||
// Select folder to start recursing from
|
// Select folder to start recursing from
|
||||||
QString topLevelDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder that will contain the top level test script", ".", QFileDialog::ShowDirsOnly);
|
QString topLevelDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder that will contain the top level test script", ".", QFileDialog::ShowDirsOnly);
|
||||||
if (topLevelDirectory == "") {
|
if (topLevelDirectory == "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leave if test results folder could not be created
|
||||||
|
if (!createTestResultsFolderPathIfNeeded(topLevelDirectory)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool success{ true };
|
bool success{ true };
|
||||||
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString directory = it.next();
|
QString directory = it.next();
|
||||||
if (directory[directory.length() - 1] == '.') {
|
|
||||||
// ignore '.', '..' directories
|
if (!isAValidDirectory(directory)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
const QString testPathname{ directory + "/" + TEST_FILENAME };
|
||||||
const QString testPathname{ directory + "/" + testFilename };
|
|
||||||
QFileInfo fileInfo(testPathname);
|
QFileInfo fileInfo(testPathname);
|
||||||
if (!fileInfo.exists()) {
|
if (!fileInfo.exists()) {
|
||||||
// Folder does not contain 'test.js'
|
// Folder does not contain 'test.js'
|
||||||
|
@ -164,7 +294,7 @@ void Test::evaluateTestsRecursively() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set success to false if any test has failed
|
// Set success to false if any test has failed
|
||||||
success &= compareImageLists(expectedImages, resultImages);
|
success &= compareImageLists(expectedImages, resultImages, directory, interactiveMode, progressBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -172,6 +302,8 @@ void Test::evaluateTestsRecursively() {
|
||||||
} else {
|
} else {
|
||||||
messageBox.information(0, "Failure", "One or more images are not as expected");
|
messageBox.information(0, "Failure", "One or more images are not as expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zipAndDeleteTestResultsFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::importTest(QTextStream& textStream, const QString& testPathname, int testNumber) {
|
void Test::importTest(QTextStream& textStream, const QString& testPathname, int testNumber) {
|
||||||
|
@ -191,7 +323,8 @@ void Test::createRecursiveScript() {
|
||||||
if (!allTestsFilename.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
if (!allTestsFilename.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
messageBox.critical(0,
|
messageBox.critical(0,
|
||||||
"Internal Error",
|
"Internal Error",
|
||||||
"Failed to create \"allTests.js\" in directory \"" + topLevelDirectory + "\"");
|
"Failed to create \"allTests.js\" in directory \"" + topLevelDirectory + "\""
|
||||||
|
);
|
||||||
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +339,7 @@ void Test::createRecursiveScript() {
|
||||||
QVector<QString> testPathnames;
|
QVector<QString> testPathnames;
|
||||||
|
|
||||||
// First test if top-level folder has a test.js file
|
// First test if top-level folder has a test.js file
|
||||||
const QString testPathname{ topLevelDirectory + "/" + testFilename };
|
const QString testPathname{ topLevelDirectory + "/" + TEST_FILENAME };
|
||||||
QFileInfo fileInfo(testPathname);
|
QFileInfo fileInfo(testPathname);
|
||||||
if (fileInfo.exists()) {
|
if (fileInfo.exists()) {
|
||||||
// Current folder contains a test
|
// Current folder contains a test
|
||||||
|
@ -219,12 +352,14 @@ void Test::createRecursiveScript() {
|
||||||
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString directory = it.next();
|
QString directory = it.next();
|
||||||
if (directory[directory.length() - 1] == '.') {
|
|
||||||
// ignore '.', '..' directories
|
// Only process directories
|
||||||
|
QDir dir(directory);
|
||||||
|
if (!isAValidDirectory(directory)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString testPathname{ directory + "/" + testFilename };
|
const QString testPathname{ directory + "/" + TEST_FILENAME };
|
||||||
QFileInfo fileInfo(testPathname);
|
QFileInfo fileInfo(testPathname);
|
||||||
if (fileInfo.exists()) {
|
if (fileInfo.exists()) {
|
||||||
// Current folder contains a test
|
// Current folder contains a test
|
||||||
|
@ -264,7 +399,7 @@ void Test::createRecursiveScript() {
|
||||||
// The script produced will look as follows:
|
// The script produced will look as follows:
|
||||||
// if (test1HasNotStarted) {
|
// if (test1HasNotStarted) {
|
||||||
// test1HasNotStarted = false;
|
// test1HasNotStarted = false;
|
||||||
// test1.test();
|
// test1.test("auto");
|
||||||
// print("******started test 1******");
|
// print("******started test 1******");
|
||||||
// }
|
// }
|
||||||
// |
|
// |
|
||||||
|
@ -287,7 +422,7 @@ void Test::createRecursiveScript() {
|
||||||
textStream << tab << tab << "if (test" << i - 1 << ".complete && test" << i << "HasNotStarted) {" << endl;
|
textStream << tab << tab << "if (test" << i - 1 << ".complete && test" << i << "HasNotStarted) {" << endl;
|
||||||
}
|
}
|
||||||
textStream << tab << tab << tab << "test" << i << "HasNotStarted = false;" << endl;
|
textStream << tab << tab << tab << "test" << i << "HasNotStarted = false;" << endl;
|
||||||
textStream << tab << tab << tab << "test" << i << "." << testFunction << "();" << endl;
|
textStream << tab << tab << tab << "test" << i << "." << testFunction << "(\"auto\");" << endl;
|
||||||
textStream << tab << tab << tab << "print(\"******started test " << i << "******\");" << endl;
|
textStream << tab << tab << tab << "print(\"******started test " << i << "******\");" << endl;
|
||||||
|
|
||||||
textStream << tab << tab << "}" << endl << endl;
|
textStream << tab << tab << "}" << endl << endl;
|
||||||
|
@ -366,6 +501,41 @@ void Test::createTest() {
|
||||||
messageBox.information(0, "Success", "Test images have been created");
|
messageBox.information(0, "Success", "Test images have been created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Test::deleteOldSnapshots() {
|
||||||
|
// Select folder to start recursing from
|
||||||
|
QString topLevelDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select root folder for snapshot deletion", ".", QFileDialog::ShowDirsOnly);
|
||||||
|
if (topLevelDirectory == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse over folders
|
||||||
|
QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QString directory = it.next();
|
||||||
|
|
||||||
|
// Only process directories
|
||||||
|
QDir dir(directory);
|
||||||
|
if (!isAValidDirectory(directory)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList sortedImageFilenames = createListOfAllJPEGimagesInDirectory(directory);
|
||||||
|
|
||||||
|
// Delete any file that is a snapshot (NOT the Expected Images)
|
||||||
|
QStringList expectedImages;
|
||||||
|
QStringList resultImages;
|
||||||
|
foreach(QString currentFilename, sortedImageFilenames) {
|
||||||
|
QString fullCurrentFilename = directory + "/" + currentFilename;
|
||||||
|
if (isInSnapshotFilenameFormat(currentFilename)) {
|
||||||
|
if (!QFile::remove(fullCurrentFilename)) {
|
||||||
|
messageBox.critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nSnapshot deletion aborted");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QStringList Test::createListOfAllJPEGimagesInDirectory(QString pathToImageDirectory) {
|
QStringList Test::createListOfAllJPEGimagesInDirectory(QString pathToImageDirectory) {
|
||||||
imageDirectory = QDir(pathToImageDirectory);
|
imageDirectory = QDir(pathToImageDirectory);
|
||||||
QStringList nameFilters;
|
QStringList nameFilters;
|
||||||
|
@ -374,6 +544,7 @@ QStringList Test::createListOfAllJPEGimagesInDirectory(QString pathToImageDirect
|
||||||
return imageDirectory.entryList(nameFilters, QDir::Files, QDir::Name);
|
return imageDirectory.entryList(nameFilters, QDir::Files, QDir::Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use regular expressions to check if files are in specific format
|
||||||
bool Test::isInSnapshotFilenameFormat(QString filename) {
|
bool Test::isInSnapshotFilenameFormat(QString filename) {
|
||||||
return (snapshotFilenameFormat.match(filename).hasMatch());
|
return (snapshotFilenameFormat.match(filename).hasMatch());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//
|
//
|
||||||
// Test.h
|
// Test.h
|
||||||
// zone/ambientLightInheritence
|
|
||||||
//
|
//
|
||||||
// Created by Nissim Hadar on 2 Nov 2017.
|
// Created by Nissim Hadar on 2 Nov 2017.
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
@ -15,6 +14,7 @@
|
||||||
#include <QtWidgets/QFileDialog>
|
#include <QtWidgets/QFileDialog>
|
||||||
#include <QtWidgets/QMessageBox>
|
#include <QtWidgets/QMessageBox>
|
||||||
#include <QtCore/QRegularExpression>
|
#include <QtCore/QRegularExpression>
|
||||||
|
#include <QProgressBar>
|
||||||
|
|
||||||
#include "ImageComparer.h"
|
#include "ImageComparer.h"
|
||||||
#include "ui/MismatchWindow.h"
|
#include "ui/MismatchWindow.h"
|
||||||
|
@ -23,10 +23,13 @@ class Test {
|
||||||
public:
|
public:
|
||||||
Test();
|
Test();
|
||||||
|
|
||||||
void evaluateTests();
|
void evaluateTests(bool interactiveMode, QProgressBar* progressBar);
|
||||||
void evaluateTestsRecursively();
|
void evaluateTestsRecursively(bool interactiveMode, QProgressBar* progressBar);
|
||||||
void createRecursiveScript();
|
void createRecursiveScript();
|
||||||
void createTest();
|
void createTest();
|
||||||
|
void deleteOldSnapshots();
|
||||||
|
|
||||||
|
bool compareImageLists(QStringList expectedImages, QStringList resultImages, QString testDirectory, bool interactiveMode, QProgressBar* progressBar);
|
||||||
|
|
||||||
QStringList createListOfAllJPEGimagesInDirectory(QString pathToImageDirectory);
|
QStringList createListOfAllJPEGimagesInDirectory(QString pathToImageDirectory);
|
||||||
|
|
||||||
|
@ -35,8 +38,17 @@ public:
|
||||||
|
|
||||||
void importTest(QTextStream& textStream, const QString& testPathname, int testNumber);
|
void importTest(QTextStream& textStream, const QString& testPathname, int testNumber);
|
||||||
|
|
||||||
|
void appendTestResultsToFile(QString testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage);
|
||||||
|
|
||||||
|
bool createTestResultsFolderPathIfNeeded(QString directory);
|
||||||
|
void zipAndDeleteTestResultsFolder();
|
||||||
|
|
||||||
|
bool isAValidDirectory(QString pathname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString testFilename{ "test.js" };
|
const QString TEST_FILENAME { "test.js" };
|
||||||
|
const QString TEST_RESULTS_FOLDER { "TestResults" };
|
||||||
|
const QString TEST_RESULTS_FILENAME { "TestResults.txt" };
|
||||||
|
|
||||||
QMessageBox messageBox;
|
QMessageBox messageBox;
|
||||||
|
|
||||||
|
@ -49,7 +61,9 @@ private:
|
||||||
|
|
||||||
ImageComparer imageComparer;
|
ImageComparer imageComparer;
|
||||||
|
|
||||||
bool compareImageLists(QStringList expectedImages, QStringList resultImages);
|
|
||||||
|
QString testResultsFolderPath { "" };
|
||||||
|
int index { 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_test_h
|
#endif // hifi_test_h
|
|
@ -34,4 +34,9 @@ enum UserResponse {
|
||||||
USER_RESPONSE_ABORT
|
USER_RESPONSE_ABORT
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_common_h
|
// Coefficients for luminosity calculation
|
||||||
|
const double R_Y = 0.212655f;
|
||||||
|
const double G_Y = 0.715158f;
|
||||||
|
const double B_Y = 0.072187f;
|
||||||
|
|
||||||
|
#endif // hifi_common_h
|
|
@ -17,4 +17,4 @@ int main(int argc, char *argv[]) {
|
||||||
autoTester.show();
|
autoTester.show();
|
||||||
|
|
||||||
return application.exec();
|
return application.exec();
|
||||||
}
|
}
|
|
@ -12,14 +12,18 @@
|
||||||
|
|
||||||
AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) {
|
AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) {
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
|
|
||||||
|
ui.checkBoxInteractiveMode->setChecked(true);
|
||||||
|
|
||||||
|
ui.progressBar->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTester::on_evaluateTestsButton_clicked() {
|
void AutoTester::on_evaluateTestsButton_clicked() {
|
||||||
test.evaluateTests();
|
test.evaluateTests(ui.checkBoxInteractiveMode->isChecked(), ui.progressBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTester::on_evaluateTestsRecursivelyButton_clicked() {
|
void AutoTester::on_evaluateTestsRecursivelyButton_clicked() {
|
||||||
test.evaluateTestsRecursively();
|
test.evaluateTestsRecursively(ui.checkBoxInteractiveMode->isChecked(), ui.progressBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTester::on_createRecursiveScriptButton_clicked() {
|
void AutoTester::on_createRecursiveScriptButton_clicked() {
|
||||||
|
@ -30,6 +34,10 @@ void AutoTester::on_createTestButton_clicked() {
|
||||||
test.createTest();
|
test.createTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoTester::on_deleteOldSnapshotsButton_clicked() {
|
||||||
|
test.deleteOldSnapshots();
|
||||||
|
}
|
||||||
|
|
||||||
void AutoTester::on_closeButton_clicked() {
|
void AutoTester::on_closeButton_clicked() {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
//
|
//
|
||||||
// AutoTester.h
|
// AutoTester.h
|
||||||
// zone/ambientLightInheritence
|
|
||||||
//
|
//
|
||||||
// Created by Nissim Hadar on 2 Nov 2017.
|
// Created by Nissim Hadar on 2 Nov 2017.
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
@ -22,10 +21,11 @@ public:
|
||||||
AutoTester(QWidget *parent = Q_NULLPTR);
|
AutoTester(QWidget *parent = Q_NULLPTR);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_evaluateTestsButton_clicked();
|
void on_evaluateTestsButton_clicked();
|
||||||
void on_evaluateTestsRecursivelyButton_clicked();
|
void on_evaluateTestsRecursivelyButton_clicked();
|
||||||
void on_createRecursiveScriptButton_clicked();
|
void on_createRecursiveScriptButton_clicked();
|
||||||
void on_createTestButton_clicked();
|
void on_createTestButton_clicked();
|
||||||
|
void on_deleteOldSnapshotsButton_clicked();
|
||||||
void on_closeButton_clicked();
|
void on_closeButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>286</width>
|
<width>607</width>
|
||||||
<height>470</height>
|
<height>395</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -17,9 +17,9 @@
|
||||||
<widget class="QPushButton" name="closeButton">
|
<widget class="QPushButton" name="closeButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>60</x>
|
<x>190</x>
|
||||||
<y>360</y>
|
<y>300</y>
|
||||||
<width>160</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
<widget class="QPushButton" name="createTestButton">
|
<widget class="QPushButton" name="createTestButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>60</x>
|
<x>360</x>
|
||||||
<y>270</y>
|
<y>130</y>
|
||||||
<width>160</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -43,9 +43,9 @@
|
||||||
<widget class="QPushButton" name="evaluateTestsButton">
|
<widget class="QPushButton" name="evaluateTestsButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>60</x>
|
<x>20</x>
|
||||||
<y>20</y>
|
<y>75</y>
|
||||||
<width>160</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -56,9 +56,9 @@
|
||||||
<widget class="QPushButton" name="createRecursiveScriptButton">
|
<widget class="QPushButton" name="createRecursiveScriptButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>60</x>
|
<x>360</x>
|
||||||
<y>210</y>
|
<y>75</y>
|
||||||
<width>160</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -69,9 +69,9 @@
|
||||||
<widget class="QPushButton" name="evaluateTestsRecursivelyButton">
|
<widget class="QPushButton" name="evaluateTestsRecursivelyButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>60</x>
|
<x>20</x>
|
||||||
<y>75</y>
|
<y>130</y>
|
||||||
<width>160</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -79,13 +79,55 @@
|
||||||
<string>Evaluate Tests Recursively</string>
|
<string>Evaluate Tests Recursively</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="checkBoxInteractiveMode">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>23</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>If unchecked, will not show results during evaluation</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Interactive Mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>20</x>
|
||||||
|
<y>190</y>
|
||||||
|
<width>255</width>
|
||||||
|
<height>23</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="deleteOldSnapshotsButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>360</x>
|
||||||
|
<y>240</y>
|
||||||
|
<width>220</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete Old Snapshots</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menuBar">
|
<widget class="QMenuBar" name="menuBar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>286</width>
|
<width>607</width>
|
||||||
<height>21</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -103,4 +145,4 @@
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
|
@ -11,11 +11,48 @@
|
||||||
|
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
MismatchWindow::MismatchWindow(QWidget *parent) : QDialog(parent) {
|
MismatchWindow::MismatchWindow(QWidget *parent) : QDialog(parent) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
expectedImage->setScaledContents(true);
|
expectedImage->setScaledContents(true);
|
||||||
resultImage->setScaledContents(true);
|
resultImage->setScaledContents(true);
|
||||||
|
diffImage->setScaledContents(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap MismatchWindow::computeDiffPixmap(QImage expectedImage, QImage resultImage) {
|
||||||
|
// This is an optimization, as QImage.setPixel() is embarrassingly slow
|
||||||
|
unsigned char* buffer = new unsigned char[expectedImage.height() * expectedImage.width() * 3];
|
||||||
|
|
||||||
|
// loop over each pixel
|
||||||
|
for (int y = 0; y < expectedImage.height(); ++y) {
|
||||||
|
for (int x = 0; x < expectedImage.width(); ++x) {
|
||||||
|
QRgb pixelP = expectedImage.pixel(QPoint(x, y));
|
||||||
|
QRgb pixelQ = resultImage.pixel(QPoint(x, y));
|
||||||
|
|
||||||
|
// Convert to luminance
|
||||||
|
double p = R_Y * qRed(pixelP) + G_Y * qGreen(pixelP) + B_Y * qBlue(pixelP);
|
||||||
|
double q = R_Y * qRed(pixelQ) + G_Y * qGreen(pixelQ) + B_Y * qBlue(pixelQ);
|
||||||
|
|
||||||
|
// The intensity value is modified to increase the brightness of the displayed image
|
||||||
|
double absoluteDifference = fabs(p - q) / 255.0;
|
||||||
|
double modifiedDifference = sqrt(absoluteDifference);
|
||||||
|
|
||||||
|
int difference = (int)(modifiedDifference * 255.0);
|
||||||
|
|
||||||
|
buffer[3 * (x + y * expectedImage.width()) + 0] = difference;
|
||||||
|
buffer[3 * (x + y * expectedImage.width()) + 1] = difference;
|
||||||
|
buffer[3 * (x + y * expectedImage.width()) + 2] = difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage diffImage(buffer, expectedImage.width(), expectedImage.height(), QImage::Format_RGB888);
|
||||||
|
QPixmap resultPixmap = QPixmap::fromImage(diffImage);
|
||||||
|
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
return resultPixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MismatchWindow::setTestFailure(TestFailure testFailure) {
|
void MismatchWindow::setTestFailure(TestFailure testFailure) {
|
||||||
|
@ -24,10 +61,19 @@ void MismatchWindow::setTestFailure(TestFailure testFailure) {
|
||||||
imagePath->setText("Path to test: " + testFailure._pathname);
|
imagePath->setText("Path to test: " + testFailure._pathname);
|
||||||
|
|
||||||
expectedFilename->setText(testFailure._expectedImageFilename);
|
expectedFilename->setText(testFailure._expectedImageFilename);
|
||||||
expectedImage->setPixmap(QPixmap(testFailure._pathname + testFailure._expectedImageFilename));
|
|
||||||
|
|
||||||
resultFilename->setText(testFailure._actualImageFilename);
|
resultFilename->setText(testFailure._actualImageFilename);
|
||||||
resultImage->setPixmap(QPixmap(testFailure._pathname + testFailure._actualImageFilename));
|
|
||||||
|
QPixmap expectedPixmap = QPixmap(testFailure._pathname + testFailure._expectedImageFilename);
|
||||||
|
QPixmap actualPixmap = QPixmap(testFailure._pathname + testFailure._actualImageFilename);
|
||||||
|
|
||||||
|
diffPixmap = computeDiffPixmap(
|
||||||
|
QImage(testFailure._pathname + testFailure._expectedImageFilename),
|
||||||
|
QImage(testFailure._pathname + testFailure._actualImageFilename)
|
||||||
|
);
|
||||||
|
|
||||||
|
expectedImage->setPixmap(expectedPixmap);
|
||||||
|
resultImage->setPixmap(actualPixmap);
|
||||||
|
diffImage->setPixmap(diffPixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MismatchWindow::on_passTestButton_clicked() {
|
void MismatchWindow::on_passTestButton_clicked() {
|
||||||
|
@ -44,3 +90,7 @@ void MismatchWindow::on_abortTestsButton_clicked() {
|
||||||
_userResponse = USER_RESPONSE_ABORT;
|
_userResponse = USER_RESPONSE_ABORT;
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap MismatchWindow::getComparisonImage() {
|
||||||
|
return diffPixmap;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ public:
|
||||||
|
|
||||||
UserResponse getUserResponse() { return _userResponse; }
|
UserResponse getUserResponse() { return _userResponse; }
|
||||||
|
|
||||||
|
QPixmap computeDiffPixmap(QImage expectedImage, QImage resultImage);
|
||||||
|
QPixmap getComparisonImage();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_passTestButton_clicked();
|
void on_passTestButton_clicked();
|
||||||
void on_failTestButton_clicked();
|
void on_failTestButton_clicked();
|
||||||
|
@ -32,7 +35,9 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UserResponse _userResponse{ USER_RESPONSE_INVALID };
|
UserResponse _userResponse{ USER_RESPONSE_INVALID };
|
||||||
|
|
||||||
|
QPixmap diffPixmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_MismatchWindow_h
|
#endif // hifi_MismatchWindow_h
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1585</width>
|
<width>1782</width>
|
||||||
<height>694</height>
|
<height>942</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -16,10 +16,10 @@
|
||||||
<widget class="QLabel" name="expectedImage">
|
<widget class="QLabel" name="expectedImage">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>20</x>
|
<x>10</x>
|
||||||
<y>170</y>
|
<y>25</y>
|
||||||
<width>720</width>
|
<width>800</width>
|
||||||
<height>362</height>
|
<height>450</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -29,28 +29,41 @@
|
||||||
<widget class="QLabel" name="resultImage">
|
<widget class="QLabel" name="resultImage">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>760</x>
|
<x>900</x>
|
||||||
<y>170</y>
|
<y>25</y>
|
||||||
<width>720</width>
|
<width>800</width>
|
||||||
<height>362</height>
|
<height>450</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>result image</string>
|
<string>result image</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QLabel" name="diffImage">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>540</x>
|
||||||
|
<y>480</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>450</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>diff image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<widget class="QLabel" name="resultFilename">
|
<widget class="QLabel" name="resultFilename">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>760</x>
|
<x>60</x>
|
||||||
<y>90</y>
|
<y>660</y>
|
||||||
<width>800</width>
|
<width>480</width>
|
||||||
<height>28</height>
|
<height>28</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>16</pointsize>
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -60,15 +73,15 @@
|
||||||
<widget class="QLabel" name="expectedFilename">
|
<widget class="QLabel" name="expectedFilename">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>40</x>
|
<x>60</x>
|
||||||
<y>90</y>
|
<y>630</y>
|
||||||
<width>700</width>
|
<width>480</width>
|
||||||
<height>28</height>
|
<height>28</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>16</pointsize>
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -78,15 +91,15 @@
|
||||||
<widget class="QLabel" name="imagePath">
|
<widget class="QLabel" name="imagePath">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>40</x>
|
<x>20</x>
|
||||||
<y>30</y>
|
<y>600</y>
|
||||||
<width>1200</width>
|
<width>1200</width>
|
||||||
<height>28</height>
|
<height>28</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>16</pointsize>
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -97,7 +110,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>30</x>
|
<x>30</x>
|
||||||
<y>600</y>
|
<y>790</y>
|
||||||
<width>75</width>
|
<width>75</width>
|
||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -109,8 +122,8 @@
|
||||||
<widget class="QPushButton" name="failTestButton">
|
<widget class="QPushButton" name="failTestButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>330</x>
|
<x>120</x>
|
||||||
<y>600</y>
|
<y>790</y>
|
||||||
<width>75</width>
|
<width>75</width>
|
||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -122,36 +135,62 @@
|
||||||
<widget class="QPushButton" name="abortTestsButton">
|
<widget class="QPushButton" name="abortTestsButton">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>630</x>
|
<x>210</x>
|
||||||
<y>600</y>
|
<y>790</y>
|
||||||
<width>75</width>
|
<width>121</width>
|
||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Abort Tests</string>
|
<string>Abort current test</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QLabel" name="errorLabel">
|
<widget class="QLabel" name="errorLabel">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>810</x>
|
<x>30</x>
|
||||||
<y>600</y>
|
<y>850</y>
|
||||||
<width>720</width>
|
<width>500</width>
|
||||||
<height>28</height>
|
<height>28</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>16</pointsize>
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>similarity</string>
|
<string>similarity</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>5</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Expected Image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>930</x>
|
||||||
|
<y>5</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Actual Image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
|
@ -195,9 +195,9 @@ void DomainBaker::enumerateEntities() {
|
||||||
auto filename = modelURL.fileName();
|
auto filename = modelURL.fileName();
|
||||||
auto baseName = filename.left(filename.lastIndexOf('.'));
|
auto baseName = filename.left(filename.lastIndexOf('.'));
|
||||||
auto subDirName = "/" + baseName;
|
auto subDirName = "/" + baseName;
|
||||||
int i = 0;
|
int i = 1;
|
||||||
while (QDir(_contentOutputPath + subDirName).exists()) {
|
while (QDir(_contentOutputPath + subDirName).exists()) {
|
||||||
subDirName = "/" + baseName + "-" + i++;
|
subDirName = "/" + baseName + "-" + QString::number(i++);
|
||||||
}
|
}
|
||||||
QSharedPointer<FBXBaker> baker {
|
QSharedPointer<FBXBaker> baker {
|
||||||
new FBXBaker(modelURL, []() -> QThread* {
|
new FBXBaker(modelURL, []() -> QThread* {
|
||||||
|
|
|
@ -133,7 +133,7 @@ var DEBUG_INFO = {
|
||||||
Reticle: {
|
Reticle: {
|
||||||
supportsScale: 'scale' in Reticle,
|
supportsScale: 'scale' in Reticle,
|
||||||
},
|
},
|
||||||
protocolVersion: location.protocolVersion,
|
protocolVersion: Window.protocolSignature(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var globalState = {
|
var globalState = {
|
||||||
|
|
|
@ -52,7 +52,7 @@ function CustomSettingsApp(options) {
|
||||||
|
|
||||||
this.extraParams = Object.assign(options.extraParams || {}, {
|
this.extraParams = Object.assign(options.extraParams || {}, {
|
||||||
customSettingsVersion: CustomSettingsApp.version+'',
|
customSettingsVersion: CustomSettingsApp.version+'',
|
||||||
protocolVersion: location.protocolVersion && location.protocolVersion()
|
protocolVersion: Window.protocolSignature && Window.protocolSignature()
|
||||||
});
|
});
|
||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
|
|
Loading…
Reference in a new issue