mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:24:00 +02:00
first working version of scriptable Overlays
This commit is contained in:
parent
8e284a55b1
commit
2eac9c293f
8 changed files with 314 additions and 38 deletions
35
examples/overlaysExample.js
Normal file
35
examples/overlaysExample.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// overlaysExample.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2/14/14.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that demonstrates use of the Overlays class
|
||||
//
|
||||
//
|
||||
|
||||
/*
|
||||
_testOverlayA.init(_glWidget, QString("https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg"),
|
||||
QRect(100,100,62,40), QRect(0,0,62,40));
|
||||
xColor red = { 255, 0, 0 };
|
||||
_testOverlayA.setBackgroundColor(red);
|
||||
_testOverlayB.init(_glWidget, QString("https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg"),
|
||||
QRect(170,100,62,40), QRect(0,80,62,40));
|
||||
*/
|
||||
|
||||
var toolA = Overlays.addOverlay({
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 62,
|
||||
height: 40,
|
||||
subImage: { x: 0, y: 0, width: 62, height: 40 },
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/hifi-interface-tools.svg",
|
||||
backgroundColor: { red: 255, green: 0, blue: 255},
|
||||
alpha: 1.0
|
||||
});
|
||||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(toolA);
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -289,6 +289,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
||||
|
||||
checkVersion();
|
||||
|
||||
_overlays.init(_glWidget); // do this before scripts load
|
||||
|
||||
|
||||
// do this as late as possible so that all required subsystems are inialized
|
||||
loadScripts();
|
||||
|
@ -1870,14 +1873,13 @@ void Application::init() {
|
|||
|
||||
_audio.init(_glWidget);
|
||||
|
||||
_testOverlayA.init(_glWidget, QString("./resources/images/hifi-interface-tools.svg"), QRect(100,100,62,40), QRect(0,0,62,40));
|
||||
_testOverlayB.init(_glWidget, QString("./resources/images/hifi-interface-tools.svg"), QRect(170,100,62,40), QRect(0,80,62,40));
|
||||
|
||||
_rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings);
|
||||
connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView()));
|
||||
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
|
||||
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
|
||||
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Application::closeMirrorView() {
|
||||
|
@ -2986,8 +2988,7 @@ void Application::displayOverlay() {
|
|||
_pieMenu.render();
|
||||
}
|
||||
|
||||
_testOverlayA.render(); //
|
||||
_testOverlayB.render(); //
|
||||
_overlays.render();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
@ -4066,6 +4067,8 @@ void Application::loadScript(const QString& fileNameString) {
|
|||
scriptEngine->registerGlobalObject("Camera", cameraScriptable);
|
||||
connect(scriptEngine, SIGNAL(finished(const QString&)), cameraScriptable, SLOT(deleteLater()));
|
||||
|
||||
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
||||
|
||||
QThread* workerThread = new QThread(this);
|
||||
|
||||
// when the worker thread is started, call our engine's run..
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
#include "FileLogger.h"
|
||||
#include "ParticleTreeRenderer.h"
|
||||
#include "ControllerScriptingInterface.h"
|
||||
#include "ui/ImageOverlay.h"
|
||||
#include "ui/Overlays.h"
|
||||
|
||||
|
||||
class QAction;
|
||||
|
@ -490,8 +490,7 @@ private:
|
|||
|
||||
TouchEvent _lastTouchEvent;
|
||||
|
||||
ImageOverlay _testOverlayA;
|
||||
ImageOverlay _testOverlayB;
|
||||
Overlays _overlays;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Application__) */
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
//
|
||||
// ImageOverlay.cpp
|
||||
// interface
|
||||
//
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "ImageOverlay.h"
|
||||
|
||||
#include <QSvgRenderer>
|
||||
|
@ -7,17 +15,24 @@
|
|||
|
||||
ImageOverlay::ImageOverlay() :
|
||||
_parent(NULL),
|
||||
_textureID(0)
|
||||
_textureID(0),
|
||||
_alpha(DEFAULT_ALPHA),
|
||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||
_renderImage(false),
|
||||
_textureBound(false)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void ImageOverlay::init(QGLWidget* parent, const QString& filename, const QRect& drawAt, const QRect& fromImage) {
|
||||
void ImageOverlay::init(QGLWidget* parent) {
|
||||
qDebug() << "ImageOverlay::init() parent=" << parent;
|
||||
_parent = parent;
|
||||
qDebug() << "ImageOverlay::init()... filename=" << filename;
|
||||
|
||||
/*
|
||||
qDebug() << "ImageOverlay::init()... url=" << url;
|
||||
_bounds = drawAt;
|
||||
_fromImage = fromImage;
|
||||
_textureImage = QImage(filename);
|
||||
_textureID = _parent->bindTexture(_textureImage);
|
||||
setImageURL(url);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,17 +43,43 @@ ImageOverlay::~ImageOverlay() {
|
|||
}
|
||||
}
|
||||
|
||||
void ImageOverlay::setImageURL(const QUrl& url) {
|
||||
// TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made?
|
||||
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
|
||||
manager->get(QNetworkRequest(url));
|
||||
}
|
||||
|
||||
void ImageOverlay::replyFinished(QNetworkReply* reply) {
|
||||
qDebug() << "ImageOverlay::replyFinished() reply=" << reply;
|
||||
// replace our byte array with the downloaded data
|
||||
QByteArray rawData = reply->readAll();
|
||||
_textureImage.loadFromData(rawData);
|
||||
_renderImage = true;
|
||||
|
||||
// TODO: handle setting image multiple times, how do we manage releasing the bound texture
|
||||
qDebug() << "ImageOverlay::replyFinished() about to call _parent->bindTexture(_textureImage)... _parent" << _parent;
|
||||
|
||||
|
||||
qDebug() << "ImageOverlay::replyFinished _textureID=" << _textureID
|
||||
<< "_textureImage.width()=" << _textureImage.width()
|
||||
<< "_textureImage.height()=" << _textureImage.height();
|
||||
}
|
||||
|
||||
void ImageOverlay::render() {
|
||||
qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _bounds;
|
||||
//qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _bounds;
|
||||
|
||||
if (_renderImage && !_textureBound) {
|
||||
_textureID = _parent->bindTexture(_textureImage);
|
||||
_textureBound = true;
|
||||
}
|
||||
|
||||
|
||||
bool renderImage = false;
|
||||
if (renderImage) {
|
||||
if (_renderImage) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, _textureID);
|
||||
}
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.7f); // ???
|
||||
const float MAX_COLOR = 255;
|
||||
glColor4f((_backgroundColor.red / MAX_COLOR), (_backgroundColor.green / MAX_COLOR), (_backgroundColor.blue / MAX_COLOR), _alpha);
|
||||
|
||||
float imageWidth = _textureImage.width();
|
||||
float imageHeight = _textureImage.height();
|
||||
|
@ -47,23 +88,84 @@ qDebug() << "ImageOverlay::render _textureID=" << _textureID << "_bounds=" << _b
|
|||
float w = _fromImage.width() / imageWidth; // ?? is this what we want? not sure
|
||||
float h = _fromImage.height() / imageHeight;
|
||||
|
||||
qDebug() << "ImageOverlay::render x=" << x << "y=" << y << "w="<<w << "h="<<h << "(1.0f - y)=" << (1.0f - y);
|
||||
//qDebug() << "ImageOverlay::render x=" << x << "y=" << y << "w="<<w << "h="<<h << "(1.0f - y)=" << (1.0f - y);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
//glTexCoord2f(x, 1.0f - y);
|
||||
if (_renderImage) {
|
||||
glTexCoord2f(x, 1.0f - y);
|
||||
}
|
||||
glVertex2f(_bounds.left(), _bounds.top());
|
||||
|
||||
//glTexCoord2f(x + w, 1.0f - y);
|
||||
if (_renderImage) {
|
||||
glTexCoord2f(x + w, 1.0f - y);
|
||||
}
|
||||
glVertex2f(_bounds.right(), _bounds.top());
|
||||
|
||||
//glTexCoord2f(x + w, 1.0f - (y + h));
|
||||
if (_renderImage) {
|
||||
glTexCoord2f(x + w, 1.0f - (y + h));
|
||||
}
|
||||
glVertex2f(_bounds.right(), _bounds.bottom());
|
||||
|
||||
//glTexCoord2f(x, 1.0f - (y + h));
|
||||
if (_renderImage) {
|
||||
glTexCoord2f(x, 1.0f - (y + h));
|
||||
}
|
||||
glVertex2f(_bounds.left(), _bounds.bottom());
|
||||
glEnd();
|
||||
if (renderImage) {
|
||||
if (_renderImage) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle only setting the included values...
|
||||
QScriptValue ImageOverlay::getProperties() {
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
// TODO: handle only setting the included values...
|
||||
void ImageOverlay::setProperties(const QScriptValue& properties) {
|
||||
QScriptValue bounds = properties.property("bounds");
|
||||
if (bounds.isValid()) {
|
||||
QRect boundsRect;
|
||||
boundsRect.setX(bounds.property("x").toVariant().toInt());
|
||||
boundsRect.setY(bounds.property("y").toVariant().toInt());
|
||||
boundsRect.setWidth(bounds.property("width").toVariant().toInt());
|
||||
boundsRect.setHeight(bounds.property("height").toVariant().toInt());
|
||||
setBounds(boundsRect);
|
||||
} else {
|
||||
setX(properties.property("x").toVariant().toInt());
|
||||
setY(properties.property("y").toVariant().toInt());
|
||||
setWidth(properties.property("width").toVariant().toInt());
|
||||
setHeight(properties.property("height").toVariant().toInt());
|
||||
}
|
||||
QScriptValue subImageBounds = properties.property("subImage");
|
||||
if (subImageBounds.isValid()) {
|
||||
QRect subImageRect;
|
||||
subImageRect.setX(subImageBounds.property("x").toVariant().toInt());
|
||||
subImageRect.setY(subImageBounds.property("y").toVariant().toInt());
|
||||
subImageRect.setWidth(subImageBounds.property("width").toVariant().toInt());
|
||||
subImageRect.setHeight(subImageBounds.property("height").toVariant().toInt());
|
||||
setClipFromSource(subImageRect);
|
||||
qDebug() << "set subImage to " << getClipFromSource();
|
||||
}
|
||||
|
||||
QScriptValue imageURL = properties.property("imageURL");
|
||||
if (imageURL.isValid()) {
|
||||
setImageURL(imageURL.toVariant().toString());
|
||||
}
|
||||
|
||||
QScriptValue color = properties.property("backgroundColor");
|
||||
if (color.isValid()) {
|
||||
QScriptValue red = color.property("red");
|
||||
QScriptValue green = color.property("green");
|
||||
QScriptValue blue = color.property("blue");
|
||||
if (red.isValid() && green.isValid() && blue.isValid()) {
|
||||
_backgroundColor.red = red.toVariant().toInt();
|
||||
_backgroundColor.green = green.toVariant().toInt();
|
||||
_backgroundColor.blue = blue.toVariant().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
setAlpha(properties.property("alpha").toVariant().toFloat());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,17 +8,21 @@
|
|||
#ifndef __interface__ImageOverlay__
|
||||
#define __interface__ImageOverlay__
|
||||
|
||||
#include <QImage>
|
||||
#include <QGLWidget>
|
||||
#include <QImage>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
//#include "Util.h"
|
||||
|
||||
const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 };
|
||||
const float DEFAULT_ALPHA = 0.7f;
|
||||
|
||||
class ImageOverlay : QObject {
|
||||
Q_OBJECT
|
||||
|
@ -34,9 +38,10 @@ class ImageOverlay : QObject {
|
|||
public:
|
||||
ImageOverlay();
|
||||
~ImageOverlay();
|
||||
void init(QGLWidget* parent, const QString& filename, const QRect& drawAt, const QRect& fromImage);
|
||||
void init(QGLWidget* parent);
|
||||
void render();
|
||||
|
||||
public slots:
|
||||
// getters
|
||||
int getX() const { return _bounds.x(); }
|
||||
int getY() const { return _bounds.y(); }
|
||||
|
@ -47,19 +52,25 @@ public:
|
|||
const xColor& getBackgroundColor() const { return _backgroundColor; }
|
||||
float getAlpha() const { return _alpha; }
|
||||
const QUrl& getImageURL() const { return _imageURL; }
|
||||
QScriptValue getProperties();
|
||||
|
||||
// setters
|
||||
void setX(int x) { }
|
||||
void setY(int y) { }
|
||||
void setWidth(int width) { }
|
||||
void setHeight(int height) { }
|
||||
void setBounds(const QRect& bounds) { }
|
||||
void setClipFromSource(const QRect& bounds) { }
|
||||
void setBackgroundColor(const xColor& color) { }
|
||||
void setAlpha(float) { }
|
||||
void setImageURL(const QUrl& ) { }
|
||||
void setX(int x) { _bounds.setX(x); }
|
||||
void setY(int y) { _bounds.setY(y); }
|
||||
void setWidth(int width) { _bounds.setWidth(width); }
|
||||
void setHeight(int height) { _bounds.setHeight(height); }
|
||||
void setBounds(const QRect& bounds) { _bounds = bounds; }
|
||||
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
|
||||
void setBackgroundColor(const xColor& color) { _backgroundColor = color; }
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
void setImageURL(const QUrl& url);
|
||||
void setProperties(const QScriptValue& properties);
|
||||
|
||||
private slots:
|
||||
void replyFinished(QNetworkReply* reply); // we actually want to hide this...
|
||||
|
||||
private:
|
||||
|
||||
QUrl _imageURL;
|
||||
QGLWidget* _parent;
|
||||
QImage _textureImage;
|
||||
|
@ -68,6 +79,9 @@ private:
|
|||
QRect _fromImage; // where from in the image to sample
|
||||
float _alpha;
|
||||
xColor _backgroundColor;
|
||||
bool _renderImage;
|
||||
bool _textureBound;
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(__interface__ImageOverlay__) */
|
||||
|
|
66
interface/src/ui/Overlays.cpp
Normal file
66
interface/src/ui/Overlays.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// Overlays.cpp
|
||||
// interface
|
||||
//
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "Overlays.h"
|
||||
|
||||
unsigned int Overlays::_nextOverlayID = 0;
|
||||
|
||||
Overlays::Overlays() {
|
||||
}
|
||||
|
||||
Overlays::~Overlays() {
|
||||
}
|
||||
|
||||
void Overlays::init(QGLWidget* parent) {
|
||||
qDebug() << "Overlays::init() parent=" << parent;
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
void Overlays::render() {
|
||||
foreach(ImageOverlay* thisOverlay, _imageOverlays) {
|
||||
thisOverlay->render();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make multi-threaded safe
|
||||
unsigned int Overlays::addOverlay(const QScriptValue& properties) {
|
||||
unsigned int thisID = _nextOverlayID;
|
||||
_nextOverlayID++;
|
||||
ImageOverlay* thisOverlay = new ImageOverlay();
|
||||
thisOverlay->init(_parent);
|
||||
thisOverlay->setProperties(properties);
|
||||
_imageOverlays[thisID] = thisOverlay;
|
||||
return thisID;
|
||||
}
|
||||
|
||||
QScriptValue Overlays::getOverlayProperties(unsigned int id) {
|
||||
if (!_imageOverlays.contains(id)) {
|
||||
return QScriptValue();
|
||||
}
|
||||
ImageOverlay* thisOverlay = _imageOverlays[id];
|
||||
return thisOverlay->getProperties();
|
||||
}
|
||||
|
||||
// TODO: make multi-threaded safe
|
||||
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
||||
if (!_imageOverlays.contains(id)) {
|
||||
return false;
|
||||
}
|
||||
ImageOverlay* thisOverlay = _imageOverlays[id];
|
||||
thisOverlay->setProperties(properties);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: make multi-threaded safe
|
||||
void Overlays::deleteOverlay(unsigned int id) {
|
||||
if (_imageOverlays.contains(id)) {
|
||||
_imageOverlays.erase(_imageOverlays.find(id));
|
||||
|
||||
}
|
||||
}
|
||||
|
58
interface/src/ui/Overlays.h
Normal file
58
interface/src/ui/Overlays.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// Overlays.h
|
||||
// interface
|
||||
//
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Overlays__
|
||||
#define __interface__Overlays__
|
||||
|
||||
/**
|
||||
#include <QGLWidget>
|
||||
#include <QImage>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QRect>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
**/
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include "ImageOverlay.h"
|
||||
|
||||
class Overlays : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Overlays();
|
||||
~Overlays();
|
||||
void init(QGLWidget* parent);
|
||||
void render();
|
||||
|
||||
public slots:
|
||||
/// adds an overlay with the specific properties
|
||||
unsigned int addOverlay(const QScriptValue& properties);
|
||||
|
||||
/// gets the current overlay properties for a specific overlay
|
||||
QScriptValue getOverlayProperties(unsigned int id);
|
||||
|
||||
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
|
||||
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
||||
bool editOverlay(unsigned int id, const QScriptValue& properties);
|
||||
|
||||
/// deletes a particle
|
||||
void deleteOverlay(unsigned int id);
|
||||
|
||||
private:
|
||||
QMap<unsigned int, ImageOverlay*> _imageOverlays;
|
||||
static unsigned int _nextOverlayID;
|
||||
QGLWidget* _parent;
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(__interface__Overlays__) */
|
|
@ -23,7 +23,6 @@ OctreeScriptingInterface::OctreeScriptingInterface(OctreeEditPacketSender* packe
|
|||
}
|
||||
|
||||
OctreeScriptingInterface::~OctreeScriptingInterface() {
|
||||
qDebug() << "OctreeScriptingInterface::~OctreeScriptingInterface() this=" << this;
|
||||
cleanupManagedObjects();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue