overte-HifiExperiments/interface/src/ui/overlays/Overlay.cpp
2017-08-04 12:17:54 -07:00

244 lines
6.8 KiB
C++

//
// Overlay.cpp
// interface/src/ui/overlays
//
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Overlay.h"
#include <NumericalConstants.h>
#include <RegisteredMetaTypes.h>
#include "Application.h"
static const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
static const float DEFAULT_ALPHA = 0.7f;
Overlay::Overlay() :
_renderItemID(render::Item::INVALID_ITEM_ID),
_isLoaded(true),
_alpha(DEFAULT_ALPHA),
_pulse(1.0f),
_pulseMax(0.0f),
_pulseMin(0.0f),
_pulsePeriod(1.0f),
_pulseDirection(1.0f),
_lastPulseUpdate(usecTimestampNow()),
_alphaPulse(0.0f),
_colorPulse(0.0f),
_color(DEFAULT_OVERLAY_COLOR),
_visible(true),
_drawHUDLayer(false),
_anchor(NO_ANCHOR)
{
}
Overlay::Overlay(const Overlay* overlay) :
_renderItemID(render::Item::INVALID_ITEM_ID),
_isLoaded(overlay->_isLoaded),
_alpha(overlay->_alpha),
_pulse(overlay->_pulse),
_pulseMax(overlay->_pulseMax),
_pulseMin(overlay->_pulseMin),
_pulsePeriod(overlay->_pulsePeriod),
_pulseDirection(overlay->_pulseDirection),
_lastPulseUpdate(usecTimestampNow()),
_alphaPulse(overlay->_alphaPulse),
_colorPulse(overlay->_colorPulse),
_color(overlay->_color),
_visible(overlay->_visible),
_drawHUDLayer(overlay->_drawHUDLayer),
_anchor(overlay->_anchor)
{
}
Overlay::~Overlay() {
}
void Overlay::setProperties(const QVariantMap& properties) {
bool valid;
auto color = xColorFromVariant(properties["color"], valid);
if (valid) {
_color = color;
}
if (properties["alpha"].isValid()) {
setAlpha(properties["alpha"].toFloat());
}
if (properties["pulseMax"].isValid()) {
setPulseMax(properties["pulseMax"].toFloat());
}
if (properties["pulseMin"].isValid()) {
setPulseMin(properties["pulseMin"].toFloat());
}
if (properties["pulsePeriod"].isValid()) {
setPulsePeriod(properties["pulsePeriod"].toFloat());
}
if (properties["alphaPulse"].isValid()) {
setAlphaPulse(properties["alphaPulse"].toFloat());
}
if (properties["colorPulse"].isValid()) {
setColorPulse(properties["colorPulse"].toFloat());
}
if (properties["drawHUDLayer"].isValid()) {
bool drawHUDLayer = properties["drawHUDLayer"].toBool();
setDrawHUDLayer(drawHUDLayer);
}
if (properties["visible"].isValid()) {
bool visible = properties["visible"].toBool();
setVisible(visible);
}
if (properties["anchor"].isValid()) {
QString property = properties["anchor"].toString();
if (property == "MyAvatar") {
setAnchor(MY_AVATAR);
}
}
}
QVariant Overlay::getProperty(const QString& property) {
if (property == "type") {
return QVariant(getType());
}
if (property == "color") {
return xColorToVariant(_color);
}
if (property == "alpha") {
return _alpha;
}
if (property == "pulseMax") {
return _pulseMax;
}
if (property == "pulseMin") {
return _pulseMin;
}
if (property == "pulsePeriod") {
return _pulsePeriod;
}
if (property == "alphaPulse") {
return _alphaPulse;
}
if (property == "colorPulse") {
return _colorPulse;
}
if (property == "visible") {
return _visible;
}
if (property == "anchor") {
return _anchor == MY_AVATAR ? "MyAvatar" : "";
}
return QVariant();
}
xColor Overlay::getColor() {
if (_colorPulse == 0.0f) {
return _color;
}
float pulseLevel = updatePulse();
xColor result = _color;
if (_colorPulse < 0.0f) {
result.red *= (1.0f - pulseLevel);
result.green *= (1.0f - pulseLevel);
result.blue *= (1.0f - pulseLevel);
} else {
result.red *= pulseLevel;
result.green *= pulseLevel;
result.blue *= pulseLevel;
}
return result;
}
float Overlay::getAlpha() {
if (_alphaPulse == 0.0f) {
return _alpha;
}
float pulseLevel = updatePulse();
return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel);
}
void Overlay::setDrawHUDLayer(bool drawHUDLayer) {
if (drawHUDLayer != _drawHUDLayer) {
qApp->getOverlays().setOverlayDrawHUDLayer(getOverlayID(), drawHUDLayer);
_drawHUDLayer = drawHUDLayer;
}
}
// pulse travels from min to max, then max to min in one period.
float Overlay::updatePulse() {
if (_pulsePeriod <= 0.0f) {
return _pulse;
}
quint64 now = usecTimestampNow();
quint64 elapsedUSecs = (now - _lastPulseUpdate);
float elapsedSeconds = (float)elapsedUSecs / (float)USECS_PER_SECOND;
float elapsedPeriods = elapsedSeconds / _pulsePeriod;
// we can safely remove any "full" periods, since those just rotate us back
// to our final pulse level
elapsedPeriods = fmod(elapsedPeriods, 1.0f);
_lastPulseUpdate = now;
float pulseDistance = (_pulseMax - _pulseMin);
float pulseDistancePerPeriod = pulseDistance * 2.0f;
float pulseDelta = _pulseDirection * pulseDistancePerPeriod * elapsedPeriods;
float newPulse = _pulse + pulseDelta;
float limit = (_pulseDirection > 0.0f) ? _pulseMax : _pulseMin;
float passedLimit = (_pulseDirection > 0.0f) ? (newPulse >= limit) : (newPulse <= limit);
if (passedLimit) {
float pulseDeltaToLimit = newPulse - limit;
float pulseDeltaFromLimitBack = pulseDelta - pulseDeltaToLimit;
pulseDelta = -pulseDeltaFromLimitBack;
_pulseDirection *= -1.0f;
}
_pulse += pulseDelta;
return _pulse;
}
bool Overlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
_renderItemID = scene->allocateID();
transaction.resetItem(_renderItemID, std::make_shared<Overlay::Payload>(overlay));
return true;
}
void Overlay::removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
transaction.removeItem(_renderItemID);
render::Item::clearID(_renderItemID);
}
QScriptValue OverlayIDtoScriptValue(QScriptEngine* engine, const OverlayID& id) {
return quuidToScriptValue(engine, id);
}
void OverlayIDfromScriptValue(const QScriptValue &object, OverlayID& id) {
quuidFromScriptValue(object, id);
}
QVector<OverlayID> qVectorOverlayIDFromScriptValue(const QScriptValue& array) {
if (!array.isArray()) {
return QVector<OverlayID>();
}
QVector<OverlayID> newVector;
int length = array.property("length").toInteger();
newVector.reserve(length);
for (int i = 0; i < length; i++) {
newVector << OverlayID(array.property(i).toString());
}
return newVector;
}