mirror of
https://github.com/overte-org/overte.git
synced 2025-08-11 01:53:10 +02:00
implement text overlay support
This commit is contained in:
parent
0a9f9a7c7a
commit
ef11865d24
12 changed files with 382 additions and 122 deletions
|
@ -44,6 +44,19 @@ for (s = 0; s < numberOfSwatches; s++) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var text = Overlays.addOverlay("text", {
|
||||||
|
x: 200,
|
||||||
|
y: 100,
|
||||||
|
width: 150,
|
||||||
|
height: 50,
|
||||||
|
backgroundColor: { red: 0, green: 0, blue: 0},
|
||||||
|
textColor: { red: 255, green: 0, blue: 0},
|
||||||
|
topMargin: 4,
|
||||||
|
leftMargin: 4,
|
||||||
|
alpha: 0.7,
|
||||||
|
text: "Here is some text.\nAnd a second line."
|
||||||
|
});
|
||||||
|
|
||||||
var toolA = Overlays.addOverlay("image", {
|
var toolA = Overlays.addOverlay("image", {
|
||||||
x: 100,
|
x: 100,
|
||||||
y: 100,
|
y: 100,
|
||||||
|
@ -97,6 +110,7 @@ function scriptEnding() {
|
||||||
}
|
}
|
||||||
Overlays.deleteOverlay(thumb);
|
Overlays.deleteOverlay(thumb);
|
||||||
Overlays.deleteOverlay(slider);
|
Overlays.deleteOverlay(slider);
|
||||||
|
Overlays.deleteOverlay(text);
|
||||||
}
|
}
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
||||||
|
@ -132,10 +146,14 @@ function mouseMoveEvent(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function mousePressEvent(event) {
|
function mousePressEvent(event) {
|
||||||
|
var clickedText = false;
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||||
if (clickedOverlay == thumb) {
|
if (clickedOverlay == thumb) {
|
||||||
movingSlider = true;
|
movingSlider = true;
|
||||||
thumbClickOffsetX = event.x - thumbX;
|
thumbClickOffsetX = event.x - thumbX;
|
||||||
|
} else if (clickedOverlay == text) {
|
||||||
|
Overlays.editOverlay(text, { text: "you clicked here:\n " + event.x + "," + event.y } );
|
||||||
|
clickedText = true;
|
||||||
} else {
|
} else {
|
||||||
for (s = 0; s < numberOfSwatches; s++) {
|
for (s = 0; s < numberOfSwatches; s++) {
|
||||||
if (clickedOverlay == swatches[s]) {
|
if (clickedOverlay == swatches[s]) {
|
||||||
|
@ -145,6 +163,9 @@ function mousePressEvent(event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!clickedText) {
|
||||||
|
Overlays.editOverlay(text, { text: "you didn't click here" } );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseReleaseEvent(event) {
|
function mouseReleaseEvent(event) {
|
||||||
|
|
|
@ -19,15 +19,6 @@
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
// the standard sans serif font family
|
|
||||||
#define SANS_FONT_FAMILY "Helvetica"
|
|
||||||
|
|
||||||
// the standard mono font family
|
|
||||||
#define MONO_FONT_FAMILY "Courier"
|
|
||||||
|
|
||||||
// the Inconsolata font family
|
|
||||||
#define INCONSOLATA_FONT_FAMILY "Inconsolata"
|
|
||||||
|
|
||||||
void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * fwd, glm::vec3 * left, glm::vec3 * up);
|
void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * fwd, glm::vec3 * left, glm::vec3 * up);
|
||||||
|
|
||||||
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos);
|
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos);
|
||||||
|
|
|
@ -14,23 +14,13 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
ImageOverlay::ImageOverlay() :
|
ImageOverlay::ImageOverlay() :
|
||||||
_parent(NULL),
|
|
||||||
_textureID(0),
|
_textureID(0),
|
||||||
_alpha(DEFAULT_ALPHA),
|
|
||||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
|
||||||
_visible(true),
|
|
||||||
_renderImage(false),
|
_renderImage(false),
|
||||||
_textureBound(false),
|
_textureBound(false),
|
||||||
_wantClipFromImage(false)
|
_wantClipFromImage(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageOverlay::init(QGLWidget* parent) {
|
|
||||||
qDebug() << "ImageOverlay::init() parent=" << parent;
|
|
||||||
_parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ImageOverlay::~ImageOverlay() {
|
ImageOverlay::~ImageOverlay() {
|
||||||
if (_parent && _textureID) {
|
if (_parent && _textureID) {
|
||||||
// do we need to call this?
|
// do we need to call this?
|
||||||
|
@ -114,44 +104,9 @@ void ImageOverlay::render() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle only setting the included values...
|
|
||||||
void ImageOverlay::setProperties(const QScriptValue& properties) {
|
void ImageOverlay::setProperties(const QScriptValue& properties) {
|
||||||
//qDebug() << "ImageOverlay::setProperties()... properties=" << &properties;
|
Overlay::setProperties(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 {
|
|
||||||
QRect oldBounds = getBounds();
|
|
||||||
QRect newBounds = oldBounds;
|
|
||||||
|
|
||||||
if (properties.property("x").isValid()) {
|
|
||||||
newBounds.setX(properties.property("x").toVariant().toInt());
|
|
||||||
} else {
|
|
||||||
newBounds.setX(oldBounds.x());
|
|
||||||
}
|
|
||||||
if (properties.property("y").isValid()) {
|
|
||||||
newBounds.setY(properties.property("y").toVariant().toInt());
|
|
||||||
} else {
|
|
||||||
newBounds.setY(oldBounds.y());
|
|
||||||
}
|
|
||||||
if (properties.property("width").isValid()) {
|
|
||||||
newBounds.setWidth(properties.property("width").toVariant().toInt());
|
|
||||||
} else {
|
|
||||||
newBounds.setWidth(oldBounds.width());
|
|
||||||
}
|
|
||||||
if (properties.property("height").isValid()) {
|
|
||||||
newBounds.setHeight(properties.property("height").toVariant().toInt());
|
|
||||||
} else {
|
|
||||||
newBounds.setHeight(oldBounds.height());
|
|
||||||
}
|
|
||||||
setBounds(newBounds);
|
|
||||||
//qDebug() << "set bounds to " << getBounds();
|
|
||||||
}
|
|
||||||
QScriptValue subImageBounds = properties.property("subImage");
|
QScriptValue subImageBounds = properties.property("subImage");
|
||||||
if (subImageBounds.isValid()) {
|
if (subImageBounds.isValid()) {
|
||||||
QRect oldSubImageRect = _fromImage;
|
QRect oldSubImageRect = _fromImage;
|
||||||
|
@ -183,26 +138,6 @@ void ImageOverlay::setProperties(const QScriptValue& properties) {
|
||||||
if (imageURL.isValid()) {
|
if (imageURL.isValid()) {
|
||||||
setImageURL(imageURL.toVariant().toString());
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (properties.property("alpha").isValid()) {
|
|
||||||
setAlpha(properties.property("alpha").toVariant().toFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (properties.property("visible").isValid()) {
|
|
||||||
setVisible(properties.property("visible").toVariant().toBool());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,43 +22,24 @@
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 };
|
#include "Overlay.h"
|
||||||
const float DEFAULT_ALPHA = 0.7f;
|
|
||||||
|
|
||||||
class ImageOverlay : QObject {
|
class ImageOverlay : public Overlay {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImageOverlay();
|
ImageOverlay();
|
||||||
~ImageOverlay();
|
~ImageOverlay();
|
||||||
void init(QGLWidget* parent);
|
virtual void render();
|
||||||
void render();
|
|
||||||
|
|
||||||
//public slots:
|
|
||||||
// getters
|
// getters
|
||||||
bool getVisible() const { return _visible; }
|
|
||||||
int getX() const { return _bounds.x(); }
|
|
||||||
int getY() const { return _bounds.y(); }
|
|
||||||
int getWidth() const { return _bounds.width(); }
|
|
||||||
int getHeight() const { return _bounds.height(); }
|
|
||||||
const QRect& getBounds() const { return _bounds; }
|
|
||||||
const QRect& getClipFromSource() const { return _fromImage; }
|
const QRect& getClipFromSource() const { return _fromImage; }
|
||||||
const xColor& getBackgroundColor() const { return _backgroundColor; }
|
|
||||||
float getAlpha() const { return _alpha; }
|
|
||||||
const QUrl& getImageURL() const { return _imageURL; }
|
const QUrl& getImageURL() const { return _imageURL; }
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setVisible(bool visible) { _visible = visible; }
|
|
||||||
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; _wantClipFromImage = true; }
|
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; _wantClipFromImage = true; }
|
||||||
void setBackgroundColor(const xColor& color) { _backgroundColor = color; }
|
|
||||||
void setAlpha(float alpha) { _alpha = alpha; }
|
|
||||||
void setImageURL(const QUrl& url);
|
void setImageURL(const QUrl& url);
|
||||||
void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void replyFinished(QNetworkReply* reply); // we actually want to hide this...
|
void replyFinished(QNetworkReply* reply); // we actually want to hide this...
|
||||||
|
@ -66,14 +47,9 @@ private slots:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QUrl _imageURL;
|
QUrl _imageURL;
|
||||||
QGLWidget* _parent;
|
|
||||||
QImage _textureImage;
|
QImage _textureImage;
|
||||||
GLuint _textureID;
|
GLuint _textureID;
|
||||||
QRect _bounds; // where on the screen to draw
|
|
||||||
QRect _fromImage; // where from in the image to sample
|
QRect _fromImage; // where from in the image to sample
|
||||||
float _alpha;
|
|
||||||
xColor _backgroundColor;
|
|
||||||
bool _visible; // should the overlay be drawn at all
|
|
||||||
bool _renderImage; // is there an image associated with this overlay, or is it just a colored rectangle
|
bool _renderImage; // is there an image associated with this overlay, or is it just a colored rectangle
|
||||||
bool _textureBound; // has the texture been bound
|
bool _textureBound; // has the texture been bound
|
||||||
bool _wantClipFromImage;
|
bool _wantClipFromImage;
|
||||||
|
|
88
interface/src/ui/Overlay.cpp
Normal file
88
interface/src/ui/Overlay.cpp
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// Overlay.cpp
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include "Overlay.h"
|
||||||
|
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QGLWidget>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
Overlay::Overlay() :
|
||||||
|
_parent(NULL),
|
||||||
|
_alpha(DEFAULT_ALPHA),
|
||||||
|
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||||
|
_visible(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlay::init(QGLWidget* parent) {
|
||||||
|
_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Overlay::~Overlay() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlay::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 {
|
||||||
|
QRect oldBounds = getBounds();
|
||||||
|
QRect newBounds = oldBounds;
|
||||||
|
|
||||||
|
if (properties.property("x").isValid()) {
|
||||||
|
newBounds.setX(properties.property("x").toVariant().toInt());
|
||||||
|
} else {
|
||||||
|
newBounds.setX(oldBounds.x());
|
||||||
|
}
|
||||||
|
if (properties.property("y").isValid()) {
|
||||||
|
newBounds.setY(properties.property("y").toVariant().toInt());
|
||||||
|
} else {
|
||||||
|
newBounds.setY(oldBounds.y());
|
||||||
|
}
|
||||||
|
if (properties.property("width").isValid()) {
|
||||||
|
newBounds.setWidth(properties.property("width").toVariant().toInt());
|
||||||
|
} else {
|
||||||
|
newBounds.setWidth(oldBounds.width());
|
||||||
|
}
|
||||||
|
if (properties.property("height").isValid()) {
|
||||||
|
newBounds.setHeight(properties.property("height").toVariant().toInt());
|
||||||
|
} else {
|
||||||
|
newBounds.setHeight(oldBounds.height());
|
||||||
|
}
|
||||||
|
setBounds(newBounds);
|
||||||
|
//qDebug() << "set bounds to " << getBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.property("alpha").isValid()) {
|
||||||
|
setAlpha(properties.property("alpha").toVariant().toFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.property("visible").isValid()) {
|
||||||
|
setVisible(properties.property("visible").toVariant().toBool());
|
||||||
|
}
|
||||||
|
}
|
64
interface/src/ui/Overlay.h
Normal file
64
interface/src/ui/Overlay.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// Overlay.h
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __interface__Overlay__
|
||||||
|
#define __interface__Overlay__
|
||||||
|
|
||||||
|
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
|
#include <QGLWidget>
|
||||||
|
#include <QRect>
|
||||||
|
#include <QScriptValue>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <SharedUtil.h> // for xColor
|
||||||
|
|
||||||
|
const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 };
|
||||||
|
const float DEFAULT_ALPHA = 0.7f;
|
||||||
|
|
||||||
|
class Overlay : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Overlay();
|
||||||
|
~Overlay();
|
||||||
|
void init(QGLWidget* parent);
|
||||||
|
virtual void render() = 0;
|
||||||
|
|
||||||
|
// getters
|
||||||
|
bool getVisible() const { return _visible; }
|
||||||
|
int getX() const { return _bounds.x(); }
|
||||||
|
int getY() const { return _bounds.y(); }
|
||||||
|
int getWidth() const { return _bounds.width(); }
|
||||||
|
int getHeight() const { return _bounds.height(); }
|
||||||
|
const QRect& getBounds() const { return _bounds; }
|
||||||
|
const xColor& getBackgroundColor() const { return _backgroundColor; }
|
||||||
|
float getAlpha() const { return _alpha; }
|
||||||
|
|
||||||
|
// setters
|
||||||
|
void setVisible(bool visible) { _visible = visible; }
|
||||||
|
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 setBackgroundColor(const xColor& color) { _backgroundColor = color; }
|
||||||
|
void setAlpha(float alpha) { _alpha = alpha; }
|
||||||
|
|
||||||
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QGLWidget* _parent;
|
||||||
|
QRect _bounds; // where on the screen to draw
|
||||||
|
float _alpha;
|
||||||
|
xColor _backgroundColor;
|
||||||
|
bool _visible; // should the overlay be drawn at all
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* defined(__interface__Overlay__) */
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
|
|
||||||
#include "Overlays.h"
|
#include "Overlays.h"
|
||||||
|
#include "ImageOverlay.h"
|
||||||
|
#include "TextOverlay.h"
|
||||||
|
|
||||||
|
|
||||||
unsigned int Overlays::_nextOverlayID = 1;
|
unsigned int Overlays::_nextOverlayID = 1;
|
||||||
|
|
||||||
|
@ -21,7 +24,7 @@ void Overlays::init(QGLWidget* parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::render() {
|
void Overlays::render() {
|
||||||
foreach(ImageOverlay* thisOverlay, _imageOverlays) {
|
foreach(Overlay* thisOverlay, _overlays) {
|
||||||
thisOverlay->render();
|
thisOverlay->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,36 +39,44 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
|
||||||
ImageOverlay* thisOverlay = new ImageOverlay();
|
ImageOverlay* thisOverlay = new ImageOverlay();
|
||||||
thisOverlay->init(_parent);
|
thisOverlay->init(_parent);
|
||||||
thisOverlay->setProperties(properties);
|
thisOverlay->setProperties(properties);
|
||||||
_imageOverlays[thisID] = thisOverlay;
|
_overlays[thisID] = thisOverlay;
|
||||||
|
} else if (type == "text") {
|
||||||
|
thisID = _nextOverlayID;
|
||||||
|
_nextOverlayID++;
|
||||||
|
TextOverlay* thisOverlay = new TextOverlay();
|
||||||
|
thisOverlay->init(_parent);
|
||||||
|
thisOverlay->setProperties(properties);
|
||||||
|
_overlays[thisID] = thisOverlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
return thisID;
|
return thisID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make multi-threaded safe
|
// TODO: make multi-threaded safe
|
||||||
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
||||||
if (!_imageOverlays.contains(id)) {
|
if (!_overlays.contains(id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ImageOverlay* thisOverlay = _imageOverlays[id];
|
Overlay* thisOverlay = _overlays[id];
|
||||||
thisOverlay->setProperties(properties);
|
thisOverlay->setProperties(properties);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make multi-threaded safe
|
// TODO: make multi-threaded safe
|
||||||
void Overlays::deleteOverlay(unsigned int id) {
|
void Overlays::deleteOverlay(unsigned int id) {
|
||||||
if (_imageOverlays.contains(id)) {
|
if (_overlays.contains(id)) {
|
||||||
_imageOverlays.erase(_imageOverlays.find(id));
|
_overlays.erase(_overlays.find(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||||
QMapIterator<unsigned int, ImageOverlay*> i(_imageOverlays);
|
QMapIterator<unsigned int, Overlay*> i(_overlays);
|
||||||
i.toBack();
|
i.toBack();
|
||||||
while (i.hasPrevious()) {
|
while (i.hasPrevious()) {
|
||||||
i.previous();
|
i.previous();
|
||||||
unsigned int thisID = i.key();
|
unsigned int thisID = i.key();
|
||||||
ImageOverlay* thisOverlay = i.value();
|
Overlay* thisOverlay = i.value();
|
||||||
if (thisOverlay->getBounds().contains(point.x, point.y, false)) {
|
if (thisOverlay->getVisible() && thisOverlay->getBounds().contains(point.x, point.y, false)) {
|
||||||
return thisID;
|
return thisID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include <QScriptValue>
|
#include <QScriptValue>
|
||||||
|
|
||||||
#include "ImageOverlay.h"
|
#include "Overlay.h"
|
||||||
|
|
||||||
class Overlays : public QObject {
|
class Overlays : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -35,7 +35,7 @@ public slots:
|
||||||
unsigned int getOverlayAtPoint(const glm::vec2& point);
|
unsigned int getOverlayAtPoint(const glm::vec2& point);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<unsigned int, ImageOverlay*> _imageOverlays;
|
QMap<unsigned int, Overlay*> _overlays;
|
||||||
static unsigned int _nextOverlayID;
|
static unsigned int _nextOverlayID;
|
||||||
QGLWidget* _parent;
|
QGLWidget* _parent;
|
||||||
};
|
};
|
||||||
|
|
80
interface/src/ui/TextOverlay.cpp
Normal file
80
interface/src/ui/TextOverlay.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
//
|
||||||
|
// TextOverlay.cpp
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <QGLWidget>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include "TextOverlay.h"
|
||||||
|
#include "TextRenderer.h"
|
||||||
|
|
||||||
|
TextOverlay::TextOverlay() :
|
||||||
|
_leftMargin(DEFAULT_MARGIN),
|
||||||
|
_topMargin(DEFAULT_MARGIN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TextOverlay::~TextOverlay() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextOverlay::render() {
|
||||||
|
if (!_visible) {
|
||||||
|
return; // do nothing if we're not visible
|
||||||
|
}
|
||||||
|
|
||||||
|
const float MAX_COLOR = 255;
|
||||||
|
glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glVertex2f(_bounds.left(), _bounds.top());
|
||||||
|
glVertex2f(_bounds.right(), _bounds.top());
|
||||||
|
glVertex2f(_bounds.right(), _bounds.bottom());
|
||||||
|
glVertex2f(_bounds.left(), _bounds.bottom());
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
//TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false,
|
||||||
|
// EffectType effect = NO_EFFECT, int effectThickness = 1);
|
||||||
|
|
||||||
|
TextRenderer textRenderer(SANS_FONT_FAMILY, 11, 50);
|
||||||
|
const int leftAdjust = -1; // required to make text render relative to left edge of bounds
|
||||||
|
const int topAdjust = -2; // required to make text render relative to top edge of bounds
|
||||||
|
int x = _bounds.left() + _leftMargin + leftAdjust;
|
||||||
|
int y = _bounds.top() + _topMargin + topAdjust;
|
||||||
|
|
||||||
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
|
QStringList lines = _text.split("\n");
|
||||||
|
int lineOffset = 0;
|
||||||
|
foreach(QString thisLine, lines) {
|
||||||
|
if (lineOffset == 0) {
|
||||||
|
lineOffset = textRenderer.calculateHeight(qPrintable(thisLine));
|
||||||
|
}
|
||||||
|
lineOffset += textRenderer.draw(x, y + lineOffset, qPrintable(thisLine));
|
||||||
|
|
||||||
|
const int lineGap = 2;
|
||||||
|
lineOffset += lineGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextOverlay::setProperties(const QScriptValue& properties) {
|
||||||
|
Overlay::setProperties(properties);
|
||||||
|
|
||||||
|
QScriptValue text = properties.property("text");
|
||||||
|
if (text.isValid()) {
|
||||||
|
setText(text.toVariant().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.property("leftMargin").isValid()) {
|
||||||
|
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.property("topMargin").isValid()) {
|
||||||
|
setTopMargin(properties.property("topMargin").toVariant().toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
58
interface/src/ui/TextOverlay.h
Normal file
58
interface/src/ui/TextOverlay.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// TextOverlay.h
|
||||||
|
// interface
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __interface__TextOverlay__
|
||||||
|
#define __interface__TextOverlay__
|
||||||
|
|
||||||
|
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
|
#include <QGLWidget>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QRect>
|
||||||
|
#include <QScriptValue>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include "Overlay.h"
|
||||||
|
|
||||||
|
const int DEFAULT_MARGIN = 10;
|
||||||
|
|
||||||
|
class TextOverlay : public Overlay {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextOverlay();
|
||||||
|
~TextOverlay();
|
||||||
|
virtual void render();
|
||||||
|
|
||||||
|
// getters
|
||||||
|
const QString& getText() const { return _text; }
|
||||||
|
int getLeftMargin() const { return _leftMargin; }
|
||||||
|
int getTopMargin() const { return _topMargin; }
|
||||||
|
|
||||||
|
// setters
|
||||||
|
void setText(const QString& text) { _text = text; }
|
||||||
|
void setLeftMargin(int margin) { _leftMargin = margin; }
|
||||||
|
void setTopMargin(int margin) { _topMargin = margin; }
|
||||||
|
|
||||||
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString _text;
|
||||||
|
int _leftMargin;
|
||||||
|
int _topMargin;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* defined(__interface__TextOverlay__) */
|
|
@ -8,6 +8,8 @@
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QPaintEngine>
|
#include <QPaintEngine>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "TextRenderer.h"
|
#include "TextRenderer.h"
|
||||||
|
@ -30,10 +32,25 @@ TextRenderer::~TextRenderer() {
|
||||||
glDeleteTextures(_allTextureIDs.size(), _allTextureIDs.constData());
|
glDeleteTextures(_allTextureIDs.size(), _allTextureIDs.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextRenderer::draw(int x, int y, const char* str) {
|
int TextRenderer::calculateHeight(const char* str) {
|
||||||
|
int maxHeight = 0;
|
||||||
|
for (const char* ch = str; *ch != 0; ch++) {
|
||||||
|
const Glyph& glyph = getGlyph(*ch);
|
||||||
|
if (glyph.textureID() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glyph.bounds().height() > maxHeight) {
|
||||||
|
maxHeight = glyph.bounds().height();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextRenderer::draw(int x, int y, const char* str) {
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
int maxHeight = 0;
|
||||||
for (const char* ch = str; *ch != 0; ch++) {
|
for (const char* ch = str; *ch != 0; ch++) {
|
||||||
const Glyph& glyph = getGlyph(*ch);
|
const Glyph& glyph = getGlyph(*ch);
|
||||||
if (glyph.textureID() == 0) {
|
if (glyph.textureID() == 0) {
|
||||||
|
@ -41,19 +58,23 @@ void TextRenderer::draw(int x, int y, const char* str) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (glyph.bounds().height() > maxHeight) {
|
||||||
|
maxHeight = glyph.bounds().height();
|
||||||
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, glyph.textureID());
|
glBindTexture(GL_TEXTURE_2D, glyph.textureID());
|
||||||
|
|
||||||
int left = x + glyph.bounds().x();
|
int left = x + glyph.bounds().x();
|
||||||
int right = x + glyph.bounds().x() + glyph.bounds().width();
|
int right = x + glyph.bounds().x() + glyph.bounds().width();
|
||||||
int bottom = y + glyph.bounds().y();
|
int bottom = y + glyph.bounds().y();
|
||||||
int top = y + glyph.bounds().y() + glyph.bounds().height();
|
int top = y + glyph.bounds().y() + glyph.bounds().height();
|
||||||
|
|
||||||
float scale = 1.0 / IMAGE_SIZE;
|
float scale = 1.0 / IMAGE_SIZE;
|
||||||
float ls = glyph.location().x() * scale;
|
float ls = glyph.location().x() * scale;
|
||||||
float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
|
float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
|
||||||
float bt = glyph.location().y() * scale;
|
float bt = glyph.location().y() * scale;
|
||||||
float tt = (glyph.location().y() + glyph.bounds().height()) * scale;
|
float tt = (glyph.location().y() + glyph.bounds().height()) * scale;
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(ls, bt);
|
glTexCoord2f(ls, bt);
|
||||||
glVertex2f(left, bottom);
|
glVertex2f(left, bottom);
|
||||||
|
@ -64,12 +85,13 @@ void TextRenderer::draw(int x, int y, const char* str) {
|
||||||
glTexCoord2f(ls, tt);
|
glTexCoord2f(ls, tt);
|
||||||
glVertex2f(left, top);
|
glVertex2f(left, top);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
x += glyph.width();
|
x += glyph.width();
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
return maxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextRenderer::computeWidth(char ch)
|
int TextRenderer::computeWidth(char ch)
|
||||||
|
|
|
@ -20,6 +20,16 @@
|
||||||
// a special "character" that renders as a solid block
|
// a special "character" that renders as a solid block
|
||||||
const char SOLID_BLOCK_CHAR = 127;
|
const char SOLID_BLOCK_CHAR = 127;
|
||||||
|
|
||||||
|
// the standard sans serif font family
|
||||||
|
#define SANS_FONT_FAMILY "Helvetica"
|
||||||
|
|
||||||
|
// the standard mono font family
|
||||||
|
#define MONO_FONT_FAMILY "Courier"
|
||||||
|
|
||||||
|
// the Inconsolata font family
|
||||||
|
#define INCONSOLATA_FONT_FAMILY "Inconsolata"
|
||||||
|
|
||||||
|
|
||||||
class Glyph;
|
class Glyph;
|
||||||
|
|
||||||
class TextRenderer {
|
class TextRenderer {
|
||||||
|
@ -33,7 +43,11 @@ public:
|
||||||
|
|
||||||
const QFontMetrics& metrics() const { return _metrics; }
|
const QFontMetrics& metrics() const { return _metrics; }
|
||||||
|
|
||||||
void draw(int x, int y, const char* str);
|
// returns the height of the tallest character
|
||||||
|
int calculateHeight(const char* str);
|
||||||
|
|
||||||
|
// also returns the height of the tallest character
|
||||||
|
int draw(int x, int y, const char* str);
|
||||||
|
|
||||||
int computeWidth(char ch);
|
int computeWidth(char ch);
|
||||||
int computeWidth(const char* str);
|
int computeWidth(const char* str);
|
||||||
|
|
Loading…
Reference in a new issue