mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 20:43:39 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into one
This commit is contained in:
commit
24c5525a90
45 changed files with 836 additions and 536 deletions
|
@ -126,10 +126,12 @@ Item {
|
|||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
z: 10
|
||||
anchors {
|
||||
verticalCenter: usernameField.textFieldLabel.verticalCenter
|
||||
left: usernameField.textFieldLabel.right
|
||||
leftMargin: 10
|
||||
left: usernameField.left
|
||||
top: usernameField.top
|
||||
leftMargin: usernameField.textFieldLabel.contentWidth + 10
|
||||
topMargin: -19
|
||||
}
|
||||
|
||||
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Username?</a>"
|
||||
|
@ -154,10 +156,12 @@ Item {
|
|||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
z: 10
|
||||
anchors {
|
||||
verticalCenter: passwordField.textFieldLabel.verticalCenter
|
||||
left: passwordField.textFieldLabel.right
|
||||
leftMargin: 10
|
||||
left: passwordField.left
|
||||
top: passwordField.top
|
||||
leftMargin: passwordField.textFieldLabel.contentWidth + 10
|
||||
topMargin: -19
|
||||
}
|
||||
|
||||
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Password?</a>"
|
||||
|
@ -168,6 +172,7 @@ Item {
|
|||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = true;
|
||||
|
|
|
@ -11,25 +11,16 @@
|
|||
|
||||
#include "SecondaryCamera.h"
|
||||
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <RenderForwardTask.h>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <gpu/Context.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
||||
|
||||
void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
|
||||
task.addJob<RenderShadowTask>("RenderShadowTask", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
if (!isDeferred) {
|
||||
task.addJob<RenderForwardTask>("Forward", items);
|
||||
} else {
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
||||
}
|
||||
}
|
||||
|
||||
class SecondaryCameraJob { // Changes renderContext for our framebuffer and view.
|
||||
public:
|
||||
using Config = SecondaryCameraJobConfig;
|
||||
|
@ -215,10 +206,10 @@ void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inp
|
|||
const auto cachedArg = task.addJob<SecondaryCameraJob>("SecondaryCamera");
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
if (!isDeferred) {
|
||||
task.addJob<RenderForwardTask>("Forward", items);
|
||||
if (isDeferred) {
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items, false);
|
||||
} else {
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
||||
task.addJob<RenderForwardTask>("Forward", items);
|
||||
}
|
||||
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
||||
}
|
|
@ -12,23 +12,11 @@
|
|||
#pragma once
|
||||
#ifndef hifi_SecondaryCamera_h
|
||||
#define hifi_SecondaryCamera_h
|
||||
|
||||
#include <RenderShadowTask.h>
|
||||
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <RenderForwardTask.h>
|
||||
#include <TextureCache.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
class MainRenderTask {
|
||||
public:
|
||||
using JobModel = render::Task::Model<MainRenderTask>;
|
||||
|
||||
MainRenderTask() {}
|
||||
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true);
|
||||
};
|
||||
|
||||
class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript.
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation
|
||||
|
|
|
@ -127,31 +127,40 @@ EC_KEY* readKeys(const char* filename) {
|
|||
bool Wallet::writeBackupInstructions() {
|
||||
QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html");
|
||||
QString outputFilename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE);
|
||||
QFile inputFile(inputFilename);
|
||||
QFile outputFile(outputFilename);
|
||||
bool retval = false;
|
||||
|
||||
if (QFile::exists(outputFilename) || getKeyFilePath() == "")
|
||||
if (getKeyFilePath() == "")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QFile::copy(inputFilename, outputFilename);
|
||||
|
||||
if (QFile::exists(outputFilename) && outputFile.open(QIODevice::ReadWrite)) {
|
||||
if (QFile::exists(inputFilename) && inputFile.open(QIODevice::ReadOnly)) {
|
||||
if (outputFile.open(QIODevice::ReadWrite)) {
|
||||
// Read the data from the original file, then close it
|
||||
QByteArray fileData = inputFile.readAll();
|
||||
inputFile.close();
|
||||
|
||||
QByteArray fileData = outputFile.readAll();
|
||||
QString text(fileData);
|
||||
// Translate the data from the original file into a QString
|
||||
QString text(fileData);
|
||||
|
||||
text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath());
|
||||
// Replace the necessary string
|
||||
text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath());
|
||||
|
||||
outputFile.seek(0); // go to the beginning of the file
|
||||
outputFile.write(text.toUtf8()); // write the new text back to the file
|
||||
// Write the new text back to the file
|
||||
outputFile.write(text.toUtf8());
|
||||
|
||||
outputFile.close(); // close the file handle.
|
||||
// Close the output file
|
||||
outputFile.close();
|
||||
|
||||
retval = true;
|
||||
qCDebug(commerce) << "wrote html file successfully";
|
||||
retval = true;
|
||||
qCDebug(commerce) << "wrote html file successfully";
|
||||
} else {
|
||||
qCDebug(commerce) << "failed to open output html file" << outputFilename;
|
||||
}
|
||||
} else {
|
||||
qCDebug(commerce) << "failed to open output html file" << outputFilename;
|
||||
qCDebug(commerce) << "failed to open input html file" << inputFilename;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -363,6 +363,14 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
return false;
|
||||
}
|
||||
|
||||
void EntityRenderer::updateModelTransform() {
|
||||
bool success = false;
|
||||
auto newModelTransform = _entity->getTransformToCenter(success);
|
||||
if (success) {
|
||||
_modelTransform = newModelTransform;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
withWriteLock([&] {
|
||||
|
@ -419,4 +427,4 @@ void EntityRenderer::addMaterial(graphics::MaterialLayer material, const std::st
|
|||
void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[parentMaterialName].remove(material);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ protected:
|
|||
virtual void doRender(RenderArgs* args) = 0;
|
||||
|
||||
bool isFading() const { return _isFading; }
|
||||
void updateModelTransform();
|
||||
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
|
||||
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
|
||||
|
||||
|
@ -140,6 +141,7 @@ protected:
|
|||
bool _needsRenderUpdate { false };
|
||||
// Only touched on the rendering thread
|
||||
bool _renderUpdateQueued{ false };
|
||||
Transform _renderTransform;
|
||||
|
||||
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
|
|
|
@ -35,7 +35,6 @@ private:
|
|||
glm::vec2 _materialMappingPos;
|
||||
glm::vec2 _materialMappingScale;
|
||||
float _materialMappingRot;
|
||||
Transform _renderTransform;
|
||||
|
||||
std::shared_ptr<NetworkMaterial> _drawMaterial;
|
||||
};
|
||||
|
|
|
@ -122,6 +122,14 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
|
||||
withWriteLock([&] {
|
||||
updateModelTransform();
|
||||
_renderTransform = getModelTransform();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
|
@ -319,7 +327,10 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
// In trail mode, the particles are created in world space.
|
||||
// so we only set a transform if they're not in trail mode
|
||||
if (!_particleProperties.emission.shouldTrail) {
|
||||
transform = getModelTransform();
|
||||
|
||||
withReadLock([&] {
|
||||
transform = _renderTransform;
|
||||
});
|
||||
transform.setScale(vec3(1));
|
||||
}
|
||||
batch.setModelTransform(transform);
|
||||
|
|
|
@ -97,16 +97,25 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
addMaterial(graphics::MaterialLayer(_material, 0), "0");
|
||||
|
||||
_shape = entity->getShape();
|
||||
_position = entity->getWorldPosition();
|
||||
_dimensions = entity->getScaledDimensions();
|
||||
_orientation = entity->getWorldOrientation();
|
||||
_renderTransform = getModelTransform();
|
||||
});
|
||||
|
||||
if (_shape == entity::Sphere) {
|
||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
|
||||
withWriteLock([&] {
|
||||
auto entity = getEntity();
|
||||
_position = entity->getWorldPosition();
|
||||
_dimensions = entity->getScaledDimensions();
|
||||
_orientation = entity->getWorldOrientation();
|
||||
bool success = false;
|
||||
auto newModelTransform = entity->getTransformToCenter(success);
|
||||
_renderTransform = success ? newModelTransform : getModelTransform();
|
||||
|
||||
_renderTransform.postScale(_dimensions);
|
||||
if (_shape == entity::Sphere) {
|
||||
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
|
||||
_renderTransform.postScale(_dimensions);
|
||||
});;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ private:
|
|||
|
||||
Procedural _procedural;
|
||||
QString _lastUserData;
|
||||
Transform _renderTransform;
|
||||
entity::Shape _shape { entity::Sphere };
|
||||
std::shared_ptr<graphics::Material> _material;
|
||||
glm::vec3 _position;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "GLMHelpers.h"
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
static const int FIXED_FONT_POINT_SIZE = 40;
|
||||
|
@ -64,10 +65,20 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
|
|||
return false;
|
||||
}
|
||||
|
||||
void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
|
||||
withWriteLock([&] {
|
||||
_dimensions = entity->getScaledDimensions();
|
||||
updateModelTransform();
|
||||
_renderTransform = getModelTransform();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_textColor = toGlm(entity->getTextColorX());
|
||||
_backgroundColor = toGlm(entity->getBackgroundColorX());
|
||||
_dimensions = entity->getScaledDimensions();
|
||||
_faceCamera = entity->getFaceCamera();
|
||||
_lineHeight = entity->getLineHeight();
|
||||
_text = entity->getText();
|
||||
|
@ -76,24 +87,28 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
|||
|
||||
void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
||||
|
||||
|
||||
Transform modelTransform;
|
||||
glm::vec3 dimensions;
|
||||
withReadLock([&] {
|
||||
modelTransform = _renderTransform;
|
||||
dimensions = _dimensions;
|
||||
});
|
||||
static const float SLIGHTLY_BEHIND = -0.005f;
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
bool transparent = fadeRatio < 1.0f;
|
||||
glm::vec4 textColor = glm::vec4(_textColor, fadeRatio);
|
||||
glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio);
|
||||
const glm::vec3& dimensions = _dimensions;
|
||||
|
||||
|
||||
// Render background
|
||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
||||
|
||||
|
||||
|
||||
|
||||
// Batch render calls
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
const auto& modelTransform = getModelTransform();
|
||||
auto transformToTopLeft = modelTransform;
|
||||
if (_faceCamera) {
|
||||
//rotate about vertical to face the camera
|
||||
|
@ -105,7 +120,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
}
|
||||
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
|
||||
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
|
||||
|
||||
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (!_geometryID) {
|
||||
|
@ -113,11 +128,11 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
}
|
||||
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, false);
|
||||
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
||||
|
||||
|
||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
||||
transformToTopLeft.setScale(scale); // Scale to have the correct line height
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
|
||||
|
||||
float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
|
||||
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
|
||||
dimensions.y - 2.0f * topMargin);
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
~TextEntityRenderer();
|
||||
private:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
int _geometryID{ 0 };
|
||||
|
@ -39,6 +40,6 @@ private:
|
|||
float _lineHeight;
|
||||
};
|
||||
|
||||
} }
|
||||
} }
|
||||
|
||||
#endif // hifi_RenderableTextEntityItem_h
|
||||
|
|
|
@ -149,8 +149,8 @@ void WebEntityRenderer::onTimeout() {
|
|||
}
|
||||
|
||||
void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
// If the content type has changed, or the old content type was QML, we need to
|
||||
// destroy the existing surface (because surfaces don't support changing the root
|
||||
// If the content type has changed, or the old content type was QML, we need to
|
||||
// destroy the existing surface (because surfaces don't support changing the root
|
||||
// object, so subsequent loads of content just overlap the existing content
|
||||
bool urlChanged = false;
|
||||
{
|
||||
|
@ -187,24 +187,30 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
|||
if (!hasWebSurface() && !buildWebSurface(entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (urlChanged && _contentType == ContentType::HtmlContent) {
|
||||
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl);
|
||||
}
|
||||
|
||||
if (_contextPosition != entity->getWorldPosition()) {
|
||||
// update globalPosition
|
||||
_contextPosition = entity->getWorldPosition();
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
||||
}
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
|
||||
withWriteLock([&] {
|
||||
if (_contextPosition != entity->getWorldPosition()) {
|
||||
// update globalPosition
|
||||
_contextPosition = entity->getWorldPosition();
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
||||
}
|
||||
|
||||
_lastDPI = entity->getDPI();
|
||||
_lastLocked = entity->getLocked();
|
||||
_lastDPI = entity->getDPI();
|
||||
_lastLocked = entity->getLocked();
|
||||
|
||||
glm::vec2 windowSize = getWindowSize(entity);
|
||||
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
||||
_renderTransform = getModelTransform();
|
||||
_renderTransform.postScale(entity->getScaledDimensions());
|
||||
glm::vec2 windowSize = getWindowSize(entity);
|
||||
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
||||
updateModelTransform();
|
||||
_renderTransform = getModelTransform();
|
||||
_renderTransform.postScale(entity->getScaledDimensions());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -297,7 +303,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
|||
|
||||
if (_contentType == ContentType::HtmlContent) {
|
||||
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
||||
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the
|
||||
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the
|
||||
// web entity
|
||||
if (QUrl(_lastSourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
||||
_webSurface->setMaxFps(YOUTUBE_MAX_FPS);
|
||||
|
|
|
@ -68,7 +68,6 @@ private:
|
|||
bool _lastLocked;
|
||||
QTimer _timer;
|
||||
uint64_t _lastRenderTime { 0 };
|
||||
Transform _renderTransform;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -123,7 +123,6 @@ private:
|
|||
bool _pendingSkyboxTexture{ false };
|
||||
|
||||
QString _proceduralUserData;
|
||||
Transform _renderTransform;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -185,6 +185,7 @@ public:
|
|||
/// Dimensions in meters (0.0 - TREE_SCALE)
|
||||
glm::vec3 getScaledDimensions() const;
|
||||
virtual void setScaledDimensions(const glm::vec3& value);
|
||||
virtual glm::vec3 getRaycastDimensions() const { return getScaledDimensions(); }
|
||||
|
||||
inline const glm::vec3 getUnscaledDimensions() const { return _unscaledDimensions; }
|
||||
virtual void setUnscaledDimensions(const glm::vec3& value);
|
||||
|
@ -239,7 +240,7 @@ public:
|
|||
// position, size, and bounds related helpers
|
||||
virtual AACube getMaximumAACube(bool& success) const override;
|
||||
AACube getMinimumAACube(bool& success) const;
|
||||
AABox getAABox(bool& success) const; /// axis aligned bounding box in world-frame (meters)
|
||||
virtual AABox getAABox(bool& success) const; /// axis aligned bounding box in world-frame (meters)
|
||||
|
||||
using SpatiallyNestable::getQueryAACube;
|
||||
virtual AACube getQueryAACube(bool& success) const override;
|
||||
|
|
|
@ -214,7 +214,7 @@ EntityItemID EntityTreeElement::findDetailedRayIntersection(const glm::vec3& ori
|
|||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
||||
glm::vec3 dimensions = entity->getScaledDimensions();
|
||||
glm::vec3 dimensions = entity->getRaycastDimensions();
|
||||
glm::vec3 registrationPoint = entity->getRegistrationPoint();
|
||||
glm::vec3 corner = -(dimensions * registrationPoint);
|
||||
|
||||
|
@ -312,7 +312,7 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc
|
|||
glm::vec3 penetration;
|
||||
if (!success || entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) {
|
||||
|
||||
glm::vec3 dimensions = entity->getScaledDimensions();
|
||||
glm::vec3 dimensions = entity->getRaycastDimensions();
|
||||
|
||||
// FIXME - consider allowing the entity to determine penetration so that
|
||||
// entities could presumably dull actuall hull testing if they wanted to
|
||||
|
|
|
@ -278,6 +278,7 @@ protected:
|
|||
|
||||
struct InputStageState {
|
||||
bool _invalidFormat { true };
|
||||
bool _lastUpdateStereoState{ false };
|
||||
bool _hadColorAttribute{ true };
|
||||
Stream::FormatPointer _format;
|
||||
std::string _formatKey;
|
||||
|
|
|
@ -156,6 +156,14 @@ void GLBackend::do_setIndirectBuffer(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
|
||||
void GLBackend::updateInput() {
|
||||
bool isStereoNow = isStereo();
|
||||
// track stereo state change potentially happening wihtout changing the input format
|
||||
// this is a rare case requesting to invalid the format
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
|
||||
#endif
|
||||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
|
@ -213,7 +221,7 @@ void GLBackend::updateInput() {
|
|||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereo() ? 2 : 1));
|
||||
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereoNow ? 2 : 1));
|
||||
#else
|
||||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,14 @@ void GL41Backend::resetInputStage() {
|
|||
}
|
||||
|
||||
void GL41Backend::updateInput() {
|
||||
bool isStereoNow = isStereo();
|
||||
// track stereo state change potentially happening wihtout changing the input format
|
||||
// this is a rare case requesting to invalid the format
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
|
||||
#endif
|
||||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
|
@ -111,7 +119,7 @@ void GL41Backend::updateInput() {
|
|||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
||||
}
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1));
|
||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereoNow ? 2 : 1));
|
||||
#else
|
||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,14 @@ void GL45Backend::resetInputStage() {
|
|||
}
|
||||
|
||||
void GL45Backend::updateInput() {
|
||||
bool isStereoNow = isStereo();
|
||||
// track stereo state change potentially happening wihtout changing the input format
|
||||
// this is a rare case requesting to invalid the format
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
_input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState);
|
||||
#endif
|
||||
_input._lastUpdateStereoState = isStereoNow;
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
|
@ -84,7 +92,7 @@ void GL45Backend::updateInput() {
|
|||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereo() ? 2 : 1));
|
||||
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereoNow ? 2 : 1));
|
||||
#else
|
||||
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||
#endif
|
||||
|
|
|
@ -472,7 +472,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
const graphics::HazePointer& haze,
|
||||
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
||||
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) {
|
||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource,
|
||||
bool renderShadows) {
|
||||
|
||||
auto args = renderContext->args;
|
||||
auto& batch = (*args->_batch);
|
||||
|
@ -554,7 +555,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
// Check if keylight casts shadows
|
||||
bool keyLightCastShadows { false };
|
||||
|
||||
if (lightStage && lightStage->_currentFrame._sunLights.size()) {
|
||||
if (renderShadows && lightStage && lightStage->_currentFrame._sunLights.size()) {
|
||||
graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front());
|
||||
if (keyLight) {
|
||||
keyLightCastShadows = keyLight->getCastShadows();
|
||||
|
@ -711,11 +712,6 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex
|
|||
}
|
||||
}
|
||||
|
||||
RenderDeferred::RenderDeferred() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RenderDeferred::configure(const Config& config) {
|
||||
}
|
||||
|
||||
|
@ -742,7 +738,7 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs
|
|||
args->_batch = &batch;
|
||||
_gpuTimer->begin(batch);
|
||||
|
||||
setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, haze, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource);
|
||||
setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, haze, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource, _renderShadows);
|
||||
|
||||
lightsJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, lightClusters);
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ public:
|
|||
const graphics::HazePointer& haze,
|
||||
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
||||
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource);
|
||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource,
|
||||
bool renderShadows);
|
||||
};
|
||||
|
||||
class RenderDeferredLocals {
|
||||
|
@ -166,7 +167,8 @@ public:
|
|||
using Config = RenderDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
||||
|
||||
RenderDeferred();
|
||||
RenderDeferred() {}
|
||||
RenderDeferred(bool renderShadows) : _renderShadows(renderShadows) {}
|
||||
|
||||
void configure(const Config& config);
|
||||
|
||||
|
@ -178,6 +180,9 @@ public:
|
|||
|
||||
protected:
|
||||
gpu::RangeTimerPointer _gpuTimer;
|
||||
|
||||
private:
|
||||
bool _renderShadows { false };
|
||||
};
|
||||
|
||||
class DefaultLightingSetup {
|
||||
|
|
|
@ -401,26 +401,34 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
|||
glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 meshFrameDirection = glm::vec3(worldToMeshMatrix * glm::vec4(direction, 0.0f));
|
||||
|
||||
for (auto& triangleSet : _modelSpaceMeshTriangleSets) {
|
||||
float triangleSetDistance = 0.0f;
|
||||
BoxFace triangleSetFace;
|
||||
Triangle triangleSetTriangle;
|
||||
if (triangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
|
||||
int shapeID = 0;
|
||||
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||
int partIndex = 0;
|
||||
for (auto &partTriangleSet : meshTriangleSets) {
|
||||
float triangleSetDistance = 0.0f;
|
||||
BoxFace triangleSetFace;
|
||||
Triangle triangleSetTriangle;
|
||||
if (partTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
|
||||
|
||||
glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
|
||||
glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
|
||||
float worldDistance = glm::distance(origin, worldIntersectionPoint);
|
||||
glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
|
||||
glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
|
||||
float worldDistance = glm::distance(origin, worldIntersectionPoint);
|
||||
|
||||
if (worldDistance < bestDistance) {
|
||||
bestDistance = worldDistance;
|
||||
intersectedSomething = true;
|
||||
face = triangleSetFace;
|
||||
bestModelTriangle = triangleSetTriangle;
|
||||
bestWorldTriangle = triangleSetTriangle * meshToWorldMatrix;
|
||||
extraInfo["worldIntersectionPoint"] = vec3toVariant(worldIntersectionPoint);
|
||||
extraInfo["meshIntersectionPoint"] = vec3toVariant(meshIntersectionPoint);
|
||||
bestSubMeshIndex = subMeshIndex;
|
||||
if (worldDistance < bestDistance) {
|
||||
bestDistance = worldDistance;
|
||||
intersectedSomething = true;
|
||||
face = triangleSetFace;
|
||||
bestModelTriangle = triangleSetTriangle;
|
||||
bestWorldTriangle = triangleSetTriangle * meshToWorldMatrix;
|
||||
extraInfo["worldIntersectionPoint"] = vec3toVariant(worldIntersectionPoint);
|
||||
extraInfo["meshIntersectionPoint"] = vec3toVariant(meshIntersectionPoint);
|
||||
extraInfo["partIndex"] = partIndex;
|
||||
extraInfo["shapeID"] = shapeID;
|
||||
bestSubMeshIndex = subMeshIndex;
|
||||
}
|
||||
}
|
||||
partIndex++;
|
||||
shapeID++;
|
||||
}
|
||||
subMeshIndex++;
|
||||
}
|
||||
|
@ -485,12 +493,14 @@ bool Model::convexHullContains(glm::vec3 point) {
|
|||
glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
|
||||
glm::vec3 meshFramePoint = glm::vec3(worldToMeshMatrix * glm::vec4(point, 1.0f));
|
||||
|
||||
for (const auto& triangleSet : _modelSpaceMeshTriangleSets) {
|
||||
const AABox& box = triangleSet.getBounds();
|
||||
if (box.contains(meshFramePoint)) {
|
||||
if (triangleSet.convexHullContains(meshFramePoint)) {
|
||||
// It's inside this mesh, return true.
|
||||
return true;
|
||||
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||
for (auto &partTriangleSet : meshTriangleSets) {
|
||||
const AABox& box = partTriangleSet.getBounds();
|
||||
if (box.contains(meshFramePoint)) {
|
||||
if (partTriangleSet.convexHullContains(meshFramePoint)) {
|
||||
// It's inside this mesh, return true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -653,9 +663,15 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
|||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
|
||||
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||
const int numberOfParts = mesh.parts.size();
|
||||
auto& meshTriangleSets = _modelSpaceMeshTriangleSets[i];
|
||||
meshTriangleSets.resize(numberOfParts);
|
||||
|
||||
for (int j = 0; j < numberOfParts; j++) {
|
||||
const FBXMeshPart& part = mesh.parts.at(j);
|
||||
|
||||
auto& partTriangleSet = meshTriangleSets[j];
|
||||
|
||||
const int INDICES_PER_TRIANGLE = 3;
|
||||
const int INDICES_PER_QUAD = 4;
|
||||
const int TRIANGLES_PER_QUAD = 2;
|
||||
|
@ -664,7 +680,7 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
|||
int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD;
|
||||
int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE;
|
||||
int totalTriangles = (numberOfQuads * TRIANGLES_PER_QUAD) + numberOfTris;
|
||||
_modelSpaceMeshTriangleSets[i].reserve(totalTriangles);
|
||||
partTriangleSet.reserve(totalTriangles);
|
||||
|
||||
auto meshTransform = geometry.offset * mesh.modelTransform;
|
||||
|
||||
|
@ -686,8 +702,8 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
|||
|
||||
Triangle tri1 = { v0, v1, v3 };
|
||||
Triangle tri2 = { v1, v2, v3 };
|
||||
_modelSpaceMeshTriangleSets[i].insert(tri1);
|
||||
_modelSpaceMeshTriangleSets[i].insert(tri2);
|
||||
partTriangleSet.insert(tri1);
|
||||
partTriangleSet.insert(tri2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +722,7 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
|
|||
glm::vec3 v2 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i2], 1.0f));
|
||||
|
||||
Triangle tri = { v0, v1, v2 };
|
||||
_modelSpaceMeshTriangleSets[i].insert(tri);
|
||||
partTriangleSet.insert(tri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -876,56 +892,58 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
|
|||
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true);
|
||||
|
||||
for (const auto& triangleSet : _modelSpaceMeshTriangleSets) {
|
||||
auto box = triangleSet.getBounds();
|
||||
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||
for (auto &partTriangleSet : meshTriangleSets) {
|
||||
auto box = partTriangleSet.getBounds();
|
||||
|
||||
if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) {
|
||||
_debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) {
|
||||
_debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
QVector<glm::vec3> points;
|
||||
|
||||
glm::vec3 brn = box.getCorner();
|
||||
glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0);
|
||||
glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z);
|
||||
glm::vec3 blf = brn + glm::vec3(box.getDimensions().x, 0, box.getDimensions().z);
|
||||
|
||||
glm::vec3 trn = brn + glm::vec3(0, box.getDimensions().y, 0);
|
||||
glm::vec3 tln = bln + glm::vec3(0, box.getDimensions().y, 0);
|
||||
glm::vec3 trf = brf + glm::vec3(0, box.getDimensions().y, 0);
|
||||
glm::vec3 tlf = blf + glm::vec3(0, box.getDimensions().y, 0);
|
||||
|
||||
points << brn << bln;
|
||||
points << brf << blf;
|
||||
points << brn << brf;
|
||||
points << bln << blf;
|
||||
|
||||
points << trn << tln;
|
||||
points << trf << tlf;
|
||||
points << trn << trf;
|
||||
points << tln << tlf;
|
||||
|
||||
points << brn << trn;
|
||||
points << brf << trf;
|
||||
points << bln << tln;
|
||||
points << blf << tlf;
|
||||
|
||||
glm::vec4 color[] = {
|
||||
{ 0.0f, 1.0f, 0.0f, 1.0f }, // green
|
||||
{ 1.0f, 0.0f, 0.0f, 1.0f }, // red
|
||||
{ 0.0f, 0.0f, 1.0f, 1.0f }, // blue
|
||||
{ 1.0f, 0.0f, 1.0f, 1.0f }, // purple
|
||||
{ 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
|
||||
{ 0.0f, 1.0f, 1.0f, 1.0f }, // cyan
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f }, // white
|
||||
{ 0.0f, 0.5f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 1.0f },
|
||||
{ 0.5f, 0.0f, 0.5f, 1.0f },
|
||||
{ 0.5f, 0.5f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.5f, 0.5f, 1.0f } };
|
||||
|
||||
DependencyManager::get<GeometryCache>()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID);
|
||||
colorNdx++;
|
||||
}
|
||||
QVector<glm::vec3> points;
|
||||
|
||||
glm::vec3 brn = box.getCorner();
|
||||
glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0);
|
||||
glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z);
|
||||
glm::vec3 blf = brn + glm::vec3(box.getDimensions().x, 0, box.getDimensions().z);
|
||||
|
||||
glm::vec3 trn = brn + glm::vec3(0, box.getDimensions().y, 0);
|
||||
glm::vec3 tln = bln + glm::vec3(0, box.getDimensions().y, 0);
|
||||
glm::vec3 trf = brf + glm::vec3(0, box.getDimensions().y, 0);
|
||||
glm::vec3 tlf = blf + glm::vec3(0, box.getDimensions().y, 0);
|
||||
|
||||
points << brn << bln;
|
||||
points << brf << blf;
|
||||
points << brn << brf;
|
||||
points << bln << blf;
|
||||
|
||||
points << trn << tln;
|
||||
points << trf << tlf;
|
||||
points << trn << trf;
|
||||
points << tln << tlf;
|
||||
|
||||
points << brn << trn;
|
||||
points << brf << trf;
|
||||
points << bln << tln;
|
||||
points << blf << tlf;
|
||||
|
||||
glm::vec4 color[] = {
|
||||
{ 0.0f, 1.0f, 0.0f, 1.0f }, // green
|
||||
{ 1.0f, 0.0f, 0.0f, 1.0f }, // red
|
||||
{ 0.0f, 0.0f, 1.0f, 1.0f }, // blue
|
||||
{ 1.0f, 0.0f, 1.0f, 1.0f }, // purple
|
||||
{ 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
|
||||
{ 0.0f, 1.0f, 1.0f, 1.0f }, // cyan
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f }, // white
|
||||
{ 0.0f, 0.5f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 1.0f },
|
||||
{ 0.5f, 0.0f, 0.5f, 1.0f },
|
||||
{ 0.5f, 0.5f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.5f, 0.5f, 1.0f } };
|
||||
|
||||
DependencyManager::get<GeometryCache>()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID);
|
||||
colorNdx++;
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
|
|
@ -423,8 +423,7 @@ protected:
|
|||
bool _overrideModelTransform { false };
|
||||
bool _triangleSetsValid { false };
|
||||
void calculateTriangleSets(const FBXGeometry& geometry);
|
||||
QVector<TriangleSet> _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes
|
||||
|
||||
std::vector<std::vector<TriangleSet>> _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes
|
||||
|
||||
virtual void createRenderItemSet();
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ protected:
|
|||
class DrawOverlay3D {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
|
||||
|
||||
using Config = DrawOverlay3DConfig;
|
||||
using JobModel = render::Job::ModelI<DrawOverlay3D, Inputs, Config>;
|
||||
|
||||
|
@ -73,7 +72,7 @@ public:
|
|||
protected:
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
int _maxDrawn; // initialized by Config
|
||||
bool _opaquePass{ true };
|
||||
bool _opaquePass { true };
|
||||
};
|
||||
|
||||
class CompositeHUD {
|
||||
|
|
|
@ -64,8 +64,8 @@ void RenderDeferredTask::configure(const Config& config)
|
|||
}
|
||||
|
||||
const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, const char* selectionName,
|
||||
const render::Varying& metas,
|
||||
const render::Varying& opaques,
|
||||
const render::Varying& metas,
|
||||
const render::Varying& opaques,
|
||||
const render::Varying& transparents) {
|
||||
const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying();
|
||||
const auto selectedMetas = task.addJob<SelectItems>("MetaSelection", selectMetaInput, selectionName);
|
||||
|
@ -75,7 +75,7 @@ const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, cons
|
|||
return task.addJob<SelectItems>("TransparentSelection", selectItemInput, selectionName);
|
||||
}
|
||||
|
||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output, bool renderShadows) {
|
||||
const auto& items = input.get<Input>();
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
|
||||
|
@ -168,7 +168,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters, hazeModel).asVarying();
|
||||
|
||||
task.addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs);
|
||||
task.addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs, renderShadows);
|
||||
|
||||
|
||||
// Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job
|
||||
|
|
|
@ -126,7 +126,7 @@ public:
|
|||
RenderDeferredTask();
|
||||
|
||||
void configure(const Config& config);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, bool renderShadows);
|
||||
|
||||
private:
|
||||
static const render::Varying addSelectItemJobs(JobModel& task,
|
||||
|
|
|
@ -27,7 +27,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render:
|
|||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
|
||||
if (isDeferred) {
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items, true);
|
||||
} else {
|
||||
task.addJob<RenderForwardTask>("Forward", items);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "AABox.h"
|
||||
|
|
73
scripts/developer/tests/raypickTester.js
Normal file
73
scripts/developer/tests/raypickTester.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
// raypickTester.js
|
||||
//
|
||||
// display intersection details (including material) when hovering over entities/avatars/overlays
|
||||
//
|
||||
|
||||
/* eslint-disable comma-dangle, no-empty, no-magic-numbers */
|
||||
|
||||
var PICK_FILTERS = Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS | Picks.PICK_AVATARS | Picks.PICK_INCLUDE_NONCOLLIDABLE;
|
||||
var HAND_JOINT = '_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND'.replace('RIGHT', MyAvatar.getDominantHand().toUpperCase());
|
||||
var JOINT_NAME = HMD.active ? HAND_JOINT : 'Mouse';
|
||||
var UPDATE_MS = 1000/30;
|
||||
|
||||
// create tect3d overlay to display hover results
|
||||
var overlayID = Overlays.addOverlay('text3d', {
|
||||
text: 'hover',
|
||||
visible: false,
|
||||
backgroundAlpha: 0,
|
||||
isFacingAvatar: true,
|
||||
lineHeight: 0.05,
|
||||
dimensions: Vec3.HALF,
|
||||
});
|
||||
Script.scriptEnding.connect(function() {
|
||||
Overlays.deleteOverlay(overlayID);
|
||||
});
|
||||
|
||||
// create raycast picker
|
||||
var pickID = Picks.createPick(PickType.Ray, {
|
||||
joint: JOINT_NAME,
|
||||
filter: PICK_FILTERS,
|
||||
enabled: true,
|
||||
});
|
||||
var blacklist = [ overlayID ]; // exclude hover text from ray pick results
|
||||
Picks.setIgnoreItems(pickID, blacklist);
|
||||
Script.scriptEnding.connect(function() {
|
||||
Picks.removePick(pickID);
|
||||
});
|
||||
|
||||
// query object materials (using the Graphics.* API)
|
||||
function getSubmeshMaterial(objectID, shapeID) {
|
||||
try {
|
||||
var materialLayers = Graphics.getModel(objectID).materialLayers;
|
||||
var shapeMaterialLayers = materialLayers[shapeID];
|
||||
return shapeMaterialLayers[0].material;
|
||||
} catch (e) {
|
||||
return { name: '<unknown>' };
|
||||
}
|
||||
}
|
||||
|
||||
// refresh hover overlay text based on intersection results
|
||||
function updateOverlay(overlayID, result) {
|
||||
var material = this.getSubmeshMaterial(result.objectID, result.extraInfo.shapeID);
|
||||
var position = Vec3.mix(result.searchRay.origin, result.intersection, 0.5);
|
||||
var extraInfo = result.extraInfo;
|
||||
var text = [
|
||||
'mesh: ' + extraInfo.subMeshName,
|
||||
'materialName: ' + material.name,
|
||||
'type: ' + Entities.getNestableType(result.objectID),
|
||||
'distance: ' + result.distance.toFixed(2)+'m',
|
||||
['submesh: ' + extraInfo.subMeshIndex, 'part: '+extraInfo.partIndex, 'shape: '+extraInfo.shapeID].join(' | '),
|
||||
].filter(Boolean).join('\n');
|
||||
|
||||
Overlays.editOverlay(overlayID, {
|
||||
text: text,
|
||||
position: position,
|
||||
visible: result.intersects,
|
||||
});
|
||||
}
|
||||
|
||||
// monitor for enw results at 30fps
|
||||
Script.setInterval(function() {
|
||||
var result = Picks.getPrevPickResult(pickID);
|
||||
updateOverlay(overlayID, result);
|
||||
}, UPDATE_MS);
|
|
@ -260,7 +260,7 @@ function Grabber() {
|
|||
|
||||
this.mouseRayOverlays = Picks.createPick(PickType.Ray, {
|
||||
joint: "Mouse",
|
||||
filter: Picks.PICK_OVERLAYS,
|
||||
filter: Picks.PICK_OVERLAYS | Picks.PICK_INCLUDE_NONCOLLIDABLE,
|
||||
enabled: true
|
||||
});
|
||||
var tabletItems = getMainTabletIDs();
|
||||
|
@ -270,7 +270,7 @@ function Grabber() {
|
|||
var renderStates = [{name: "grabbed", end: beacon}];
|
||||
this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
|
||||
joint: "Mouse",
|
||||
filter: Picks.PICK_ENTITIES,
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
enabled: true,
|
||||
|
|
|
@ -475,15 +475,16 @@ var toolBar = (function () {
|
|||
var DELETE_ENTITY_TIMER_TIMEOUT = 100;
|
||||
|
||||
function checkDeletedEntityAndUpdate(entityID) {
|
||||
// Allow for multiple entity deletes before updating the entity list.
|
||||
// Allow for multiple entity deletes before updating the entities selected.
|
||||
entitiesToDelete.push(entityID);
|
||||
if (deletedEntityTimer !== null) {
|
||||
Script.clearTimeout(deletedEntityTimer);
|
||||
}
|
||||
deletedEntityTimer = Script.setTimeout(function () {
|
||||
selectionManager.removeEntities(entitiesToDelete);
|
||||
entityListTool.clearEntityList();
|
||||
entityListTool.sendUpdate();
|
||||
if (entitiesToDelete.length > 0) {
|
||||
selectionManager.removeEntities(entitiesToDelete);
|
||||
}
|
||||
entityListTool.removeEntities(entitiesToDelete, selectionManager.selections);
|
||||
entitiesToDelete = [];
|
||||
deletedEntityTimer = null;
|
||||
}, DELETE_ENTITY_TIMER_TIMEOUT);
|
||||
|
@ -2027,12 +2028,8 @@ var PropertiesTool = function (opts) {
|
|||
} else if (data.type === "update") {
|
||||
selectionManager.saveProperties();
|
||||
if (selectionManager.selections.length > 1) {
|
||||
properties = {
|
||||
locked: data.properties.locked,
|
||||
visible: data.properties.visible
|
||||
};
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
Entities.editEntity(selectionManager.selections[i], properties);
|
||||
Entities.editEntity(selectionManager.selections[i], data.properties);
|
||||
}
|
||||
} else if (data.properties) {
|
||||
if (data.properties.dynamic === false) {
|
||||
|
|
|
@ -269,6 +269,9 @@ For usage and examples: colpick.com/plugin
|
|||
},
|
||||
// Show/hide the color picker
|
||||
show = function (ev) {
|
||||
if ($(this).attr('disabled')) {
|
||||
return;
|
||||
}
|
||||
// Prevent the trigger of any direct parent
|
||||
ev.stopPropagation();
|
||||
var cal = $('#' + $(this).data('colpickId'));
|
||||
|
|
|
@ -184,17 +184,27 @@ function loaded() {
|
|||
currentElement.onclick = onRowClicked;
|
||||
currentElement.ondblclick = onRowDoubleClicked;
|
||||
});
|
||||
|
||||
if (refreshEntityListTimer) {
|
||||
clearTimeout(refreshEntityListTimer);
|
||||
}
|
||||
refreshEntityListTimer = setTimeout(refreshEntityListObject, 50);
|
||||
} else {
|
||||
var item = entities[id].item;
|
||||
item.values({ name: name, url: filename, locked: locked, visible: visible });
|
||||
}
|
||||
}
|
||||
|
||||
function removeEntities(deletedIDs) {
|
||||
for (i = 0, length = deletedIDs.length; i < length; i++) {
|
||||
delete entities[deletedIDs[i]];
|
||||
entityList.remove("id", deletedIDs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleRefreshEntityList() {
|
||||
var REFRESH_DELAY = 50;
|
||||
if (refreshEntityListTimer) {
|
||||
clearTimeout(refreshEntityListTimer);
|
||||
}
|
||||
refreshEntityListTimer = setTimeout(refreshEntityListObject, REFRESH_DELAY);
|
||||
}
|
||||
|
||||
function clearEntities() {
|
||||
entities = {};
|
||||
entityList.clear();
|
||||
|
@ -346,7 +356,7 @@ function loaded() {
|
|||
if (notFound) {
|
||||
refreshEntities();
|
||||
}
|
||||
} else if (data.type == "update") {
|
||||
} else if (data.type === "update" && data.selectedIDs !== undefined) {
|
||||
var newEntities = data.entities;
|
||||
if (newEntities && newEntities.length == 0) {
|
||||
elNoEntitiesMessage.style.display = "block";
|
||||
|
@ -365,13 +375,15 @@ function loaded() {
|
|||
newEntities[i].hasScript ? SCRIPT_GLYPH : null);
|
||||
}
|
||||
updateSelectedEntities(data.selectedIDs);
|
||||
scheduleRefreshEntityList();
|
||||
resize();
|
||||
}
|
||||
} else if (data.type === "deleted") {
|
||||
for (i = 0, length = data.ids.length; i < length; i++) {
|
||||
delete entities[data.ids[i]];
|
||||
entityList.remove("id", data.ids[i]);
|
||||
}
|
||||
} else if (data.type === "removeEntities" && data.deletedIDs !== undefined && data.selectedIDs !== undefined) {
|
||||
removeEntities(data.deletedIDs);
|
||||
updateSelectedEntities(data.selectedIDs);
|
||||
scheduleRefreshEntityList();
|
||||
} else if (data.type === "deleted" && data.ids) {
|
||||
removeEntities(data.ids);
|
||||
refreshFooter();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -893,9 +893,9 @@ function loaded() {
|
|||
} else {
|
||||
elServerScriptStatus.innerText = "Not running";
|
||||
}
|
||||
} else if (data.type === "update") {
|
||||
} else if (data.type === "update" && data.selections) {
|
||||
|
||||
if (!data.selections || data.selections.length === 0) {
|
||||
if (data.selections.length === 0) {
|
||||
if (lastEntityID !== null) {
|
||||
if (editor !== null) {
|
||||
saveJSONUserData(true);
|
||||
|
@ -911,7 +911,7 @@ function loaded() {
|
|||
elID.value = "";
|
||||
elPropertiesList.className = '';
|
||||
disableProperties();
|
||||
} else if (data.selections && data.selections.length > 1) {
|
||||
} else if (data.selections.length > 1) {
|
||||
deleteJSONEditor();
|
||||
deleteJSONMaterialEditor();
|
||||
var selections = data.selections;
|
||||
|
|
|
@ -57,6 +57,15 @@ EntityListTool = function(opts) {
|
|||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
};
|
||||
|
||||
that.removeEntities = function (deletedIDs, selectedIDs) {
|
||||
var data = {
|
||||
type: 'removeEntities',
|
||||
deletedIDs: deletedIDs,
|
||||
selectedIDs: selectedIDs
|
||||
};
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
};
|
||||
|
||||
function valueIfDefined(value) {
|
||||
return value !== undefined ? value : "";
|
||||
}
|
||||
|
|
|
@ -13,11 +13,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global SPACE_LOCAL, SelectionManager */
|
||||
/* global SelectionManager, grid, rayPlaneIntersection, rayPlaneIntersection2, pushCommandForSelections,
|
||||
getMainTabletIDs, getControllerWorldLocation */
|
||||
|
||||
SPACE_LOCAL = "local";
|
||||
SPACE_WORLD = "world";
|
||||
HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
|
||||
var SPACE_LOCAL = "local";
|
||||
var SPACE_WORLD = "world";
|
||||
var HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
|
||||
|
||||
Script.include([
|
||||
"./controllers.js",
|
||||
|
@ -84,7 +85,7 @@ SelectionManager = (function() {
|
|||
outlineWidth: 3,
|
||||
isOutlineSmooth: true
|
||||
};
|
||||
//disabling this for now as it is causing rendering issues with the other handle overlays
|
||||
// disabling this for now as it is causing rendering issues with the other handle overlays
|
||||
//Selection.enableListHighlight(HIGHLIGHT_LIST_NAME, editHandleOutlineStyle);
|
||||
|
||||
that.savedProperties = {};
|
||||
|
@ -192,7 +193,7 @@ SelectionManager = (function() {
|
|||
}
|
||||
});
|
||||
return duplicatedEntityIDs;
|
||||
}
|
||||
};
|
||||
|
||||
that._update = function(selectionUpdated) {
|
||||
var properties = null;
|
||||
|
@ -270,11 +271,12 @@ SelectionManager = (function() {
|
|||
|
||||
// Normalize degrees to be in the range (-180, 180)
|
||||
function normalizeDegrees(degrees) {
|
||||
degrees = ((degrees + 180) % 360) - 180;
|
||||
if (degrees <= -180) {
|
||||
degrees += 360;
|
||||
var maxDegrees = 360;
|
||||
var halfMaxDegrees = maxDegrees / 2;
|
||||
degrees = ((degrees + halfMaxDegrees) % maxDegrees) - halfMaxDegrees;
|
||||
if (degrees <= -halfMaxDegrees) {
|
||||
degrees += maxDegrees;
|
||||
}
|
||||
|
||||
return degrees;
|
||||
}
|
||||
|
||||
|
@ -284,14 +286,14 @@ SelectionDisplay = (function() {
|
|||
|
||||
var NEGATE_VECTOR = -1;
|
||||
|
||||
var COLOR_GREEN = { red:31, green:198, blue:166 };
|
||||
var COLOR_BLUE = { red:0, green:147, blue:197 };
|
||||
var COLOR_RED = { red:226, green:51, blue:77 };
|
||||
var COLOR_HOVER = { red:227, green:227, blue:227 };
|
||||
var COLOR_GREEN = { red: 31, green: 198, blue: 166 };
|
||||
var COLOR_BLUE = { red: 0, green: 147, blue: 197 };
|
||||
var COLOR_RED = { red: 226, green: 51, blue: 77 };
|
||||
var COLOR_HOVER = { red: 227, green: 227, blue: 227 };
|
||||
var COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 };
|
||||
var COLOR_SCALE_EDGE = { red:87, green:87, blue:87 };
|
||||
var COLOR_SCALE_CUBE = { red:106, green:106, blue:106 };
|
||||
var COLOR_SCALE_CUBE_SELECTED = { red:18, green:18, blue:18 };
|
||||
var COLOR_SCALE_EDGE = { red: 87, green: 87, blue: 87 };
|
||||
var COLOR_SCALE_CUBE = { red: 106, green: 106, blue: 106 };
|
||||
var COLOR_SCALE_CUBE_SELECTED = { red: 18, green: 18, blue: 18 };
|
||||
|
||||
var TRANSLATE_ARROW_CYLINDER_OFFSET = 0.1;
|
||||
var TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE = 0.005;
|
||||
|
@ -320,41 +322,41 @@ SelectionDisplay = (function() {
|
|||
var STRETCH_PANEL_WIDTH = 0.01;
|
||||
|
||||
var SCALE_CUBE_OFFSET = 0.5;
|
||||
var SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.015;
|
||||
var SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.0125;
|
||||
|
||||
var CLONER_OFFSET = { x:0.9, y:-0.9, z:0.9 };
|
||||
var CLONER_OFFSET = { x: 0.9, y: -0.9, z: 0.9 };
|
||||
|
||||
var CTRL_KEY_CODE = 16777249;
|
||||
|
||||
var TRANSLATE_DIRECTION = {
|
||||
X : 0,
|
||||
Y : 1,
|
||||
Z : 2
|
||||
}
|
||||
X: 0,
|
||||
Y: 1,
|
||||
Z: 2
|
||||
};
|
||||
|
||||
var STRETCH_DIRECTION = {
|
||||
X : 0,
|
||||
Y : 1,
|
||||
Z : 2,
|
||||
ALL : 3
|
||||
}
|
||||
X: 0,
|
||||
Y: 1,
|
||||
Z: 2,
|
||||
ALL: 3
|
||||
};
|
||||
|
||||
var SCALE_DIRECTION = {
|
||||
LBN : 0,
|
||||
RBN : 1,
|
||||
LBF : 2,
|
||||
RBF : 3,
|
||||
LTN : 4,
|
||||
RTN : 5,
|
||||
LTF : 6,
|
||||
RTF : 7
|
||||
}
|
||||
LBN: 0,
|
||||
RBN: 1,
|
||||
LBF: 2,
|
||||
RBF: 3,
|
||||
LTN: 4,
|
||||
RTN: 5,
|
||||
LTF: 6,
|
||||
RTF: 7
|
||||
};
|
||||
|
||||
var ROTATE_DIRECTION = {
|
||||
PITCH : 0,
|
||||
YAW : 1,
|
||||
ROLL : 2
|
||||
}
|
||||
PITCH: 0,
|
||||
YAW: 1,
|
||||
ROLL: 2
|
||||
};
|
||||
|
||||
var spaceMode = SPACE_LOCAL;
|
||||
var overlayNames = [];
|
||||
|
@ -397,16 +399,16 @@ SelectionDisplay = (function() {
|
|||
};
|
||||
var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
||||
var handleTranslateXCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
||||
Overlays.editOverlay(handleTranslateXCone, { color : COLOR_RED });
|
||||
Overlays.editOverlay(handleTranslateXCylinder, { color : COLOR_RED });
|
||||
Overlays.editOverlay(handleTranslateXCone, { color: COLOR_RED });
|
||||
Overlays.editOverlay(handleTranslateXCylinder, { color: COLOR_RED });
|
||||
var handleTranslateYCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
||||
var handleTranslateYCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
||||
Overlays.editOverlay(handleTranslateYCone, { color : COLOR_GREEN });
|
||||
Overlays.editOverlay(handleTranslateYCylinder, { color : COLOR_GREEN });
|
||||
Overlays.editOverlay(handleTranslateYCone, { color: COLOR_GREEN });
|
||||
Overlays.editOverlay(handleTranslateYCylinder, { color: COLOR_GREEN });
|
||||
var handleTranslateZCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
|
||||
var handleTranslateZCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
|
||||
Overlays.editOverlay(handleTranslateZCone, { color : COLOR_BLUE });
|
||||
Overlays.editOverlay(handleTranslateZCylinder, { color : COLOR_BLUE });
|
||||
Overlays.editOverlay(handleTranslateZCone, { color: COLOR_BLUE });
|
||||
Overlays.editOverlay(handleTranslateZCylinder, { color: COLOR_BLUE });
|
||||
|
||||
var handlePropertiesRotateRings = {
|
||||
alpha: 1,
|
||||
|
@ -422,18 +424,18 @@ SelectionDisplay = (function() {
|
|||
};
|
||||
var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
||||
Overlays.editOverlay(handleRotatePitchRing, {
|
||||
color : COLOR_RED,
|
||||
majorTickMarksColor: COLOR_RED,
|
||||
color: COLOR_RED,
|
||||
majorTickMarksColor: COLOR_RED
|
||||
});
|
||||
var handleRotateYawRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
||||
Overlays.editOverlay(handleRotateYawRing, {
|
||||
color : COLOR_GREEN,
|
||||
majorTickMarksColor: COLOR_GREEN,
|
||||
color: COLOR_GREEN,
|
||||
majorTickMarksColor: COLOR_GREEN
|
||||
});
|
||||
var handleRotateRollRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
|
||||
Overlays.editOverlay(handleRotateRollRing, {
|
||||
color : COLOR_BLUE,
|
||||
majorTickMarksColor: COLOR_BLUE,
|
||||
color: COLOR_BLUE,
|
||||
majorTickMarksColor: COLOR_BLUE
|
||||
});
|
||||
|
||||
var handleRotateCurrentRing = Overlays.addOverlay("circle3d", {
|
||||
|
@ -472,11 +474,11 @@ SelectionDisplay = (function() {
|
|||
drawInFront: true
|
||||
};
|
||||
var handleStretchXSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
||||
Overlays.editOverlay(handleStretchXSphere, { color : COLOR_RED });
|
||||
Overlays.editOverlay(handleStretchXSphere, { color: COLOR_RED });
|
||||
var handleStretchYSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
||||
Overlays.editOverlay(handleStretchYSphere, { color : COLOR_GREEN });
|
||||
Overlays.editOverlay(handleStretchYSphere, { color: COLOR_GREEN });
|
||||
var handleStretchZSphere = Overlays.addOverlay("shape", handlePropertiesStretchSpheres);
|
||||
Overlays.editOverlay(handleStretchZSphere, { color : COLOR_BLUE });
|
||||
Overlays.editOverlay(handleStretchZSphere, { color: COLOR_BLUE });
|
||||
|
||||
var handlePropertiesStretchPanel = {
|
||||
shape: "Quad",
|
||||
|
@ -485,13 +487,13 @@ SelectionDisplay = (function() {
|
|||
visible: false,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true
|
||||
}
|
||||
};
|
||||
var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||
Overlays.editOverlay(handleStretchXPanel, { color : COLOR_RED });
|
||||
Overlays.editOverlay(handleStretchXPanel, { color: COLOR_RED });
|
||||
var handleStretchYPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||
Overlays.editOverlay(handleStretchYPanel, { color : COLOR_GREEN });
|
||||
Overlays.editOverlay(handleStretchYPanel, { color: COLOR_GREEN });
|
||||
var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||
Overlays.editOverlay(handleStretchZPanel, { color : COLOR_BLUE });
|
||||
Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE });
|
||||
|
||||
var handlePropertiesScaleCubes = {
|
||||
size: 0.025,
|
||||
|
@ -517,7 +519,7 @@ SelectionDisplay = (function() {
|
|||
ignoreRayIntersection: true,
|
||||
drawInFront: true,
|
||||
lineWidth: 0.2
|
||||
}
|
||||
};
|
||||
var handleScaleTREdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
||||
var handleScaleTLEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
||||
var handleScaleTFEdge = Overlays.addOverlay("line3d", handlePropertiesScaleEdge);
|
||||
|
@ -785,11 +787,11 @@ SelectionDisplay = (function() {
|
|||
};
|
||||
|
||||
that.resetPreviousHandleColor = function() {
|
||||
if (previousHandle != null) {
|
||||
if (previousHandle !== null) {
|
||||
Overlays.editOverlay(previousHandle, { color: previousHandleColor });
|
||||
previousHandle = null;
|
||||
}
|
||||
if (previousHandleHelper != null) {
|
||||
if (previousHandleHelper !== null) {
|
||||
Overlays.editOverlay(previousHandleHelper, { color: previousHandleColor });
|
||||
previousHandleHelper = null;
|
||||
}
|
||||
|
@ -886,7 +888,7 @@ SelectionDisplay = (function() {
|
|||
Overlays.editOverlay(result.overlayID, { color: COLOR_HOVER });
|
||||
previousHandle = result.overlayID;
|
||||
previousHandleHelper = that.getHandleHelper(result.overlayID);
|
||||
if (previousHandleHelper != null) {
|
||||
if (previousHandleHelper !== null) {
|
||||
Overlays.editOverlay(previousHandleHelper, { color: COLOR_HOVER });
|
||||
}
|
||||
previousHandleColor = pickedColor;
|
||||
|
@ -944,7 +946,7 @@ SelectionDisplay = (function() {
|
|||
ctrlPressed = false;
|
||||
that.updateActiveRotateRing();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Triggers notification on specific key driven events
|
||||
that.keyPressEvent = function(key) {
|
||||
|
@ -952,7 +954,7 @@ SelectionDisplay = (function() {
|
|||
ctrlPressed = true;
|
||||
that.updateActiveRotateRing();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these:
|
||||
// Controller.mousePressEvent.connect(that.mousePressEvent);
|
||||
|
@ -994,6 +996,11 @@ SelectionDisplay = (function() {
|
|||
var toCameraDistance = Vec3.length(Vec3.subtract(cameraPosition, position));
|
||||
return toCameraDistance;
|
||||
}
|
||||
|
||||
function usePreviousPickRay(pickRayDirection, previousPickRayDirection, normal) {
|
||||
return (Vec3.dot(pickRayDirection, normal) > 0 && Vec3.dot(previousPickRayDirection, normal) < 0) ||
|
||||
(Vec3.dot(pickRayDirection, normal) < 0 && Vec3.dot(previousPickRayDirection, normal) > 0);
|
||||
}
|
||||
|
||||
// @return string - The mode of the currently active tool;
|
||||
// otherwise, "UNKNOWN" if there's no active tool.
|
||||
|
@ -1014,8 +1021,6 @@ SelectionDisplay = (function() {
|
|||
lastCameraOrientation = Camera.getOrientation();
|
||||
|
||||
if (event !== false) {
|
||||
pickRay = generalComputePickRay(event.x, event.y);
|
||||
|
||||
var wantDebug = false;
|
||||
if (wantDebug) {
|
||||
print("select() with EVENT...... ");
|
||||
|
@ -1041,7 +1046,8 @@ SelectionDisplay = (function() {
|
|||
spaceMode = newSpaceMode;
|
||||
that.updateHandles();
|
||||
} else if (wantDebug) {
|
||||
print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " + spaceMode + " DesiredMode: " + newSpaceMode);
|
||||
print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " +
|
||||
spaceMode + " DesiredMode: " + newSpaceMode);
|
||||
}
|
||||
if (wantDebug) {
|
||||
print("====== SetSpaceMode called. <========");
|
||||
|
@ -1091,7 +1097,8 @@ SelectionDisplay = (function() {
|
|||
}
|
||||
|
||||
if (!handleTools.hasOwnProperty(toolHandle)) {
|
||||
print("WARNING: entitySelectionTool.isActiveTool - Encountered unknown grabberToolHandle: " + toolHandle + ". Tools should be registered via addHandleTool.");
|
||||
print("WARNING: entitySelectionTool.isActiveTool - Encountered unknown grabberToolHandle: " +
|
||||
toolHandle + ". Tools should be registered via addHandleTool.");
|
||||
// EARLY EXIT
|
||||
return false;
|
||||
}
|
||||
|
@ -1121,13 +1128,14 @@ SelectionDisplay = (function() {
|
|||
var rotationInverse = Quat.inverse(rotation);
|
||||
var toCameraDistance = getDistanceToCamera(position);
|
||||
|
||||
var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -90);
|
||||
var rotationDegrees = 90;
|
||||
var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -rotationDegrees);
|
||||
var rotationX = Quat.multiply(rotation, localRotationX);
|
||||
worldRotationX = rotationX;
|
||||
var localRotationY = Quat.fromPitchYawRollDegrees(0, 90, 0);
|
||||
var localRotationY = Quat.fromPitchYawRollDegrees(0, rotationDegrees, 0);
|
||||
var rotationY = Quat.multiply(rotation, localRotationY);
|
||||
worldRotationY = rotationY;
|
||||
var localRotationZ = Quat.fromPitchYawRollDegrees(90, 0, 0);
|
||||
var localRotationZ = Quat.fromPitchYawRollDegrees(rotationDegrees, 0, 0);
|
||||
var rotationZ = Quat.multiply(rotation, localRotationZ);
|
||||
worldRotationZ = rotationZ;
|
||||
|
||||
|
@ -1140,7 +1148,7 @@ SelectionDisplay = (function() {
|
|||
// UPDATE ROTATION RINGS
|
||||
// rotateDimension is used as the base dimension for all overlays
|
||||
var rotateDimension = Math.max(maxHandleDimension, toCameraDistance * ROTATE_RING_CAMERA_DISTANCE_MULTIPLE);
|
||||
var rotateDimensions = { x:rotateDimension, y:rotateDimension, z:rotateDimension };
|
||||
var rotateDimensions = { x: rotateDimension, y: rotateDimension, z: rotateDimension };
|
||||
if (!isActiveTool(handleRotatePitchRing)) {
|
||||
Overlays.editOverlay(handleRotatePitchRing, {
|
||||
position: position,
|
||||
|
@ -1172,16 +1180,16 @@ SelectionDisplay = (function() {
|
|||
var arrowCylinderDimension = rotateDimension * TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE /
|
||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||
var arrowCylinderDimensions = {
|
||||
x:arrowCylinderDimension,
|
||||
y:arrowCylinderDimension * TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE,
|
||||
z:arrowCylinderDimension
|
||||
x: arrowCylinderDimension,
|
||||
y: arrowCylinderDimension * TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE,
|
||||
z: arrowCylinderDimension
|
||||
};
|
||||
var arrowConeDimension = rotateDimension * TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE /
|
||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||
var arrowConeDimensions = { x:arrowConeDimension, y:arrowConeDimension, z:arrowConeDimension };
|
||||
var arrowConeDimensions = { x: arrowConeDimension, y: arrowConeDimension, z: arrowConeDimension };
|
||||
var arrowCylinderOffset = rotateDimension * TRANSLATE_ARROW_CYLINDER_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||
var arrowConeOffset = arrowCylinderDimensions.y * TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE;
|
||||
var cylinderXPosition = { x:arrowCylinderOffset, y:0, z:0 };
|
||||
var cylinderXPosition = { x: arrowCylinderOffset, y: 0, z: 0 };
|
||||
cylinderXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderXPosition));
|
||||
Overlays.editOverlay(handleTranslateXCylinder, {
|
||||
position: cylinderXPosition,
|
||||
|
@ -1195,7 +1203,7 @@ SelectionDisplay = (function() {
|
|||
rotation: rotationX,
|
||||
dimensions: arrowConeDimensions
|
||||
});
|
||||
var cylinderYPosition = { x:0, y:arrowCylinderOffset, z:0 };
|
||||
var cylinderYPosition = { x: 0, y: arrowCylinderOffset, z: 0 };
|
||||
cylinderYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderYPosition));
|
||||
Overlays.editOverlay(handleTranslateYCylinder, {
|
||||
position: cylinderYPosition,
|
||||
|
@ -1209,7 +1217,7 @@ SelectionDisplay = (function() {
|
|||
rotation: rotationY,
|
||||
dimensions: arrowConeDimensions
|
||||
});
|
||||
var cylinderZPosition = { x:0, y:0, z:arrowCylinderOffset };
|
||||
var cylinderZPosition = { x: 0, y: 0, z: arrowCylinderOffset };
|
||||
cylinderZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderZPosition));
|
||||
Overlays.editOverlay(handleTranslateZCylinder, {
|
||||
position: cylinderZPosition,
|
||||
|
@ -1228,61 +1236,73 @@ SelectionDisplay = (function() {
|
|||
var scaleCubeOffsetX = SCALE_CUBE_OFFSET * dimensions.x;
|
||||
var scaleCubeOffsetY = SCALE_CUBE_OFFSET * dimensions.y;
|
||||
var scaleCubeOffsetZ = SCALE_CUBE_OFFSET * dimensions.z;
|
||||
var scaleCubeDimension = rotateDimension * SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE /
|
||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||
var scaleCubeDimensions = { x:scaleCubeDimension, y:scaleCubeDimension, z:scaleCubeDimension };
|
||||
var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY;
|
||||
var scaleLBNCubePosition = { x:-scaleCubeOffsetX, y:-scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
||||
var scaleLBNCubePosition = { x: -scaleCubeOffsetX, y: -scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||
scaleLBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBNCubePosition));
|
||||
var scaleLBNCubeToCamera = getDistanceToCamera(scaleLBNCubePosition);
|
||||
var scaleRBNCubePosition = { x: scaleCubeOffsetX, y: -scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||
scaleRBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBNCubePosition));
|
||||
var scaleRBNCubeToCamera = getDistanceToCamera(scaleRBNCubePosition);
|
||||
var scaleLBFCubePosition = { x: -scaleCubeOffsetX, y: -scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||
scaleLBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBFCubePosition));
|
||||
var scaleLBFCubeToCamera = getDistanceToCamera(scaleLBFCubePosition);
|
||||
var scaleRBFCubePosition = { x: scaleCubeOffsetX, y: -scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||
scaleRBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBFCubePosition));
|
||||
var scaleRBFCubeToCamera = getDistanceToCamera(scaleRBFCubePosition);
|
||||
var scaleLTNCubePosition = { x: -scaleCubeOffsetX, y: scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||
scaleLTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTNCubePosition));
|
||||
var scaleLTNCubeToCamera = getDistanceToCamera(scaleLTNCubePosition);
|
||||
var scaleRTNCubePosition = { x: scaleCubeOffsetX, y: scaleCubeOffsetY, z: -scaleCubeOffsetZ };
|
||||
scaleRTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTNCubePosition));
|
||||
var scaleRTNCubeToCamera = getDistanceToCamera(scaleRTNCubePosition);
|
||||
var scaleLTFCubePosition = { x: -scaleCubeOffsetX, y: scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||
scaleLTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTFCubePosition));
|
||||
var scaleLTFCubeToCamera = getDistanceToCamera(scaleLTFCubePosition);
|
||||
var scaleRTFCubePosition = { x: scaleCubeOffsetX, y: scaleCubeOffsetY, z: scaleCubeOffsetZ };
|
||||
scaleRTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTFCubePosition));
|
||||
var scaleRTFCubeToCamera = getDistanceToCamera(scaleRTFCubePosition);
|
||||
|
||||
var scaleCubeToCamera = Math.min(scaleLBNCubeToCamera, scaleRBNCubeToCamera, scaleLBFCubeToCamera,
|
||||
scaleRBFCubeToCamera, scaleLTNCubeToCamera, scaleRTNCubeToCamera,
|
||||
scaleLTFCubeToCamera, scaleRTFCubeToCamera);
|
||||
var scaleCubeDimension = scaleCubeToCamera * SCALE_CUBE_CAMERA_DISTANCE_MULTIPLE;
|
||||
var scaleCubeDimensions = { x: scaleCubeDimension, y: scaleCubeDimension, z: scaleCubeDimension };
|
||||
|
||||
Overlays.editOverlay(handleScaleLBNCube, {
|
||||
position: scaleLBNCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleRBNCubePosition = { x:scaleCubeOffsetX, y:-scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
||||
scaleRBNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBNCubePosition));
|
||||
Overlays.editOverlay(handleScaleRBNCube, {
|
||||
position: scaleRBNCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleLBFCubePosition = { x:-scaleCubeOffsetX, y:-scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
||||
scaleLBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLBFCubePosition));
|
||||
Overlays.editOverlay(handleScaleLBFCube, {
|
||||
position: scaleLBFCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleRBFCubePosition = { x:scaleCubeOffsetX, y:-scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
||||
scaleRBFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRBFCubePosition));
|
||||
Overlays.editOverlay(handleScaleRBFCube, {
|
||||
position: scaleRBFCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleLTNCubePosition = { x:-scaleCubeOffsetX, y:scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
||||
scaleLTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTNCubePosition));
|
||||
Overlays.editOverlay(handleScaleLTNCube, {
|
||||
position: scaleLTNCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleRTNCubePosition = { x:scaleCubeOffsetX, y:scaleCubeOffsetY, z:-scaleCubeOffsetZ };
|
||||
scaleRTNCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTNCubePosition));
|
||||
Overlays.editOverlay(handleScaleRTNCube, {
|
||||
position: scaleRTNCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleLTFCubePosition = { x:-scaleCubeOffsetX, y:scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
||||
scaleLTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleLTFCubePosition));
|
||||
Overlays.editOverlay(handleScaleLTFCube, {
|
||||
position: scaleLTFCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
dimensions: scaleCubeDimensions
|
||||
});
|
||||
var scaleRTFCubePosition = { x:scaleCubeOffsetX, y:scaleCubeOffsetY, z:scaleCubeOffsetZ };
|
||||
scaleRTFCubePosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, scaleRTFCubePosition));
|
||||
Overlays.editOverlay(handleScaleRTFCube, {
|
||||
position: scaleRTFCubePosition,
|
||||
rotation: scaleCubeRotation,
|
||||
|
@ -1306,21 +1326,21 @@ SelectionDisplay = (function() {
|
|||
// UPDATE STRETCH SPHERES
|
||||
var stretchSphereDimension = rotateDimension * STRETCH_SPHERE_CAMERA_DISTANCE_MULTIPLE /
|
||||
ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||
var stretchSphereDimensions = { x:stretchSphereDimension, y:stretchSphereDimension, z:stretchSphereDimension };
|
||||
var stretchSphereDimensions = { x: stretchSphereDimension, y: stretchSphereDimension, z: stretchSphereDimension };
|
||||
var stretchSphereOffset = rotateDimension * STRETCH_SPHERE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
|
||||
var stretchXPosition = { x:stretchSphereOffset, y:0, z:0 };
|
||||
var stretchXPosition = { x: stretchSphereOffset, y: 0, z: 0 };
|
||||
stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition));
|
||||
Overlays.editOverlay(handleStretchXSphere, {
|
||||
position: stretchXPosition,
|
||||
dimensions: stretchSphereDimensions
|
||||
});
|
||||
var stretchYPosition = { x:0, y:stretchSphereOffset, z:0 };
|
||||
var stretchYPosition = { x: 0, y: stretchSphereOffset, z: 0 };
|
||||
stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition));
|
||||
Overlays.editOverlay(handleStretchYSphere, {
|
||||
position: stretchYPosition,
|
||||
dimensions: stretchSphereDimensions
|
||||
});
|
||||
var stretchZPosition = { x:0, y:0, z:stretchSphereOffset };
|
||||
var stretchZPosition = { x: 0, y: 0, z: stretchSphereOffset };
|
||||
stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition));
|
||||
Overlays.editOverlay(handleStretchZSphere, {
|
||||
position: stretchZPosition,
|
||||
|
@ -1337,27 +1357,29 @@ SelectionDisplay = (function() {
|
|||
stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH;
|
||||
stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z);
|
||||
stretchPanelXDimensions.z = tempY;
|
||||
var stretchPanelXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:dimensions.x / 2, y:0, z:0 }));
|
||||
var stretchPanelXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: dimensions.x / 2, y: 0, z: 0 }));
|
||||
Overlays.editOverlay(handleStretchXPanel, {
|
||||
position: stretchPanelXPosition,
|
||||
rotation: rotationZ,
|
||||
dimensions: stretchPanelXDimensions
|
||||
});
|
||||
var stretchPanelYDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRTFCubePositionRotated);
|
||||
var tempX = Math.abs(stretchPanelYDimensions.x);
|
||||
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
||||
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
||||
stretchPanelYDimensions.z = Math.abs(stretchPanelYDimensions.x);
|
||||
var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:dimensions.y / 2, z:0 }));
|
||||
stretchPanelYDimensions.z = tempX;
|
||||
var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: dimensions.y / 2, z: 0 }));
|
||||
Overlays.editOverlay(handleStretchYPanel, {
|
||||
position: stretchPanelYPosition,
|
||||
rotation: rotationY,
|
||||
dimensions: stretchPanelYDimensions
|
||||
});
|
||||
var stretchPanelZDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRBFCubePositionRotated);
|
||||
tempX = Math.abs(stretchPanelZDimensions.x);
|
||||
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
||||
stretchPanelZDimensions.y = Math.abs(stretchPanelZDimensions.x);
|
||||
stretchPanelZDimensions.y = tempX;
|
||||
stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH;
|
||||
var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:0, z:dimensions.z / 2 }));
|
||||
var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: 0, z: dimensions.z / 2 }));
|
||||
Overlays.editOverlay(handleStretchZPanel, {
|
||||
position: stretchPanelZPosition,
|
||||
rotation: rotationX,
|
||||
|
@ -1390,10 +1412,10 @@ SelectionDisplay = (function() {
|
|||
}
|
||||
|
||||
// UPDATE CLONER (CURRENTLY HIDDEN FOR NOW)
|
||||
var handleClonerOffset = {
|
||||
x:CLONER_OFFSET.x * dimensions.x,
|
||||
y:CLONER_OFFSET.y * dimensions.y,
|
||||
z:CLONER_OFFSET.z * dimensions.z
|
||||
var handleClonerOffset = {
|
||||
x: CLONER_OFFSET.x * dimensions.x,
|
||||
y: CLONER_OFFSET.y * dimensions.y,
|
||||
z: CLONER_OFFSET.z * dimensions.z
|
||||
};
|
||||
var handleClonerPos = Vec3.sum(position, Vec3.multiplyQbyV(rotation, handleClonerOffset));
|
||||
Overlays.editOverlay(handleCloner, {
|
||||
|
@ -1431,9 +1453,9 @@ SelectionDisplay = (function() {
|
|||
!isActiveTool(handleRotateYawRing) &&
|
||||
!isActiveTool(handleRotateRollRing)));
|
||||
|
||||
//keep cloner always hidden for now since you can hold Alt to clone while
|
||||
//translating an entity - we may bring cloner back for HMD only later
|
||||
//that.setHandleClonerVisible(!activeTool || isActiveTool(handleCloner));
|
||||
// keep cloner always hidden for now since you can hold Alt to clone while
|
||||
// translating an entity - we may bring cloner back for HMD only later
|
||||
// that.setHandleClonerVisible(!activeTool || isActiveTool(handleCloner));
|
||||
|
||||
if (wantDebug) {
|
||||
print("====== Update Handles <=======");
|
||||
|
@ -1451,8 +1473,8 @@ SelectionDisplay = (function() {
|
|||
} else if (isActiveTool(handleRotateRollRing)) {
|
||||
activeRotateRing = handleRotateRollRing;
|
||||
}
|
||||
if (activeRotateRing != null) {
|
||||
var tickMarksAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_TICK_MARKS_ANGLE;
|
||||
if (activeRotateRing !== null) {
|
||||
var tickMarksAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_TICK_MARKS_ANGLE;
|
||||
Overlays.editOverlay(activeRotateRing, { majorTickMarksAngle: tickMarksAngle });
|
||||
}
|
||||
};
|
||||
|
@ -1633,7 +1655,7 @@ SelectionDisplay = (function() {
|
|||
},
|
||||
onMove: function(event) {
|
||||
var wantDebug = false;
|
||||
pickRay = generalComputePickRay(event.x, event.y);
|
||||
var pickRay = generalComputePickRay(event.x, event.y);
|
||||
|
||||
var pick = rayPlaneIntersection2(pickRay, translateXZTool.pickPlanePosition, {
|
||||
x: 0,
|
||||
|
@ -1699,7 +1721,8 @@ SelectionDisplay = (function() {
|
|||
}
|
||||
|
||||
constrainMajorOnly = event.isControl;
|
||||
var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(-0.5, SelectionManager.worldDimensions));
|
||||
var negateAndHalve = -0.5;
|
||||
var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(negateAndHalve, SelectionManager.worldDimensions));
|
||||
vector = Vec3.subtract(
|
||||
grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
|
||||
cornerPosition);
|
||||
|
@ -1745,15 +1768,16 @@ SelectionDisplay = (function() {
|
|||
var pickNormal = null;
|
||||
var lastPick = null;
|
||||
var projectionVector = null;
|
||||
var previousPickRay = null;
|
||||
addHandleTool(overlay, {
|
||||
mode: mode,
|
||||
onBegin: function(event, pickRay, pickResult) {
|
||||
if (direction === TRANSLATE_DIRECTION.X) {
|
||||
pickNormal = { x:0, y:1, z:1 };
|
||||
pickNormal = { x: 0, y: 1, z: 1 };
|
||||
} else if (direction === TRANSLATE_DIRECTION.Y) {
|
||||
pickNormal = { x:1, y:0, z:1 };
|
||||
pickNormal = { x: 1, y: 0, z: 1 };
|
||||
} else if (direction === TRANSLATE_DIRECTION.Z) {
|
||||
pickNormal = { x:1, y:1, z:0 };
|
||||
pickNormal = { x: 1, y: 1, z: 0 };
|
||||
}
|
||||
|
||||
var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
|
||||
|
@ -1780,22 +1804,29 @@ SelectionDisplay = (function() {
|
|||
} else {
|
||||
duplicatedEntityIDs = null;
|
||||
}
|
||||
|
||||
previousPickRay = pickRay;
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
pushCommandForSelections(duplicatedEntityIDs);
|
||||
},
|
||||
onMove: function(event) {
|
||||
pickRay = generalComputePickRay(event.x, event.y);
|
||||
var pickRay = generalComputePickRay(event.x, event.y);
|
||||
|
||||
// Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
|
||||
if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickNormal)) {
|
||||
pickRay = previousPickRay;
|
||||
}
|
||||
|
||||
var newIntersection = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, pickNormal);
|
||||
var vector = Vec3.subtract(newIntersection, lastPick);
|
||||
|
||||
if (direction === TRANSLATE_DIRECTION.X) {
|
||||
projectionVector = { x:1, y:0, z:0 };
|
||||
projectionVector = { x: 1, y: 0, z: 0 };
|
||||
} else if (direction === TRANSLATE_DIRECTION.Y) {
|
||||
projectionVector = { x:0, y:1, z:0 };
|
||||
projectionVector = { x: 0, y: 1, z: 0 };
|
||||
} else if (direction === TRANSLATE_DIRECTION.Z) {
|
||||
projectionVector = { x:0, y:0, z:1 };
|
||||
projectionVector = { x: 0, y: 0, z: 1 };
|
||||
}
|
||||
|
||||
var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
|
||||
|
@ -1829,6 +1860,8 @@ SelectionDisplay = (function() {
|
|||
var newPosition = Vec3.sum(properties.position, vector);
|
||||
Entities.editEntity(id, { position: newPosition });
|
||||
}
|
||||
|
||||
previousPickRay = pickRay;
|
||||
|
||||
SelectionManager._update();
|
||||
}
|
||||
|
@ -1869,7 +1902,6 @@ SelectionDisplay = (function() {
|
|||
var lastPick3D = null;
|
||||
var initialPosition = null;
|
||||
var initialDimensions = null;
|
||||
var initialIntersection = null;
|
||||
var initialProperties = null;
|
||||
var registrationPoint = null;
|
||||
var deltaPivot = null;
|
||||
|
@ -1877,6 +1909,7 @@ SelectionDisplay = (function() {
|
|||
var pickRayPosition = null;
|
||||
var pickRayPosition3D = null;
|
||||
var rotation = null;
|
||||
var previousPickRay = null;
|
||||
|
||||
var onBegin = function(event, pickRay, pickResult) {
|
||||
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
||||
|
@ -1909,7 +1942,7 @@ SelectionDisplay = (function() {
|
|||
var scaledOffset = Vec3.multiply(0.5, offset);
|
||||
|
||||
// Offset from the registration point
|
||||
offsetRP = Vec3.subtract(scaledOffset, centeredRP);
|
||||
var offsetRP = Vec3.subtract(scaledOffset, centeredRP);
|
||||
|
||||
// Scaled offset in world coordinates
|
||||
var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP);
|
||||
|
@ -1919,57 +1952,10 @@ SelectionDisplay = (function() {
|
|||
if (directionFor3DStretch) {
|
||||
// pivot, offset and pickPlanePosition for 3D manipulation
|
||||
var scaledPivot3D = Vec3.multiply(0.5, Vec3.multiply(1.0, directionFor3DStretch));
|
||||
deltaPivot3D = Vec3.subtract(centeredRP, scaledPivot3D);
|
||||
|
||||
var scaledOffsetWorld3D = vec3Mult(initialDimensions,
|
||||
Vec3.subtract(Vec3.multiply(0.5, Vec3.multiply(-1.0, directionFor3DStretch)), centeredRP));
|
||||
|
||||
deltaPivot3D = Vec3.subtract(centeredRP, scaledPivot3D);
|
||||
pickRayPosition3D = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
|
||||
}
|
||||
var start = null;
|
||||
var end = null;
|
||||
if ((numDimensions === 1) && mask.x) {
|
||||
start = Vec3.multiplyQbyV(rotation, {
|
||||
x: -10000,
|
||||
y: 0,
|
||||
z: 0
|
||||
});
|
||||
start = Vec3.sum(start, properties.position);
|
||||
end = Vec3.multiplyQbyV(rotation, {
|
||||
x: 10000,
|
||||
y: 0,
|
||||
z: 0
|
||||
});
|
||||
end = Vec3.sum(end, properties.position);
|
||||
}
|
||||
if ((numDimensions === 1) && mask.y) {
|
||||
start = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: -10000,
|
||||
z: 0
|
||||
});
|
||||
start = Vec3.sum(start, properties.position);
|
||||
end = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: 10000,
|
||||
z: 0
|
||||
});
|
||||
end = Vec3.sum(end, properties.position);
|
||||
}
|
||||
if ((numDimensions === 1) && mask.z) {
|
||||
start = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: -10000
|
||||
});
|
||||
start = Vec3.sum(start, properties.position);
|
||||
end = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 10000
|
||||
});
|
||||
end = Vec3.sum(end, properties.position);
|
||||
}
|
||||
|
||||
if (numDimensions === 1) {
|
||||
if (mask.x === 1) {
|
||||
planeNormal = {
|
||||
|
@ -2040,10 +2026,10 @@ SelectionDisplay = (function() {
|
|||
SelectionManager.saveProperties();
|
||||
that.resetPreviousHandleColor();
|
||||
|
||||
if (stretchPanel != null) {
|
||||
if (stretchPanel !== null) {
|
||||
Overlays.editOverlay(stretchPanel, { visible: true });
|
||||
}
|
||||
if (scaleHandle != null) {
|
||||
if (scaleHandle !== null) {
|
||||
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE_SELECTED });
|
||||
}
|
||||
|
||||
|
@ -2053,13 +2039,15 @@ SelectionDisplay = (function() {
|
|||
Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
|
||||
that.replaceCollisionsAfterStretch = true;
|
||||
}
|
||||
|
||||
previousPickRay = pickRay;
|
||||
};
|
||||
|
||||
var onEnd = function(event, reason) {
|
||||
if (stretchPanel != null) {
|
||||
if (stretchPanel !== null) {
|
||||
Overlays.editOverlay(stretchPanel, { visible: false });
|
||||
}
|
||||
if (scaleHandle != null) {
|
||||
if (scaleHandle !== null) {
|
||||
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE });
|
||||
}
|
||||
|
||||
|
@ -2075,14 +2063,12 @@ SelectionDisplay = (function() {
|
|||
var onMove = function(event) {
|
||||
var proportional = (spaceMode === SPACE_WORLD) || directionEnum === STRETCH_DIRECTION.ALL;
|
||||
|
||||
var position, dimensions, rotation;
|
||||
var position, rotation;
|
||||
if (spaceMode === SPACE_LOCAL) {
|
||||
position = SelectionManager.localPosition;
|
||||
dimensions = SelectionManager.localDimensions;
|
||||
rotation = SelectionManager.localRotation;
|
||||
} else {
|
||||
position = SelectionManager.worldPosition;
|
||||
dimensions = SelectionManager.worldDimensions;
|
||||
rotation = SelectionManager.worldRotation;
|
||||
}
|
||||
|
||||
|
@ -2090,9 +2076,15 @@ SelectionDisplay = (function() {
|
|||
var localSigns = signs;
|
||||
var pickRay = generalComputePickRay(event.x, event.y);
|
||||
|
||||
// Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
|
||||
if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, planeNormal)) {
|
||||
pickRay = previousPickRay;
|
||||
}
|
||||
|
||||
// Are we using handControllers or Mouse - only relevant for 3D tools
|
||||
var controllerPose = getControllerWorldLocation(activeHand, true);
|
||||
var vector = null;
|
||||
var newPick = null;
|
||||
if (HMD.isHMDAvailable() && HMD.isHandControllerAvailable() &&
|
||||
controllerPose.valid && that.triggered && directionFor3DStretch) {
|
||||
localDeltaPivot = deltaPivot3D;
|
||||
|
@ -2143,14 +2135,23 @@ SelectionDisplay = (function() {
|
|||
}
|
||||
|
||||
var minimumDimension = directionEnum === STRETCH_DIRECTION.ALL ? STRETCH_ALL_MINIMUM_DIMENSION :
|
||||
STRETCH_MINIMUM_DIMENSION;
|
||||
newDimensions.x = Math.max(newDimensions.x, minimumDimension);
|
||||
newDimensions.y = Math.max(newDimensions.y, minimumDimension);
|
||||
newDimensions.z = Math.max(newDimensions.z, minimumDimension);
|
||||
STRETCH_MINIMUM_DIMENSION;
|
||||
if (newDimensions.x < minimumDimension) {
|
||||
newDimensions.x = minimumDimension;
|
||||
changeInDimensions.x = minimumDimension - initialDimensions.x;
|
||||
}
|
||||
if (newDimensions.y < minimumDimension) {
|
||||
newDimensions.y = minimumDimension;
|
||||
changeInDimensions.y = minimumDimension - initialDimensions.y;
|
||||
}
|
||||
if (newDimensions.z < minimumDimension) {
|
||||
newDimensions.z = minimumDimension;
|
||||
changeInDimensions.z = minimumDimension - initialDimensions.z;
|
||||
}
|
||||
|
||||
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions));
|
||||
if (directionEnum === STRETCH_DIRECTION.ALL) {
|
||||
changeInPosition = { x:0, y:0, z:0 };
|
||||
changeInPosition = { x: 0, y: 0, z: 0 };
|
||||
}
|
||||
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
||||
|
||||
|
@ -2168,6 +2169,8 @@ SelectionDisplay = (function() {
|
|||
Vec3.print(" changeInPosition:", changeInPosition);
|
||||
Vec3.print(" newPosition:", newPosition);
|
||||
}
|
||||
|
||||
previousPickRay = pickRay;
|
||||
|
||||
SelectionManager._update();
|
||||
};// End of onMove def
|
||||
|
@ -2184,13 +2187,13 @@ SelectionDisplay = (function() {
|
|||
var directionVector, offset, stretchPanel;
|
||||
if (directionEnum === STRETCH_DIRECTION.X) {
|
||||
stretchPanel = handleStretchXPanel;
|
||||
directionVector = { x:-1, y:0, z:0 };
|
||||
directionVector = { x: -1, y: 0, z: 0 };
|
||||
} else if (directionEnum === STRETCH_DIRECTION.Y) {
|
||||
stretchPanel = handleStretchYPanel;
|
||||
directionVector = { x:0, y:-1, z:0 };
|
||||
directionVector = { x: 0, y: -1, z: 0 };
|
||||
} else if (directionEnum === STRETCH_DIRECTION.Z) {
|
||||
stretchPanel = handleStretchZPanel
|
||||
directionVector = { x:0, y:0, z:-1 };
|
||||
stretchPanel = handleStretchZPanel;
|
||||
directionVector = { x: 0, y: 0, z: -1 };
|
||||
}
|
||||
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
||||
var tool = makeStretchTool(mode, directionEnum, directionVector, directionVector, offset, stretchPanel, null);
|
||||
|
@ -2201,28 +2204,28 @@ SelectionDisplay = (function() {
|
|||
function addHandleScaleTool(overlay, mode, directionEnum) {
|
||||
var directionVector, offset, selectedHandle;
|
||||
if (directionEnum === SCALE_DIRECTION.LBN) {
|
||||
directionVector = { x:1, y:1, z:1 };
|
||||
directionVector = { x: 1, y: 1, z: 1 };
|
||||
selectedHandle = handleScaleLBNCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.RBN) {
|
||||
directionVector = { x:-1, y:1, z:1 };
|
||||
directionVector = { x: -1, y: 1, z: 1 };
|
||||
selectedHandle = handleScaleRBNCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.LBF) {
|
||||
directionVector = { x:1, y:1, z:-1 };
|
||||
directionVector = { x: 1, y: 1, z: -1 };
|
||||
selectedHandle = handleScaleLBFCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.RBF) {
|
||||
directionVector = { x:-1, y:1, z:-1 };
|
||||
directionVector = { x: -1, y: 1, z: -1 };
|
||||
selectedHandle = handleScaleRBFCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.LTN) {
|
||||
directionVector = { x:1, y:-1, z:1 };
|
||||
directionVector = { x: 1, y: -1, z: 1 };
|
||||
selectedHandle = handleScaleLTNCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.RTN) {
|
||||
directionVector = { x:-1, y:-1, z:1 };
|
||||
directionVector = { x: -1, y: -1, z: 1 };
|
||||
selectedHandle = handleScaleRTNCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.LTF) {
|
||||
directionVector = { x:1, y:-1, z:-1 };
|
||||
directionVector = { x: 1, y: -1, z: -1 };
|
||||
selectedHandle = handleScaleLTFCube;
|
||||
} else if (directionEnum === SCALE_DIRECTION.RTF) {
|
||||
directionVector = { x:-1, y:-1, z:-1 };
|
||||
directionVector = { x: -1, y: -1, z: -1 };
|
||||
selectedHandle = handleScaleRTFCube;
|
||||
}
|
||||
offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
|
||||
|
@ -2233,7 +2236,6 @@ SelectionDisplay = (function() {
|
|||
|
||||
// FUNCTION: UPDATE ROTATION DEGREES OVERLAY
|
||||
function updateRotationDegreesOverlay(angleFromZero, position) {
|
||||
var angle = angleFromZero * (Math.PI / 180);
|
||||
var toCameraDistance = getDistanceToCamera(position);
|
||||
var overlayProps = {
|
||||
position: position,
|
||||
|
@ -2424,9 +2426,10 @@ SelectionDisplay = (function() {
|
|||
|
||||
var startAtCurrent = 0;
|
||||
var endAtCurrent = angleFromZero;
|
||||
var maxDegrees = 360;
|
||||
if (angleFromZero < 0) {
|
||||
startAtCurrent = 360 + angleFromZero;
|
||||
endAtCurrent = 360;
|
||||
startAtCurrent = maxDegrees + angleFromZero;
|
||||
endAtCurrent = maxDegrees;
|
||||
}
|
||||
Overlays.editOverlay(handleRotateCurrentRing, {
|
||||
startAt: startAtCurrent,
|
||||
|
@ -2438,8 +2441,9 @@ SelectionDisplay = (function() {
|
|||
if (spaceMode === SPACE_LOCAL) {
|
||||
Overlays.editOverlay(handleRotateCurrentRing, { rotation: worldRotationZ });
|
||||
} else {
|
||||
var rotationDegrees = 90;
|
||||
Overlays.editOverlay(handleRotateCurrentRing, {
|
||||
rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0)
|
||||
rotation: Quat.fromPitchYawRollDegrees(-rotationDegrees, 0, 0)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,8 @@
|
|||
// Computes SSIM - see https://en.wikipedia.org/wiki/Structural_similarity
|
||||
// The value is computed for the luminance component and the average value is returned
|
||||
double ImageComparer::compareImages(QImage resultImage, QImage expectedImage) const {
|
||||
// Make sure the image is 8 bits per colour
|
||||
QImage::Format format = expectedImage.format();
|
||||
if (format != QImage::Format::Format_ARGB32) {
|
||||
throw -1;
|
||||
}
|
||||
|
||||
const int L = 255; // (2^number of bits per pixel) - 1
|
||||
|
||||
const double K1 { 0.01 };
|
||||
const double K2 { 0.03 };
|
||||
const double c1 = pow((K1 * L), 2);
|
||||
|
|
|
@ -25,6 +25,11 @@ extern AutoTester* autoTester;
|
|||
|
||||
Test::Test() {
|
||||
mismatchWindow.setModal(true);
|
||||
|
||||
if (autoTester) {
|
||||
autoTester->setUserText("highfidelity");
|
||||
autoTester->setBranchText("master");
|
||||
}
|
||||
}
|
||||
|
||||
bool Test::createTestResultsFolderPath(const QString& directory) {
|
||||
|
@ -63,7 +68,6 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar)
|
|||
|
||||
// Loop over both lists and compare each pair of images
|
||||
// Quit loop if user has aborted due to a failed test.
|
||||
const double THRESHOLD { 0.9995 };
|
||||
bool success{ true };
|
||||
bool keepOn{ true };
|
||||
for (int i = 0; keepOn && i < expectedImagesFullFilenames.length(); ++i) {
|
||||
|
@ -71,17 +75,14 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar)
|
|||
QImage resultImage(resultImagesFullFilenames[i]);
|
||||
QImage expectedImage(expectedImagesFullFilenames[i]);
|
||||
|
||||
double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical
|
||||
|
||||
// similarityIndex is set to -100.0 to indicate images are not the same size
|
||||
if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) {
|
||||
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical
|
||||
try {
|
||||
similarityIndex = -100.0;
|
||||
} else {
|
||||
similarityIndex = imageComparer.compareImages(resultImage, expectedImage);
|
||||
} catch (...) {
|
||||
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Image not in expected format");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (similarityIndex < THRESHOLD) {
|
||||
|
@ -176,20 +177,25 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai
|
|||
comparisonImage.save(failureFolderPath + "/" + "Difference Image.png");
|
||||
}
|
||||
|
||||
void Test::startTestsEvaluation(const QString& testFolder) {
|
||||
// Get list of JPEG images in folder, sorted by name
|
||||
QString previousSelection = snapshotDirectory;
|
||||
QString parent = previousSelection.left(previousSelection.lastIndexOf('/'));
|
||||
if (!parent.isNull() && parent.right(1) != "/") {
|
||||
parent += "/";
|
||||
}
|
||||
snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent,
|
||||
QFileDialog::ShowDirsOnly);
|
||||
void Test::startTestsEvaluation(const QString& testFolder, const QString& branchFromCommandLine, const QString& userFromCommandLine) {
|
||||
if (testFolder.isNull()) {
|
||||
// Get list of JPEG images in folder, sorted by name
|
||||
QString previousSelection = snapshotDirectory;
|
||||
QString parent = previousSelection.left(previousSelection.lastIndexOf('/'));
|
||||
if (!parent.isNull() && parent.right(1) != "/") {
|
||||
parent += "/";
|
||||
}
|
||||
snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent,
|
||||
QFileDialog::ShowDirsOnly);
|
||||
|
||||
// If user cancelled then restore previous selection and return
|
||||
if (snapshotDirectory == "") {
|
||||
snapshotDirectory = previousSelection;
|
||||
return;
|
||||
// If user cancelled then restore previous selection and return
|
||||
if (snapshotDirectory == "") {
|
||||
snapshotDirectory = previousSelection;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
snapshotDirectory = testFolder;
|
||||
exitWhenComplete = true;
|
||||
}
|
||||
|
||||
// Quit if test results folder could not be created
|
||||
|
@ -197,17 +203,6 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Before any processing - all images are converted to PNGs, as this is the format stored on GitHub
|
||||
QStringList sortedSnapshotFilenames = createListOfAll_imagesInDirectory("jpg", snapshotDirectory);
|
||||
foreach(QString filename, sortedSnapshotFilenames) {
|
||||
QString filenameWithoutExtension = filename.left(filename.length() - 4);
|
||||
copyJPGtoPNG(snapshotDirectory + "/" + filenameWithoutExtension + ".jpg",
|
||||
snapshotDirectory + "/" + filenameWithoutExtension + ".png"
|
||||
);
|
||||
|
||||
QFile::remove(snapshotDirectory + "/" + filenameWithoutExtension + ".jpg");
|
||||
}
|
||||
|
||||
// Create two lists. The first is the test results, the second is the expected images
|
||||
// The expected images are represented as a URL to enable download from GitHub
|
||||
// Images that are in the wrong format are ignored.
|
||||
|
@ -219,6 +214,9 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
|||
expectedImagesFilenames.clear();
|
||||
expectedImagesFullFilenames.clear();
|
||||
|
||||
QString branch = (branchFromCommandLine.isNull()) ? autoTester->getSelectedBranch() : branchFromCommandLine;
|
||||
QString user = (userFromCommandLine.isNull()) ? autoTester->getSelectedUser() : userFromCommandLine;
|
||||
|
||||
foreach(QString currentFilename, sortedTestResultsFilenames) {
|
||||
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
||||
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
||||
|
@ -231,7 +229,7 @@ void Test::startTestsEvaluation(const QString& testFolder) {
|
|||
QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS);
|
||||
QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png";
|
||||
|
||||
QString imageURLString("https://raw.githubusercontent.com/" + GIT_HUB_USER + "/hifi_tests/" + GIT_HUB_BRANCH + "/" +
|
||||
QString imageURLString("https://raw.githubusercontent.com/" + user + "/" + GIT_HUB_REPOSITORY + "/" + branch + "/" +
|
||||
expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename);
|
||||
|
||||
expectedImagesURLs << imageURLString;
|
||||
|
@ -259,6 +257,10 @@ void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactive
|
|||
}
|
||||
|
||||
zipAndDeleteTestResultsFolder();
|
||||
|
||||
if (exitWhenComplete) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool Test::isAValidDirectory(const QString& pathname) {
|
||||
|
@ -299,10 +301,9 @@ QString Test::extractPathFromTestsDown(const QString& fullPath) {
|
|||
|
||||
void Test::includeTest(QTextStream& textStream, const QString& testPathname) {
|
||||
QString partialPath = extractPathFromTestsDown(testPathname);
|
||||
textStream << "Script.include(\""
|
||||
<< "https://github.com/" << GIT_HUB_USER << "/hifi_tests/blob/" << GIT_HUB_BRANCH
|
||||
<< partialPath + "?raw=true\");"
|
||||
<< endl;
|
||||
QString partialPathWithoutTests = partialPath.right(partialPath.length() - 7);
|
||||
|
||||
textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << endl;
|
||||
}
|
||||
|
||||
// Creates a single script in a user-selected folder.
|
||||
|
@ -397,12 +398,20 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact
|
|||
const QString DATE_TIME_FORMAT("MMM d yyyy, h:mm");
|
||||
textStream << "// This is an automatically generated file, created by auto-tester on " << QDateTime::currentDateTime().toString(DATE_TIME_FORMAT) << endl << endl;
|
||||
|
||||
textStream << "user = \"" + GIT_HUB_USER + "/\";" << endl;
|
||||
textStream << "repository = \"" + GIT_HUB_REPOSITORY + "/\";" << endl;
|
||||
textStream << "branch = \"" + GIT_HUB_BRANCH + "/\";" << endl << endl;
|
||||
// Include 'autoTest.js'
|
||||
QString branch = autoTester->getSelectedBranch();
|
||||
QString user = autoTester->getSelectedUser();
|
||||
|
||||
textStream << "var autoTester = Script.require(\"https://github.com/" + GIT_HUB_USER + "/hifi_tests/blob/"
|
||||
+ GIT_HUB_BRANCH + "/tests/utils/autoTester.js?raw=true\");" << endl << endl;
|
||||
textStream << "PATH_TO_THE_REPO_PATH_UTILS_FILE = \"https://raw.githubusercontent.com/" + user + "/hifi_tests/" + branch + "/tests/utils/branchUtils.js\";" << endl;
|
||||
textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl;
|
||||
textStream << "var autoTester = createAutoTester(Script.resolvePath(\".\"));" << endl << endl;
|
||||
|
||||
textStream << "var testsRootPath = autoTester.getTestsRootPath();" << endl << endl;
|
||||
|
||||
// Wait 10 seconds before starting
|
||||
textStream << "if (typeof Test !== 'undefined') {" << endl;
|
||||
textStream << " Test.wait(10000);" << endl;
|
||||
textStream << "};" << endl << endl;
|
||||
|
||||
textStream << "autoTester.enableRecursive();" << endl;
|
||||
textStream << "autoTester.enableAuto();" << endl << endl;
|
||||
|
@ -498,13 +507,13 @@ void Test::createTests() {
|
|||
return;
|
||||
}
|
||||
|
||||
QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("jpg", snapshotDirectory);
|
||||
QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("png", snapshotDirectory);
|
||||
|
||||
int i = 1;
|
||||
const int maxImages = pow(10, NUM_DIGITS);
|
||||
foreach (QString currentFilename, sortedImageFilenames) {
|
||||
QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename;
|
||||
if (isInSnapshotFilenameFormat("jpg", currentFilename)) {
|
||||
if (isInSnapshotFilenameFormat("png", currentFilename)) {
|
||||
if (i >= maxImages) {
|
||||
QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported");
|
||||
exit(-1);
|
||||
|
@ -528,9 +537,12 @@ void Test::createTests() {
|
|||
fullNewFileName += "/" + newFilename;
|
||||
|
||||
try {
|
||||
copyJPGtoPNG(fullCurrentFilename, fullNewFileName);
|
||||
if (QFile::exists(fullNewFileName)) {
|
||||
QFile::remove(fullNewFileName);
|
||||
}
|
||||
QFile::copy(fullCurrentFilename, fullNewFileName);
|
||||
} catch (...) {
|
||||
QMessageBox::critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nTest creation aborted");
|
||||
QMessageBox::critical(0, "Error", "Could not copy file: " + fullCurrentFilename + " to " + fullNewFileName + "\n");
|
||||
exit(-1);
|
||||
}
|
||||
++i;
|
||||
|
@ -560,9 +572,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) {
|
|||
const QString ws("\\h*"); //white-space character
|
||||
const QString functionPerformName(ws + "autoTester" + ws + "\\." + ws + "perform");
|
||||
const QString quotedString("\\\".+\\\"");
|
||||
const QString ownPath("Script" + ws + "\\." + ws + "resolvePath" + ws + "\\(" + ws + "\\\"\\.\\\"" + ws + "\\)");
|
||||
const QString functionParameter("function" + ws + "\\(testType" + ws + "\\)");
|
||||
QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString + "\\," + ws + ownPath + "\\," + ws + functionParameter + ws + "{" + ".*");
|
||||
QString regexTestTitle(ws + functionPerformName + "\\(" + quotedString);
|
||||
QRegularExpression lineContainingTitle = QRegularExpression(regexTestTitle);
|
||||
|
||||
|
||||
|
@ -811,19 +821,6 @@ void Test::createTestsOutline() {
|
|||
QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created");
|
||||
}
|
||||
|
||||
void Test::copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename) {
|
||||
QFile::remove(destinationPNGFullFilename);
|
||||
|
||||
QImageReader reader;
|
||||
reader.setFileName(sourceJPGFullFilename);
|
||||
|
||||
QImage image = reader.read();
|
||||
|
||||
QImageWriter writer;
|
||||
writer.setFileName(destinationPNGFullFilename);
|
||||
writer.write(image);
|
||||
}
|
||||
|
||||
QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) {
|
||||
imageDirectory = QDir(pathToImageDirectory);
|
||||
QStringList nameFilters;
|
||||
|
|
|
@ -37,7 +37,7 @@ class Test {
|
|||
public:
|
||||
Test();
|
||||
|
||||
void startTestsEvaluation(const QString& testFolder = QString());
|
||||
void startTestsEvaluation(const QString& testFolder = QString(), const QString& branchFromCommandLine = QString(), const QString& userFromCommandLine = QString());
|
||||
void finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar);
|
||||
|
||||
void createRecursiveScript();
|
||||
|
@ -69,13 +69,13 @@ public:
|
|||
QString getExpectedImageDestinationDirectory(const QString& filename);
|
||||
QString getExpectedImagePartialSourceDirectory(const QString& filename);
|
||||
|
||||
void copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename);
|
||||
|
||||
private:
|
||||
const QString TEST_FILENAME { "test.js" };
|
||||
const QString TEST_RESULTS_FOLDER { "TestResults" };
|
||||
const QString TEST_RESULTS_FILENAME { "TestResults.txt" };
|
||||
|
||||
const double THRESHOLD{ 0.96 };
|
||||
|
||||
QDir imageDirectory;
|
||||
|
||||
MismatchWindow mismatchWindow;
|
||||
|
@ -102,9 +102,7 @@ private:
|
|||
QStringList resultImagesFullFilenames;
|
||||
|
||||
// Used for accessing GitHub
|
||||
const QString GIT_HUB_USER{ "highfidelity" };
|
||||
const QString GIT_HUB_REPOSITORY{ "hifi_tests" };
|
||||
const QString GIT_HUB_BRANCH{ "master" };
|
||||
|
||||
const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" };
|
||||
|
||||
|
@ -115,6 +113,8 @@ private:
|
|||
// var pathSeparator = ".";
|
||||
const QString ADVANCE_KEY{ "n" };
|
||||
const QString PATH_SEPARATOR{ "." };
|
||||
|
||||
bool exitWhenComplete{ false };
|
||||
};
|
||||
|
||||
#endif // hifi_test_h
|
|
@ -10,23 +10,63 @@
|
|||
#include <QtWidgets/QApplication>
|
||||
#include "ui/AutoTester.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
AutoTester* autoTester;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Only parameter is "--testFolder"
|
||||
// If no parameters then run in interactive mode
|
||||
// Parameter --testFolder <folder containing the test images>
|
||||
// Parameter --branch <branch on GitHub>
|
||||
// default is "master"
|
||||
// Parameter --user <GitHub user>
|
||||
// default is "highfidelity"
|
||||
// Parameter --repository <repository on GitHub>
|
||||
// default is "highfidelity"
|
||||
|
||||
QString testFolder;
|
||||
if (argc == 3) {
|
||||
if (QString(argv[1]) == "--testFolder") {
|
||||
testFolder = QString(argv[2]);
|
||||
|
||||
QString branch{ "master" };
|
||||
QString user{ "highfidelity" };
|
||||
|
||||
for (int i = 1; i < argc - 1; ++i) {
|
||||
if (QString(argv[i]) == "--testFolder") {
|
||||
++i;
|
||||
if (i < argc) {
|
||||
testFolder = QString(argv[i]);
|
||||
} else {
|
||||
std::cout << "Missing parameter after --testFolder" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
} else if (QString(argv[i]) == "--branch") {
|
||||
++i;
|
||||
if (i < argc) {
|
||||
branch = QString(argv[i]);
|
||||
} else {
|
||||
std::cout << "Missing parameter after --branch" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
} else if (QString(argv[i]) == "--user") {
|
||||
++i;
|
||||
if (i < argc) {
|
||||
user = QString(argv[i]);
|
||||
} else {
|
||||
std::cout << "Missing parameter after --user" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
std::cout << "Unknown parameter" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
QApplication application(argc, argv);
|
||||
|
||||
autoTester = new AutoTester();
|
||||
autoTester->setup();
|
||||
|
||||
if (!testFolder.isNull()) {
|
||||
autoTester->runFromCommandLine(testFolder);
|
||||
autoTester->runFromCommandLine(testFolder, branch, user);
|
||||
} else {
|
||||
autoTester->show();
|
||||
}
|
||||
|
|
|
@ -29,13 +29,15 @@ AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) {
|
|||
ui.hideTaskbarButton->setVisible(false);
|
||||
ui.showTaskbarButton->setVisible(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AutoTester::setup() {
|
||||
test = new Test();
|
||||
}
|
||||
|
||||
void AutoTester::runFromCommandLine(const QString& testFolder) {
|
||||
void AutoTester::runFromCommandLine(const QString& testFolder, const QString& branch, const QString& user) {
|
||||
isRunningFromCommandline = true;
|
||||
test->startTestsEvaluation(testFolder);
|
||||
test->startTestsEvaluation(testFolder, branch, user);
|
||||
}
|
||||
|
||||
void AutoTester::on_evaluateTestsButton_clicked() {
|
||||
|
@ -116,6 +118,7 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director
|
|||
ui.progressBar->setValue(0);
|
||||
ui.progressBar->setVisible(true);
|
||||
|
||||
downloaders.clear();
|
||||
for (int i = 0; i < _numberOfImagesToDownload; ++i) {
|
||||
QUrl imageURL(URLs[i]);
|
||||
downloadImage(imageURL);
|
||||
|
@ -125,14 +128,12 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director
|
|||
}
|
||||
|
||||
void AutoTester::saveImage(int index) {
|
||||
QPixmap pixmap;
|
||||
pixmap.loadFromData(downloaders[index]->downloadedData());
|
||||
|
||||
QImage image = pixmap.toImage();
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
QString fullPathname = _directoryName + "/" + _filenames[index];
|
||||
if (!image.save(fullPathname, 0, 100)) {
|
||||
try {
|
||||
QFile file(_directoryName + "/" + _filenames[index]);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(downloaders[index]->downloadedData());
|
||||
file.close();
|
||||
} catch (...) {
|
||||
QMessageBox::information(0, "Test Aborted", "Failed to save image: " + _filenames[index]);
|
||||
ui.progressBar->setVisible(false);
|
||||
return;
|
||||
|
@ -141,6 +142,7 @@ void AutoTester::saveImage(int index) {
|
|||
++_numberOfImagesDownloaded;
|
||||
|
||||
if (_numberOfImagesDownloaded == _numberOfImagesToDownload) {
|
||||
disconnect(signalMapper, SIGNAL (mapped(int)), this, SLOT (saveImage(int)));
|
||||
test->finishTestsEvaluation(isRunningFromCommandline, ui.checkBoxInteractiveMode->isChecked(), ui.progressBar);
|
||||
} else {
|
||||
ui.progressBar->setValue(_numberOfImagesDownloaded);
|
||||
|
@ -150,3 +152,20 @@ void AutoTester::saveImage(int index) {
|
|||
void AutoTester::about() {
|
||||
QMessageBox::information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__);
|
||||
}
|
||||
|
||||
void AutoTester::setUserText(const QString& user) {
|
||||
ui.userTextEdit->setText(user);
|
||||
}
|
||||
|
||||
QString AutoTester::getSelectedUser()
|
||||
{
|
||||
return ui.userTextEdit->toPlainText();
|
||||
}
|
||||
|
||||
void AutoTester::setBranchText(const QString& branch) {
|
||||
ui.branchTextEdit->setText(branch);
|
||||
}
|
||||
|
||||
QString AutoTester::getSelectedBranch() {
|
||||
return ui.branchTextEdit->toPlainText();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QSignalMapper>
|
||||
#include <QTextEdit>
|
||||
#include "ui_AutoTester.h"
|
||||
|
||||
#include "../Downloader.h"
|
||||
|
@ -23,11 +24,19 @@ class AutoTester : public QMainWindow {
|
|||
public:
|
||||
AutoTester(QWidget *parent = Q_NULLPTR);
|
||||
|
||||
void runFromCommandLine(const QString& testFolder);
|
||||
void setup();
|
||||
|
||||
void runFromCommandLine(const QString& testFolder, const QString& branch, const QString& user);
|
||||
|
||||
void downloadImage(const QUrl& url);
|
||||
void downloadImages(const QStringList& URLs, const QString& directoryName, const QStringList& filenames);
|
||||
|
||||
void setUserText(const QString& user);
|
||||
QString getSelectedUser();
|
||||
|
||||
void setBranchText(const QString& branch);
|
||||
QString getSelectedBranch();
|
||||
|
||||
private slots:
|
||||
void on_evaluateTestsButton_clicked();
|
||||
void on_createRecursiveScriptButton_clicked();
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>607</width>
|
||||
<height>514</height>
|
||||
<width>612</width>
|
||||
<height>537</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -17,9 +17,9 @@
|
|||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>360</x>
|
||||
<y>400</y>
|
||||
<width>220</width>
|
||||
<x>380</x>
|
||||
<y>430</y>
|
||||
<width>101</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -43,9 +43,9 @@
|
|||
<widget class="QPushButton" name="evaluateTestsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>285</y>
|
||||
<width>220</width>
|
||||
<x>430</x>
|
||||
<y>270</y>
|
||||
<width>101</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -56,8 +56,8 @@
|
|||
<widget class="QPushButton" name="createRecursiveScriptButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>360</x>
|
||||
<y>35</y>
|
||||
<x>330</x>
|
||||
<y>110</y>
|
||||
<width>220</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
|
@ -69,8 +69,8 @@
|
|||
<widget class="QCheckBox" name="checkBoxInteractiveMode">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>23</x>
|
||||
<y>250</y>
|
||||
<x>320</x>
|
||||
<y>280</y>
|
||||
<width>131</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
|
@ -85,8 +85,8 @@
|
|||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>340</y>
|
||||
<x>320</x>
|
||||
<y>330</y>
|
||||
<width>255</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
|
@ -98,8 +98,8 @@
|
|||
<widget class="QPushButton" name="createAllRecursiveScriptsButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>360</x>
|
||||
<y>100</y>
|
||||
<x>330</x>
|
||||
<y>170</y>
|
||||
<width>220</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
|
@ -112,7 +112,7 @@
|
|||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>80</y>
|
||||
<y>110</y>
|
||||
<width>220</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
|
@ -125,7 +125,7 @@
|
|||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>130</y>
|
||||
<y>160</y>
|
||||
<width>220</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
|
@ -138,7 +138,7 @@
|
|||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>180</y>
|
||||
<y>250</y>
|
||||
<width>220</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
|
@ -150,27 +150,83 @@
|
|||
<widget class="QPushButton" name="showTaskbarButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>490</x>
|
||||
<y>280</y>
|
||||
<width>91</width>
|
||||
<x>10</x>
|
||||
<y>440</y>
|
||||
<width>211</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Taskbar</string>
|
||||
<string>Show Windows Taskbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="hideTaskbarButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>490</x>
|
||||
<y>230</y>
|
||||
<width>91</width>
|
||||
<x>10</x>
|
||||
<y>390</y>
|
||||
<width>211</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hide Taskbar</string>
|
||||
<string>Hide Windows Taskbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>330</x>
|
||||
<y>55</y>
|
||||
<width>81</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>GitHub Branch</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>330</x>
|
||||
<y>15</y>
|
||||
<width>81</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>GitHub User</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="userTextEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>420</x>
|
||||
<y>12</y>
|
||||
<width>140</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="branchTextEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>420</x>
|
||||
<y>50</y>
|
||||
<width>140</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -179,7 +235,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>607</width>
|
||||
<width>612</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
|
Loading…
Reference in a new issue