mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into controller-dispatcher-1
This commit is contained in:
commit
d78262f2f5
18 changed files with 241 additions and 158 deletions
|
@ -19,6 +19,7 @@ Flickable {
|
|||
|
||||
signal newViewRequestedCallback(var request)
|
||||
signal loadingChangedCallback(var loadRequest)
|
||||
pressDelay: 300
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
|
@ -167,4 +168,11 @@ Flickable {
|
|||
playing: visible
|
||||
z: 10000
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: {
|
||||
flick.flick(0, wheel.angleDelta.y*10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,12 +40,20 @@ Rectangle {
|
|||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.getKeyFilePathIfExists();
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +211,7 @@ Rectangle {
|
|||
commerce.getLoginStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HifiWallet.NeedsLogIn {
|
||||
id: needsLogIn;
|
||||
visible: root.activeView === "needsLogIn";
|
||||
|
@ -239,7 +247,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// "WALLET NOT SET UP" START
|
||||
//
|
||||
|
@ -250,7 +258,7 @@ Rectangle {
|
|||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
||||
|
||||
RalewayRegular {
|
||||
id: notSetUpText;
|
||||
text: "<b>Your wallet isn't set up.</b><br><br>Set up your Wallet (no credit card necessary) to claim your <b>free HFC</b> " +
|
||||
|
@ -281,7 +289,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 24;
|
||||
|
||||
|
||||
// "Cancel" button
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton;
|
||||
|
|
|
@ -35,12 +35,20 @@ Rectangle {
|
|||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.getKeyFilePathIfExists();
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +182,7 @@ Rectangle {
|
|||
commerce.getLoginStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HifiWallet.NeedsLogIn {
|
||||
id: needsLogIn;
|
||||
visible: root.activeView === "needsLogIn";
|
||||
|
@ -210,7 +218,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// "WALLET NOT SET UP" START
|
||||
//
|
||||
|
@ -221,7 +229,7 @@ Rectangle {
|
|||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
||||
|
||||
RalewayRegular {
|
||||
id: notSetUpText;
|
||||
text: "<b>Your wallet isn't set up.</b><br><br>Set up your Wallet (no credit card necessary) to claim your <b>free HFC</b> " +
|
||||
|
@ -252,7 +260,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 24;
|
||||
|
||||
|
||||
// "Cancel" button
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton;
|
||||
|
@ -309,7 +317,7 @@ Rectangle {
|
|||
anchors.topMargin: 8;
|
||||
anchors.bottom: actionButtonsContainer.top;
|
||||
anchors.bottomMargin: 8;
|
||||
|
||||
|
||||
//
|
||||
// FILTER BAR START
|
||||
//
|
||||
|
@ -383,7 +391,7 @@ Rectangle {
|
|||
itemHref: root_file_url;
|
||||
anchors.topMargin: 12;
|
||||
anchors.bottomMargin: 12;
|
||||
|
||||
|
||||
Connections {
|
||||
onSendToPurchases: {
|
||||
if (msg.method === 'purchases_itemInfoClicked') {
|
||||
|
@ -402,7 +410,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width;
|
||||
|
||||
|
||||
// Explanitory text
|
||||
RalewayRegular {
|
||||
id: haventPurchasedYet;
|
||||
|
|
|
@ -31,6 +31,13 @@
|
|||
#include <openssl/evp.h>
|
||||
#include <openssl/aes.h>
|
||||
|
||||
// I know, right? But per https://www.openssl.org/docs/faq.html
|
||||
// this avoids OPENSSL_Uplink(00007FF847238000,08): no OPENSSL_Applink
|
||||
// at runtime.
|
||||
#ifdef Q_OS_WIN
|
||||
#include <openssl/applink.c>
|
||||
#endif
|
||||
|
||||
static const char* KEY_FILE = "hifikey";
|
||||
static const char* IMAGE_FILE = "hifi_image"; // eventually this will live in keyfile
|
||||
|
||||
|
|
|
@ -144,25 +144,33 @@ int main(int argc, const char* argv[]) {
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
// FIXME this method of checking the OpenGL version screws up the `QOpenGLContext::globalShareContext()` value, which in turn
|
||||
// leads to crashes when creating the real OpenGL instance. Disabling for now until we come up with a better way of checking
|
||||
// the GL version on the system without resorting to creating a full Qt application
|
||||
#if 0
|
||||
// Check OpenGL version.
|
||||
// This is done separately from the main Application so that start-up and shut-down logic within the main Application is
|
||||
// not made more complicated than it already is.
|
||||
bool override = false;
|
||||
bool overrideGLCheck = false;
|
||||
|
||||
QJsonObject glData;
|
||||
{
|
||||
OpenGLVersionChecker openGLVersionChecker(argc, const_cast<char**>(argv));
|
||||
bool valid = true;
|
||||
glData = openGLVersionChecker.checkVersion(valid, override);
|
||||
glData = openGLVersionChecker.checkVersion(valid, overrideGLCheck);
|
||||
if (!valid) {
|
||||
if (override) {
|
||||
if (overrideGLCheck) {
|
||||
auto glVersion = glData["version"].toString();
|
||||
qCDebug(interfaceapp, "Running on insufficient OpenGL version: %s.", glVersion.toStdString().c_str());
|
||||
qCWarning(interfaceapp, "Running on insufficient OpenGL version: %s.", glVersion.toStdString().c_str());
|
||||
} else {
|
||||
qCDebug(interfaceapp, "Early exit due to OpenGL version.");
|
||||
qCWarning(interfaceapp, "Early exit due to OpenGL version.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Debug option to demonstrate that the client's local time does not
|
||||
// need to be in sync with any other network node. This forces clock
|
||||
|
@ -223,8 +231,9 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
Application app(argcExtended, const_cast<char**>(argvExtended.data()), startupTime, runningMarkerExisted);
|
||||
|
||||
#if 0
|
||||
// If we failed the OpenGLVersion check, log it.
|
||||
if (override) {
|
||||
if (overrideGLcheck) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
if (accountManager->isLoggedIn()) {
|
||||
UserActivityLogger::getInstance().insufficientGLVersion(glData);
|
||||
|
@ -238,6 +247,8 @@ int main(int argc, const char* argv[]) {
|
|||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Setup local server
|
||||
QLocalServer server { &app };
|
||||
|
|
|
@ -91,7 +91,12 @@ void entitiesScriptEngineDeleter(ScriptEngine* engine) {
|
|||
};
|
||||
|
||||
// Wait for the scripting thread from the thread pool to avoid hanging the main thread
|
||||
QThreadPool::globalInstance()->start(new WaitRunnable(engine));
|
||||
auto threadPool = QThreadPool::globalInstance();
|
||||
if (threadPool) {
|
||||
threadPool->start(new WaitRunnable(engine));
|
||||
} else {
|
||||
delete engine;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::resetEntitiesScriptEngine() {
|
||||
|
|
|
@ -91,20 +91,27 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||
}
|
||||
}
|
||||
if (_particleProperties != newParticleProperties) {
|
||||
|
||||
if (resultWithReadLock<bool>([&]{ return _particleProperties != newParticleProperties; })) {
|
||||
_timeUntilNextEmit = 0;
|
||||
_particleProperties = newParticleProperties;
|
||||
withWriteLock([&]{
|
||||
_particleProperties = newParticleProperties;
|
||||
});
|
||||
}
|
||||
_emitting = entity->getIsEmitting();
|
||||
|
||||
if (_particleProperties.textures.isEmpty()) {
|
||||
bool hasTexture = resultWithReadLock<bool>([&]{ return _particleProperties.textures.isEmpty(); });
|
||||
if (hasTexture) {
|
||||
if (_networkTexture) {
|
||||
withWriteLock([&] {
|
||||
_networkTexture.reset();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures)) {
|
||||
bool textureNeedsUpdate = resultWithReadLock<bool>([&]{
|
||||
return !_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures);
|
||||
});
|
||||
if (textureNeedsUpdate) {
|
||||
withWriteLock([&] {
|
||||
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
||||
});
|
||||
|
@ -115,15 +122,17 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
// Fill in Uniforms structure
|
||||
ParticleUniforms particleUniforms;
|
||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||
particleUniforms.color.start = _particleProperties.getColorStart();
|
||||
particleUniforms.color.middle = _particleProperties.getColorMiddle();
|
||||
particleUniforms.color.finish = _particleProperties.getColorFinish();
|
||||
particleUniforms.color.spread = _particleProperties.getColorSpread();
|
||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||
withReadLock([&]{
|
||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||
particleUniforms.color.start = _particleProperties.getColorStart();
|
||||
particleUniforms.color.middle = _particleProperties.getColorMiddle();
|
||||
particleUniforms.color.finish = _particleProperties.getColorFinish();
|
||||
particleUniforms.color.spread = _particleProperties.getColorSpread();
|
||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||
});
|
||||
// Update particle uniforms
|
||||
memcpy(&_uniformBuffer.edit<ParticleUniforms>(), &particleUniforms, sizeof(ParticleUniforms));
|
||||
}
|
||||
|
@ -146,35 +155,26 @@ Item::Bound ParticleEffectEntityRenderer::getBound() {
|
|||
|
||||
static const size_t VERTEX_PER_PARTICLE = 4;
|
||||
|
||||
bool ParticleEffectEntityRenderer::emitting() const {
|
||||
return (
|
||||
_emitting &&
|
||||
_particleProperties.emission.rate > 0.0f &&
|
||||
_particleProperties.lifespan > 0.0f &&
|
||||
_particleProperties.polar.start <= _particleProperties.polar.finish
|
||||
);
|
||||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::createParticle(uint64_t now) {
|
||||
ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties) {
|
||||
CpuParticle particle;
|
||||
|
||||
const auto& accelerationSpread = _particleProperties.emission.acceleration.spread;
|
||||
const auto& azimuthStart = _particleProperties.azimuth.start;
|
||||
const auto& azimuthFinish = _particleProperties.azimuth.finish;
|
||||
const auto& emitDimensions = _particleProperties.emission.dimensions;
|
||||
const auto& emitAcceleration = _particleProperties.emission.acceleration.target;
|
||||
auto emitOrientation = _particleProperties.emission.orientation;
|
||||
const auto& emitRadiusStart = glm::max(_particleProperties.radiusStart, EPSILON); // Avoid math complications at center
|
||||
const auto& emitSpeed = _particleProperties.emission.speed.target;
|
||||
const auto& speedSpread = _particleProperties.emission.speed.spread;
|
||||
const auto& polarStart = _particleProperties.polar.start;
|
||||
const auto& polarFinish = _particleProperties.polar.finish;
|
||||
const auto& accelerationSpread = particleProperties.emission.acceleration.spread;
|
||||
const auto& azimuthStart = particleProperties.azimuth.start;
|
||||
const auto& azimuthFinish = particleProperties.azimuth.finish;
|
||||
const auto& emitDimensions = particleProperties.emission.dimensions;
|
||||
const auto& emitAcceleration = particleProperties.emission.acceleration.target;
|
||||
auto emitOrientation = particleProperties.emission.orientation;
|
||||
const auto& emitRadiusStart = glm::max(particleProperties.radiusStart, EPSILON); // Avoid math complications at center
|
||||
const auto& emitSpeed = particleProperties.emission.speed.target;
|
||||
const auto& speedSpread = particleProperties.emission.speed.spread;
|
||||
const auto& polarStart = particleProperties.polar.start;
|
||||
const auto& polarFinish = particleProperties.polar.finish;
|
||||
|
||||
particle.seed = randFloatInRange(-1.0f, 1.0f);
|
||||
particle.expiration = now + (uint64_t)(_particleProperties.lifespan * USECS_PER_SECOND);
|
||||
if (_particleProperties.emission.shouldTrail) {
|
||||
particle.position = _modelTransform.getTranslation();
|
||||
emitOrientation = _modelTransform.getRotation() * emitOrientation;
|
||||
particle.expiration = now + (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND);
|
||||
if (particleProperties.emission.shouldTrail) {
|
||||
particle.position = baseTransform.getTranslation();
|
||||
emitOrientation = baseTransform.getRotation() * emitOrientation;
|
||||
}
|
||||
|
||||
// Position, velocity, and acceleration
|
||||
|
@ -232,7 +232,7 @@ void ParticleEffectEntityRenderer::createParticle(uint64_t now) {
|
|||
particle.acceleration = emitAcceleration + randFloatInRange(-1.0f, 1.0f) * accelerationSpread;
|
||||
}
|
||||
|
||||
_cpuParticles.push_back(particle);
|
||||
return particle;
|
||||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::stepSimulation() {
|
||||
|
@ -244,14 +244,19 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
const auto now = usecTimestampNow();
|
||||
const auto interval = std::min<uint64_t>(USECS_PER_SECOND / 60, now - _lastSimulated);
|
||||
_lastSimulated = now;
|
||||
|
||||
particle::Properties particleProperties;
|
||||
withReadLock([&]{
|
||||
particleProperties = _particleProperties;
|
||||
});
|
||||
|
||||
if (emitting()) {
|
||||
uint64_t emitInterval = (uint64_t)(USECS_PER_SECOND / _particleProperties.emission.rate);
|
||||
if (interval >= _timeUntilNextEmit) {
|
||||
if (_emitting && particleProperties.emitting()) {
|
||||
uint64_t emitInterval = particleProperties.emitIntervalUsecs();
|
||||
if (emitInterval > 0 && interval >= _timeUntilNextEmit) {
|
||||
auto timeRemaining = interval;
|
||||
while (timeRemaining > _timeUntilNextEmit) {
|
||||
// emit particle
|
||||
createParticle(now);
|
||||
_cpuParticles.push_back(createParticle(now, _modelTransform, particleProperties));
|
||||
_timeUntilNextEmit = emitInterval;
|
||||
if (emitInterval < timeRemaining) {
|
||||
timeRemaining -= emitInterval;
|
||||
|
@ -263,7 +268,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
}
|
||||
|
||||
// Kill any particles that have expired or are over the max size
|
||||
while (_cpuParticles.size() > _particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
|
||||
while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
|
||||
_cpuParticles.pop_front();
|
||||
}
|
||||
|
||||
|
|
|
@ -93,9 +93,8 @@ private:
|
|||
};
|
||||
|
||||
|
||||
void createParticle(uint64_t now);
|
||||
static CpuParticle createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties);
|
||||
void stepSimulation();
|
||||
bool emitting() const;
|
||||
|
||||
particle::Properties _particleProperties;
|
||||
CpuParticles _cpuParticles;
|
||||
|
|
|
@ -30,14 +30,11 @@ TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) :
|
|||
|
||||
}
|
||||
|
||||
|
||||
void TextEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
|
||||
TextEntityRenderer::~TextEntityRenderer() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (_geometryID && geometryCache) {
|
||||
geometryCache->releaseID(_geometryID);
|
||||
}
|
||||
delete _textRenderer;
|
||||
_textRenderer = nullptr;
|
||||
}
|
||||
|
||||
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
|
|
|
@ -24,14 +24,13 @@ class TextEntityRenderer : public TypedEntityRenderer<TextEntityItem> {
|
|||
using Pointer = std::shared_ptr<TextEntityRenderer>;
|
||||
public:
|
||||
TextEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
~TextEntityRenderer();
|
||||
private:
|
||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
int _geometryID{ 0 };
|
||||
TextRenderer3D* _textRenderer;
|
||||
std::shared_ptr<TextRenderer3D> _textRenderer;
|
||||
bool _faceCamera;
|
||||
glm::vec3 _dimensions;
|
||||
glm::vec3 _textColor;
|
||||
|
|
|
@ -104,7 +104,7 @@ bool operator!=(const Properties& a, const Properties& b) {
|
|||
return !(a == b);
|
||||
}
|
||||
|
||||
bool particle::Properties::valid() const {
|
||||
bool Properties::valid() const {
|
||||
if (glm::any(glm::isnan(emission.orientation))) {
|
||||
qCWarning(entities) << "Bad particle data";
|
||||
return false;
|
||||
|
@ -133,6 +133,19 @@ bool particle::Properties::valid() const {
|
|||
(radius.gradient.spread == glm::clamp(radius.gradient.spread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS));
|
||||
}
|
||||
|
||||
bool Properties::emitting() const {
|
||||
return emission.rate > 0.0f && lifespan > 0.0f && polar.start <= polar.finish;
|
||||
|
||||
}
|
||||
|
||||
uint64_t Properties::emitIntervalUsecs() const {
|
||||
if (emission.rate > 0.0f) {
|
||||
return (uint64_t)(USECS_PER_SECOND / emission.rate);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
|
|
|
@ -160,7 +160,9 @@ namespace particle {
|
|||
Properties() {};
|
||||
Properties(const Properties& other) { *this = other; }
|
||||
bool valid() const;
|
||||
|
||||
bool emitting() const;
|
||||
uint64_t emitIntervalUsecs() const;
|
||||
|
||||
Properties& operator =(const Properties& other) {
|
||||
color = other.color;
|
||||
alpha = other.alpha;
|
||||
|
|
|
@ -40,8 +40,11 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
|||
|
||||
int glVersionToInteger(QString glVersion) {
|
||||
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||
int majorNumber = versionParts[0].toInt();
|
||||
int minorNumber = versionParts[1].toInt();
|
||||
int majorNumber = 0, minorNumber = 0;
|
||||
if (versionParts.size() >= 2) {
|
||||
majorNumber = versionParts[0].toInt();
|
||||
minorNumber = versionParts[1].toInt();
|
||||
}
|
||||
return (majorNumber << 16) | minorNumber;
|
||||
}
|
||||
|
||||
|
|
|
@ -467,12 +467,14 @@ void GLVariableAllocationSupport::updateMemoryPressure() {
|
|||
_demoteQueue = WorkQueue();
|
||||
|
||||
// Populate the existing textures into the queue
|
||||
for (const auto& texture : strongTextures) {
|
||||
// Race conditions can still leave nulls in the list, so we need to check
|
||||
if (!texture) {
|
||||
continue;
|
||||
if (_memoryPressureState != MemoryPressureState::Idle) {
|
||||
for (const auto& texture : strongTextures) {
|
||||
// Race conditions can still leave nulls in the list, so we need to check
|
||||
if (!texture) {
|
||||
continue;
|
||||
}
|
||||
addToWorkQueue(texture);
|
||||
}
|
||||
addToWorkQueue(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ float Interpolate::simpleNonLinearBlend(float fraction) {
|
|||
}
|
||||
|
||||
float Interpolate::calculateFadeRatio(quint64 start) {
|
||||
const float FADE_TIME = 1.0f;
|
||||
const float FADE_TIME = 0.5f;
|
||||
float t = 2.0f * std::min(((float)(usecTimestampNow() - start)) / ((float)(FADE_TIME * USECS_PER_SECOND)), 1.0f);
|
||||
float fadeRatio = (t < 1.0f) ? 0.5f * powf(2.0f, 10.0f * (t - 1.0f)) : 0.5f * (-powf(2.0f, -10.0f * (t - 1.0f)) + 2.0f);
|
||||
|
||||
|
|
|
@ -528,6 +528,12 @@ void OffscreenQmlSurface::create() {
|
|||
|
||||
connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, &OffscreenQmlSurface::onFocusObjectChanged);
|
||||
|
||||
// acquireEngine interrogates the GL context, so we need to have the context current here
|
||||
if (!_canvas->makeCurrent()) {
|
||||
qFatal("Failed to make context current for QML Renderer");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a QML engine.
|
||||
auto qmlEngine = acquireEngine(_quickWindow);
|
||||
|
||||
|
@ -540,11 +546,6 @@ void OffscreenQmlSurface::create() {
|
|||
// FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper
|
||||
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
||||
_qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(this, _qmlContext));
|
||||
|
||||
if (!_canvas->makeCurrent()) {
|
||||
qWarning("Failed to make context current for QML Renderer");
|
||||
return;
|
||||
}
|
||||
_renderControl->initialize(_canvas->getContext());
|
||||
|
||||
// When Quick says there is a need to render, we will not render immediately. Instead,
|
||||
|
@ -639,7 +640,7 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
|||
_qmlContext->setBaseUrl(baseUrl);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
||||
}
|
||||
|
@ -659,28 +660,28 @@ void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std
|
|||
auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous);
|
||||
if (qmlComponent->isLoading()) {
|
||||
connect(qmlComponent, &QQmlComponent::statusChanged, this,
|
||||
[this, qmlComponent, targetContext, f](QQmlComponent::Status) {
|
||||
finishQmlLoad(qmlComponent, targetContext, f);
|
||||
[this, qmlComponent, targetContext, onQmlLoadedCallback](QQmlComponent::Status) {
|
||||
finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
finishQmlLoad(qmlComponent, targetContext, f);
|
||||
finishQmlLoad(qmlComponent, targetContext, onQmlLoadedCallback);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
load(qmlSource, true, f);
|
||||
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
load(qmlSource, true, onQmlLoadedCallback);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
load(qmlSource, false, f);
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
load(qmlSource, false, onQmlLoadedCallback);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::clearCache() {
|
||||
_qmlContext->engine()->clearComponentCache();
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback) {
|
||||
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
||||
if (qmlComponent->isError()) {
|
||||
for (const auto& error : qmlComponent->errors()) {
|
||||
|
@ -690,7 +691,6 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
QObject* newObject = qmlComponent->beginCreate(qmlContext);
|
||||
if (qmlComponent->isError()) {
|
||||
for (const auto& error : qmlComponent->errors()) {
|
||||
|
@ -704,7 +704,20 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
}
|
||||
|
||||
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
f(qmlContext, newObject);
|
||||
|
||||
// All quick items should be focusable
|
||||
QQuickItem* newItem = qobject_cast<QQuickItem*>(newObject);
|
||||
if (newItem) {
|
||||
// Make sure we make items focusable (critical for
|
||||
// supporting keyboard shortcuts)
|
||||
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
||||
}
|
||||
|
||||
// Make sure we will call callback for this codepath
|
||||
// Call this before qmlComponent->completeCreate() otherwise ghost window appears
|
||||
if (newItem && _rootItem) {
|
||||
onQmlLoadedCallback(qmlContext, newObject);
|
||||
}
|
||||
|
||||
QObject* eventBridge = qmlContext->contextProperty("eventBridge").value<QObject*>();
|
||||
if (qmlContext != _qmlContext && eventBridge && eventBridge != this) {
|
||||
|
@ -716,15 +729,6 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
qmlComponent->completeCreate();
|
||||
qmlComponent->deleteLater();
|
||||
|
||||
|
||||
// All quick items should be focusable
|
||||
QQuickItem* newItem = qobject_cast<QQuickItem*>(newObject);
|
||||
if (newItem) {
|
||||
// Make sure we make items focusable (critical for
|
||||
// supporting keyboard shortcuts)
|
||||
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
||||
}
|
||||
|
||||
// If we already have a root, just set a couple of flags and the ancestry
|
||||
if (newItem && _rootItem) {
|
||||
// Allow child windows to be destroyed from JS
|
||||
|
@ -747,6 +751,8 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
|||
_rootItem = newItem;
|
||||
_rootItem->setParentItem(_quickWindow->contentItem());
|
||||
_rootItem->setSize(_quickWindow->renderTargetSize());
|
||||
// Call this callback after rootitem is set, otherwise VrMenu wont work
|
||||
onQmlLoadedCallback(qmlContext, newObject);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::updateQuick() {
|
||||
|
|
|
@ -50,11 +50,11 @@ public:
|
|||
void resize(const QSize& size, bool forceResize = false);
|
||||
QSize size() const;
|
||||
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
||||
return load(QUrl(qmlSourceFile), f);
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback = [](QQmlContext*, QObject*) {}) {
|
||||
return load(QUrl(qmlSourceFile), onQmlLoadedCallback);
|
||||
}
|
||||
void clearCache();
|
||||
void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; }
|
||||
|
@ -120,7 +120,7 @@ protected:
|
|||
private:
|
||||
static QOpenGLContext* getSharedContext();
|
||||
|
||||
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f);
|
||||
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> onQmlLoadedCallback);
|
||||
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
||||
void setupFbo();
|
||||
bool allowNewFrame(uint8_t fps);
|
||||
|
|
|
@ -54,49 +54,6 @@ SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) {
|
|||
}
|
||||
|
||||
void SDL2Manager::init() {
|
||||
loadSettings();
|
||||
|
||||
auto preferences = DependencyManager::get<Preferences>();
|
||||
static const QString SDL2_PLUGIN { "Game Controller" };
|
||||
{
|
||||
auto getter = [this]()->bool { return _isEnabled; };
|
||||
auto setter = [this](bool value) {
|
||||
_isEnabled = value;
|
||||
saveSettings();
|
||||
};
|
||||
auto preference = new CheckPreference(SDL2_PLUGIN, "Enabled", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
if (initSuccess) {
|
||||
int joystickCount = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < joystickCount; i++) {
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(i);
|
||||
|
||||
if (controller) {
|
||||
SDL_JoystickID id = getInstanceId(controller);
|
||||
if (!_openJoysticks.contains(id)) {
|
||||
//Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
Joystick::Pointer joystick = std::make_shared<Joystick>(id, controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(joystick);
|
||||
auto name = SDL_GameControllerName(controller);
|
||||
_subdeviceNames << name;
|
||||
emit joystickAdded(joystick.get());
|
||||
emit subdeviceConnected(getName(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Error initializing SDL2 Manager";
|
||||
}
|
||||
}
|
||||
|
||||
QStringList SDL2Manager::getSubdeviceNames() {
|
||||
|
@ -110,8 +67,61 @@ void SDL2Manager::deinit() {
|
|||
}
|
||||
|
||||
bool SDL2Manager::activate() {
|
||||
|
||||
// FIXME for some reason calling this code in the `init` function triggers a crash
|
||||
// on OSX in PR builds, but not on my local debug build. Attempting a workaround by
|
||||
//
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]{
|
||||
loadSettings();
|
||||
|
||||
auto preferences = DependencyManager::get<Preferences>();
|
||||
static const QString SDL2_PLUGIN { "Game Controller" };
|
||||
{
|
||||
auto getter = [this]()->bool { return _isEnabled; };
|
||||
auto setter = [this](bool value) {
|
||||
_isEnabled = value;
|
||||
saveSettings();
|
||||
};
|
||||
auto preference = new CheckPreference(SDL2_PLUGIN, "Enabled", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
if (initSuccess) {
|
||||
int joystickCount = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < joystickCount; i++) {
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(i);
|
||||
|
||||
if (controller) {
|
||||
SDL_JoystickID id = getInstanceId(controller);
|
||||
if (!_openJoysticks.contains(id)) {
|
||||
//Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller);
|
||||
Joystick::Pointer joystick = std::make_shared<Joystick>(id, controller);
|
||||
_openJoysticks[id] = joystick;
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(joystick);
|
||||
auto name = SDL_GameControllerName(controller);
|
||||
_subdeviceNames << name;
|
||||
emit joystickAdded(joystick.get());
|
||||
emit subdeviceConnected(getName(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
} else {
|
||||
qDebug() << "Error initializing SDL2 Manager";
|
||||
}
|
||||
});
|
||||
|
||||
if (!_isInitialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InputPlugin::activate();
|
||||
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
for (auto joystick : _openJoysticks) {
|
||||
userInputMapper->registerDevice(joystick);
|
||||
|
|
Loading…
Reference in a new issue