Merge branch 'master' of https://github.com/highfidelity/hifi into skin

This commit is contained in:
samcake 2016-06-22 09:06:47 -07:00
commit 90e5697940
50 changed files with 799 additions and 300 deletions

View file

@ -13,13 +13,13 @@ We no longer require install of qt5 via our [homebrew formulas repository](https
Assuming you've installed OpenSSL or Qt 5 using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR and QT_CMAKE_PREFIX_PATH so CMake can find your installations.
For OpenSSL installed via homebrew, set OPENSSL_ROOT_DIR:
export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2d_1
export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2h_1/
For Qt 5.5.1 installed via homebrew, set QT_CMAKE_PREFIX_PATH as follows.
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.5.1_2/lib/cmake
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt55/5.5.1/lib/cmake
Not that these use the versions from homebrew formulae at the time of this writing, and the version in the path will likely change.
Note that these use the versions from homebrew formulae at the time of this writing, and the version in the path will likely change.
###Xcode
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.

View file

@ -4,8 +4,8 @@ set(EXTERNAL_NAME neuron)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
set(NEURON_URL "https://s3.amazonaws.com/hifi-public/dependencies/neuron_datareader_b.12.zip")
set(NEURON_URL_MD5 "0ab54ca04c9cc8094e0fa046c226e574")
set(NEURON_URL "https://s3.amazonaws.com/hifi-public/dependencies/neuron_datareader_b.12.2.zip")
set(NEURON_URL_MD5 "84273ad2200bf86a9279d1f412a822ca")
ExternalProject_Add(${EXTERNAL_NAME}
URL ${NEURON_URL}

View file

@ -1,5 +1,5 @@
{
"version": 1.4,
"version": 1.5,
"settings": [
{
"name": "metaverse",
@ -116,6 +116,7 @@
"name": "hosts",
"label": "Hosts",
"type": "table",
"can_add_new_rows": true,
"help": "Usernames of hosts who can reliably show your domain to new visitors.",
"numbered": false,
"columns": [
@ -130,6 +131,7 @@
"name": "tags",
"label": "Tags",
"type": "table",
"can_add_new_rows": true,
"help": "Common categories under which your domain falls.",
"numbered": false,
"columns": [
@ -139,6 +141,218 @@
"can_set": true
}
]
},
{
"label": "Operating Hours",
"help": "\"Open\" domains can be searched using their operating hours. Hours are entered in the local timezone, selected below.",
"name": "weekday_hours",
"caption": "Weekday Hours (Monday-Friday)",
"type": "table",
"can_add_new_rows": false,
"columns": [
{
"name": "open",
"label": "Opening Time",
"type": "time",
"default": "00:00",
"editable": true
},
{
"name": "close",
"label": "Closing Time",
"type": "time",
"default": "23:59",
"editable": true
}
]
},
{
"name": "weekend_hours",
"label": "Weekend Hours (Saturday/Sunday)",
"type": "table",
"can_add_new_rows": false,
"columns": [
{
"name": "open",
"label": "Opening Time",
"type": "time",
"default": "00:00",
"editable": true
},
{
"name": "close",
"label": "Closing Time",
"type": "time",
"default": "23:59",
"editable": true
}
]
},
{
"label": "Time Zone",
"name": "utc_offset",
"caption": "Time Zone",
"help": "This server's time zone. Used to define your server's operating hours.",
"type": "select",
"options": [
{
"value": "-12",
"label": "UTC-12:00"
},
{
"value": "-11",
"label": "UTC-11:00"
},
{
"value": "-10",
"label": "UTC-10:00"
},
{
"value": "-9.5",
"label": "UTC-09:30"
},
{
"value": "-9",
"label": "UTC-09:00"
},
{
"value": "-8",
"label": "UTC-08:00"
},
{
"value": "-7",
"label": "UTC-07:00"
},
{
"value": "-6",
"label": "UTC-06:00"
},
{
"value": "-5",
"label": "UTC-05:00"
},
{
"value": "-4",
"label": "UTC-04:00"
},
{
"value": "-3.5",
"label": "UTC-03:30"
},
{
"value": "-3",
"label": "UTC-03:00"
},
{
"value": "-2",
"label": "UTC-02:00"
},
{
"value": "-1",
"label": "UTC-01:00"
},
{
"value": "",
"label": "UTC±00:00"
},
{
"value": "1",
"label": "UTC+01:00"
},
{
"value": "2",
"label": "UTC+02:00"
},
{
"value": "3",
"label": "UTC+03:00"
},
{
"value": "3.5",
"label": "UTC+03:30"
},
{
"value": "4",
"label": "UTC+04:00"
},
{
"value": "4.5",
"label": "UTC+04:30"
},
{
"value": "5",
"label": "UTC+05:00"
},
{
"value": "5.5",
"label": "UTC+05:30"
},
{
"value": "5.75",
"label": "UTC+05:45"
},
{
"value": "6",
"label": "UTC+06:00"
},
{
"value": "6.5",
"label": "UTC+06:30"
},
{
"value": "7",
"label": "UTC+07:00"
},
{
"value": "8",
"label": "UTC+08:00"
},
{
"value": "8.5",
"label": "UTC+08:30"
},
{
"value": "8.75",
"label": "UTC+08:45"
},
{
"value": "9",
"label": "UTC+09:00"
},
{
"value": "9.5",
"label": "UTC+09:30"
},
{
"value": "10",
"label": "UTC+10:00"
},
{
"value": "10.5",
"label": "UTC+10:30"
},
{
"value": "11",
"label": "UTC+11:00"
},
{
"value": "12",
"label": "UTC+12:00"
},
{
"value": "12.75",
"label": "UTC+12:45"
},
{
"value": "13",
"label": "UTC+13:00"
},
{
"value": "14",
"label": "UTC+14:00"
}
]
}
]
},

View file

@ -243,6 +243,16 @@ $(document).ready(function(){
}
});
$('#' + Settings.FORM_ID).on('change', 'input.table-time', function() {
// Bootstrap switches in table: set the changed data attribute for all rows in table.
var row = $(this).closest('tr');
if (row.hasClass("value-row")) { // Don't set attribute on input row switches prior to it being added to table.
row.find('td.' + Settings.DATA_COL_CLASS + ' input').attr('data-changed', true);
updateDataChangedForSiblingRows(row, true);
badgeSidebarForDifferences($(this));
}
});
$('.advanced-toggle').click(function(){
Settings.showAdvanced = !Settings.showAdvanced
var advancedSelector = $('.' + Settings.ADVANCED_CLASS)
@ -987,7 +997,7 @@ function makeTable(setting, keypath, setting_value, isLocked) {
html += "<td class='key'>" + rowIndexOrName + "</td>"
}
var isNonDeletableRow = false;
var isNonDeletableRow = !setting.can_add_new_rows;
_.each(setting.columns, function(col) {
@ -1007,6 +1017,10 @@ function makeTable(setting, keypath, setting_value, isLocked) {
html += "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>"
+ "<input type='checkbox' class='form-control table-checkbox' "
+ "name='" + colName + "'" + (colValue ? " checked" : "") + " /></td>";
} else if (isArray && col.type === "time" && col.editable) {
html += "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>"
+ "<input type='time' class='form-control table-time' "
+ "name='" + colName + "' value='" + (colValue || col.default || "00:00") + "' /></td>";
} else {
// Use a hidden input so that the values are posted.
html += "<td class='" + Settings.DATA_COL_CLASS + "' name='" + colName + "'>"
@ -1196,15 +1210,21 @@ function addTableRow(add_glyphicon) {
// Hide inputs
var input = $(element).find("input")
var isCheckbox = false;
var isTime = false;
if (input.hasClass("table-checkbox")) {
input = $(input).parent();
isCheckbox = true;
} else if (input.hasClass("table-time")) {
input = $(input).parent();
isTime = true;
}
var val = input.val();
if (isCheckbox) {
val = $(input).find("input").is(':checked');
// don't hide the checkbox
val = $(input).find("input").is(':checked');
} else if (isTime) {
// don't hide the time
} else {
input.attr("type", "hidden")
}

View file

@ -10,16 +10,18 @@
#include "DomainMetadata.h"
#include <HifiConfigVariantMap.h>
#include <AccountManager.h>
#include <DependencyManager.h>
#include <HifiConfigVariantMap.h>
#include <LimitedNodeList.h>
#include "DomainServer.h"
#include "DomainServerNodeData.h"
const QString DomainMetadata::USERS = "users";
const QString DomainMetadata::USERS_NUM_TOTAL = "num_users";
const QString DomainMetadata::USERS_NUM_ANON = "num_anon_users";
const QString DomainMetadata::USERS_HOSTNAMES = "user_hostnames";
const QString DomainMetadata::Users::NUM_TOTAL = "num_users";
const QString DomainMetadata::Users::NUM_ANON = "num_anon_users";
const QString DomainMetadata::Users::HOSTNAMES = "user_hostnames";
// users metadata will appear as (JSON):
// { "num_users": Number,
// "num_anon_users": Number,
@ -27,26 +29,30 @@ const QString DomainMetadata::USERS_HOSTNAMES = "user_hostnames";
// }
const QString DomainMetadata::DESCRIPTORS = "descriptors";
const QString DomainMetadata::DESCRIPTORS_DESCRIPTION = "description";
const QString DomainMetadata::DESCRIPTORS_CAPACITY = "capacity"; // parsed from security
const QString DomainMetadata::DESCRIPTORS_RESTRICTION = "restriction"; // parsed from ACL
const QString DomainMetadata::DESCRIPTORS_MATURITY = "maturity";
const QString DomainMetadata::DESCRIPTORS_HOSTS = "hosts";
const QString DomainMetadata::DESCRIPTORS_TAGS = "tags";
const QString DomainMetadata::Descriptors::DESCRIPTION = "description";
const QString DomainMetadata::Descriptors::CAPACITY = "capacity"; // parsed from security
const QString DomainMetadata::Descriptors::RESTRICTION = "restriction"; // parsed from ACL
const QString DomainMetadata::Descriptors::MATURITY = "maturity";
const QString DomainMetadata::Descriptors::HOSTS = "hosts";
const QString DomainMetadata::Descriptors::TAGS = "tags";
const QString DomainMetadata::Descriptors::HOURS = "hours";
const QString DomainMetadata::Descriptors::Hours::WEEKDAY = "weekday";
const QString DomainMetadata::Descriptors::Hours::WEEKEND = "weekend";
const QString DomainMetadata::Descriptors::Hours::UTC_OFFSET = "utc_offset";
const QString DomainMetadata::Descriptors::Hours::OPEN = "open";
const QString DomainMetadata::Descriptors::Hours::CLOSE = "close";
// descriptors metadata will appear as (JSON):
// { "capacity": Number,
// TODO: "hours": String, // UTF-8 representation of the week, split into 15" segments
// { "description": String, // capped description
// "capacity": Number,
// "restriction": String, // enum of either open, hifi, or acl
// "maturity": String, // enum corresponding to ESRB ratings
// "hosts": [ String ], // capped list of usernames
// "description": String, // capped description
// TODO: "img": {
// "src": String,
// "type": String,
// "size": Number,
// "updated_at": Number,
// },
// "tags": [ String ], // capped list of tags
// "hours": {
// "utc_offset": Number,
// "weekday": [ { "open": Time, "close": Time } ],
// "weekend": [ { "open": Time, "close": Time } ],
// }
// }
// metadata will appear as (JSON):
@ -54,36 +60,159 @@ const QString DomainMetadata::DESCRIPTORS_TAGS = "tags";
//
// it is meant to be sent to and consumed by an external API
DomainMetadata::DomainMetadata() {
_metadata[USERS] = {};
_metadata[DESCRIPTORS] = {};
DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) {
// set up the structure necessary for casting during parsing (see parseHours, esp.)
_metadata[USERS] = QVariantMap {};
_metadata[DESCRIPTORS] = QVariantMap {
{ Descriptors::HOURS, QVariantMap {
{ Descriptors::Hours::WEEKDAY, QVariantList { QVariantMap{} } },
{ Descriptors::Hours::WEEKEND, QVariantList { QVariantMap{} } }
} }
};
assert(dynamic_cast<DomainServer*>(domainServer));
DomainServer* server = static_cast<DomainServer*>(domainServer);
// update the metadata when a user (dis)connects
connect(server, &DomainServer::userConnected, this, &DomainMetadata::usersChanged);
connect(server, &DomainServer::userDisconnected, this, &DomainMetadata::usersChanged);
// update the metadata when security changes
connect(&server->_settingsManager, &DomainServerSettingsManager::updateNodePermissions,
this, static_cast<void(DomainMetadata::*)()>(&DomainMetadata::securityChanged));
// initialize the descriptors
securityChanged(false);
descriptorsChanged();
}
void DomainMetadata::setDescriptors(QVariantMap& settings) {
QJsonObject DomainMetadata::get() {
maybeUpdateUsers();
return QJsonObject::fromVariantMap(_metadata);
}
QJsonObject DomainMetadata::get(const QString& group) {
maybeUpdateUsers();
return QJsonObject::fromVariantMap(_metadata[group].toMap());
}
void parseHours(QVariant delta, QVariant& target) {
using Hours = DomainMetadata::Descriptors::Hours;
// hours should be of the form [ { open: Time, close: Time } ]
assert(target.canConvert<QVariantList>());
auto& targetList = *static_cast<QVariantList*>(target.data());
// if/when multiple ranges are allowed, this list will need to be iterated
assert(targetList[0].canConvert<QVariantMap>());
auto& targetMap = *static_cast<QVariantMap*>(targetList[0].data());
auto deltaMap = delta.toList()[0].toMap();
if (deltaMap.isEmpty()) {
return;
}
// merge delta into base
auto open = deltaMap.find(Hours::OPEN);
if (open != deltaMap.end()) {
targetMap[Hours::OPEN] = open.value();
}
assert(targetMap[Hours::OPEN].canConvert<QString>());
auto close = deltaMap.find(Hours::CLOSE);
if (close != deltaMap.end()) {
targetMap[Hours::CLOSE] = close.value();
}
assert(targetMap[Hours::CLOSE].canConvert<QString>());
}
void DomainMetadata::descriptorsChanged() {
// get descriptors
assert(_metadata[DESCRIPTORS].canConvert<QVariantMap>());
auto& state = *static_cast<QVariantMap*>(_metadata[DESCRIPTORS].data());
auto settings = static_cast<DomainServer*>(parent())->_settingsManager.getSettingsMap();
auto descriptors = settings[DESCRIPTORS].toMap();
// copy simple descriptors (description/maturity)
state[Descriptors::DESCRIPTION] = descriptors[Descriptors::DESCRIPTION];
state[Descriptors::MATURITY] = descriptors[Descriptors::MATURITY];
// copy array descriptors (hosts/tags)
state[Descriptors::HOSTS] = descriptors[Descriptors::HOSTS].toList();
state[Descriptors::TAGS] = descriptors[Descriptors::TAGS].toList();
// parse capacity
const QString CAPACITY = "security.maximum_user_capacity";
const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY);
unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0;
state[Descriptors::CAPACITY] = capacity;
// TODO: Keep parity with ACL development.
const QString RESTRICTION = "security.restricted_access";
const QString RESTRICTION_OPEN = "open";
// const QString RESTRICTION_HIFI = "hifi";
const QString RESTRICTION_ACL = "acl";
const QVariant* isRestrictedVariant = valueForKeyPath(settings, RESTRICTION);
bool isRestricted = isRestrictedVariant ? isRestrictedVariant->toBool() : false;
QString restriction = isRestricted ? RESTRICTION_ACL : RESTRICTION_OPEN;
QVariantMap descriptors = settings[DESCRIPTORS].toMap();
descriptors[DESCRIPTORS_CAPACITY] = capacity;
descriptors[DESCRIPTORS_RESTRICTION] = restriction;
_metadata[DESCRIPTORS] = descriptors;
// parse operating hours
const QString WEEKDAY_HOURS = "weekday_hours";
const QString WEEKEND_HOURS = "weekend_hours";
const QString UTC_OFFSET = "utc_offset";
assert(state[Descriptors::HOURS].canConvert<QVariantMap>());
auto& hours = *static_cast<QVariantMap*>(state[Descriptors::HOURS].data());
parseHours(descriptors.take(WEEKDAY_HOURS), hours[Descriptors::Hours::WEEKDAY]);
parseHours(descriptors.take(WEEKEND_HOURS), hours[Descriptors::Hours::WEEKEND]);
hours[Descriptors::Hours::UTC_OFFSET] = descriptors.take(UTC_OFFSET);
#if DEV_BUILD || PR_BUILD
qDebug() << "Domain metadata descriptors set:" << descriptors;
qDebug() << "Domain metadata descriptors set:" << QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap());
#endif
sendDescriptors();
}
void DomainMetadata::securityChanged(bool send) {
// get descriptors
assert(_metadata[DESCRIPTORS].canConvert<QVariantMap>());
auto& state = *static_cast<QVariantMap*>(_metadata[DESCRIPTORS].data());
const QString RESTRICTION_OPEN = "open";
const QString RESTRICTION_ANON = "anon";
const QString RESTRICTION_HIFI = "hifi";
const QString RESTRICTION_ACL = "acl";
QString restriction;
const auto& settingsManager = static_cast<DomainServer*>(parent())->_settingsManager;
bool hasAnonymousAccess =
settingsManager.getStandardPermissionsForName(NodePermissions::standardNameAnonymous).canConnectToDomain;
bool hasHifiAccess =
settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn).canConnectToDomain;
if (hasAnonymousAccess) {
restriction = hasHifiAccess ? RESTRICTION_OPEN : RESTRICTION_ANON;
} else if (hasHifiAccess) {
restriction = RESTRICTION_HIFI;
} else {
restriction = RESTRICTION_ACL;
}
state[Descriptors::RESTRICTION] = restriction;
#if DEV_BUILD || PR_BUILD
qDebug() << "Domain metadata restriction set:" << restriction;
#endif
if (send) {
sendDescriptors();
}
}
void DomainMetadata::usersChanged() {
++_tic;
#if DEV_BUILD || PR_BUILD
qDebug() << "Domain metadata users change detected";
#endif
}
void DomainMetadata::updateUsers() {
void DomainMetadata::maybeUpdateUsers() {
if (_lastTic == _tic) {
return;
}
_lastTic = _tic;
static const QString DEFAULT_HOSTNAME = "*";
auto nodeList = DependencyManager::get<LimitedNodeList>();
@ -112,21 +241,32 @@ void DomainMetadata::updateUsers() {
}
});
QVariantMap users = {
{ USERS_NUM_TOTAL, numConnected },
{ USERS_NUM_ANON, numConnectedAnonymously },
{ USERS_HOSTNAMES, userHostnames }};
_metadata[USERS] = users;
assert(_metadata[USERS].canConvert<QVariantMap>());
auto& users = *static_cast<QVariantMap*>(_metadata[USERS].data());
users[Users::NUM_TOTAL] = numConnected;
users[Users::NUM_ANON] = numConnectedAnonymously;
users[Users::HOSTNAMES] = userHostnames;
#if DEV_BUILD || PR_BUILD
qDebug() << "Domain metadata users updated:" << users;
qDebug() << "Domain metadata users set:" << QJsonObject::fromVariantMap(_metadata[USERS].toMap());
#endif
}
void DomainMetadata::usersChanged() {
++_tic;
void DomainMetadata::sendDescriptors() {
QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(get(DESCRIPTORS)).toJson(QJsonDocument::Compact)));
const QUuid& domainID = DependencyManager::get<LimitedNodeList>()->getSessionUUID();
if (!domainID.isNull()) {
static const QString DOMAIN_UPDATE = "/api/v1/domains/%1";
QString path { DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)) };
DependencyManager::get<AccountManager>()->sendRequest(path,
AccountManagerAuth::Required,
QNetworkAccessManager::PutOperation,
JSONCallbackParameters(),
domainUpdateJSON.toUtf8());
#if DEV_BUILD || PR_BUILD
qDebug() << "Domain metadata users change detected";
qDebug() << "Domain metadata sent to" << path;
qDebug() << "Domain metadata update:" << domainUpdateJSON;
#endif
}
}

View file

@ -19,46 +19,56 @@
class DomainMetadata : public QObject {
Q_OBJECT
public:
using Tic = uint32_t;
static const QString USERS;
static const QString USERS_NUM_TOTAL;
static const QString USERS_NUM_ANON;
static const QString USERS_HOSTNAMES;
class Users {
public:
static const QString NUM_TOTAL;
static const QString NUM_ANON;
static const QString HOSTNAMES;
};
static const QString DESCRIPTORS;
static const QString DESCRIPTORS_DESCRIPTION;
static const QString DESCRIPTORS_CAPACITY;
static const QString DESCRIPTORS_HOURS;
static const QString DESCRIPTORS_RESTRICTION;
static const QString DESCRIPTORS_MATURITY;
static const QString DESCRIPTORS_HOSTS;
static const QString DESCRIPTORS_TAGS;
static const QString DESCRIPTORS_IMG;
static const QString DESCRIPTORS_IMG_SRC;
static const QString DESCRIPTORS_IMG_TYPE;
static const QString DESCRIPTORS_IMG_SIZE;
static const QString DESCRIPTORS_IMG_UPDATED_AT;
class Descriptors {
public:
static const QString DESCRIPTION;
static const QString CAPACITY;
static const QString RESTRICTION;
static const QString MATURITY;
static const QString HOSTS;
static const QString TAGS;
static const QString HOURS;
class Hours {
public:
static const QString WEEKDAY;
static const QString WEEKEND;
static const QString UTC_OFFSET;
static const QString OPEN;
static const QString CLOSE;
};
};
public:
DomainMetadata();
DomainMetadata(QObject* domainServer);
DomainMetadata() = delete;
// Returns the last set metadata
// If connected users have changed, metadata may need to be updated
// this should be checked by storing tic = getTic() between calls
// and testing it for equality before the next get (tic == getTic())
QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); }
QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS].toMap()); }
QJsonObject getDescriptors() { return QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); }
uint32_t getTic() { return _tic; }
void setDescriptors(QVariantMap& settings);
void updateUsers();
// Get cached metadata
QJsonObject get();
QJsonObject get(const QString& group);
public slots:
void descriptorsChanged();
void securityChanged(bool send);
void securityChanged() { securityChanged(true); }
void usersChanged();
protected:
void maybeUpdateUsers();
void sendDescriptors();
QVariantMap _metadata;
uint32_t _lastTic{ (uint32_t)-1 };
uint32_t _tic{ 0 };
};

View file

@ -94,10 +94,6 @@ DomainServer::DomainServer(int argc, char* argv[]) :
qRegisterMetaType<DomainServerWebSessionData>("DomainServerWebSessionData");
qRegisterMetaTypeStreamOperators<DomainServerWebSessionData>("DomainServerWebSessionData");
// update the metadata when a user (dis)connects
connect(this, &DomainServer::userConnected, &_metadata, &DomainMetadata::usersChanged);
connect(this, &DomainServer::userDisconnected, &_metadata, &DomainMetadata::usersChanged);
// make sure we hear about newly connected nodes from our gatekeeper
connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode);
@ -124,8 +120,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
optionallyGetTemporaryName(args);
}
// update the metadata with current descriptors
_metadata.setDescriptors(_settingsManager.getSettingsMap());
_metadata = new DomainMetadata(this);
}
DomainServer::~DomainServer() {
@ -1101,14 +1096,11 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
NodePermissions anonymousPermissions = _settingsManager.getPermissionsForName(NodePermissions::standardNameAnonymous);
domainObject[RESTRICTED_ACCESS_FLAG] = !anonymousPermissions.canConnectToDomain;
// Add the metadata to the heartbeat
static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat";
auto tic = _metadata.getTic();
if (_metadataTic != tic) {
_metadataTic = tic;
_metadata.updateUsers();
if (_metadata) {
// Add the metadata to the heartbeat
static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat";
domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata->get(DomainMetadata::USERS);
}
domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.getUsers();
QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact)));

View file

@ -172,13 +172,12 @@ private:
DomainServerSettingsManager _settingsManager;
DomainMetadata _metadata;
uint32_t _metadataTic{ 0 };
HifiSockAddr _iceServerSocket;
std::unique_ptr<NLPacket> _iceServerHeartbeatPacket;
QTimer* _iceHeartbeatTimer { nullptr }; // this looks like it dangles when created but it's parented to the DomainServer
// These will be parented to this, they are not dangling
DomainMetadata* _metadata { nullptr };
QTimer* _iceHeartbeatTimer { nullptr };
QList<QHostAddress> _iceServerAddresses;
QSet<QHostAddress> _failedIceServerAddresses;
@ -190,6 +189,7 @@ private:
bool _hasAccessToken { false };
friend class DomainGatekeeper;
friend class DomainMetadata;
};

View file

@ -21,6 +21,8 @@
#include <QtCore/QUrl>
#include <QtCore/QUrlQuery>
#include <QTimeZone>
#include <Assignment.h>
#include <HifiConfigVariantMap.h>
#include <HTTPConnection.h>
@ -69,7 +71,7 @@ DomainServerSettingsManager::DomainServerSettingsManager() :
}
static const QString MISSING_SETTINGS_DESC_MSG =
QString("Did not find settings decription in JSON at %1 - Unable to continue. domain-server will quit.\n%2 at %3")
QString("Did not find settings description in JSON at %1 - Unable to continue. domain-server will quit.\n%2 at %3")
.arg(SETTINGS_DESCRIPTION_RELATIVE_PATH).arg(parseError.errorString()).arg(parseError.offset);
static const int MISSING_SETTINGS_DESC_ERROR_CODE = 6;
@ -258,6 +260,27 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
_standardAgentPermissions.clear();
_agentPermissions.clear();
}
if (oldVersion < 1.5) {
// This was prior to operating hours, so add default hours
static const QString WEEKDAY_HOURS{ "descriptors.weekday_hours" };
static const QString WEEKEND_HOURS{ "descriptors.weekend_hours" };
static const QString UTC_OFFSET{ "descriptors.utc_offset" };
QVariant* weekdayHours = valueForKeyPath(_configMap.getUserConfig(), WEEKDAY_HOURS, true);
QVariant* weekendHours = valueForKeyPath(_configMap.getUserConfig(), WEEKEND_HOURS, true);
QVariant* utcOffset = valueForKeyPath(_configMap.getUserConfig(), UTC_OFFSET, true);
*weekdayHours = QVariantList { QVariantMap{ { "open", QVariant("00:00") }, { "close", QVariant("23:59") } } };
*weekendHours = QVariantList { QVariantMap{ { "open", QVariant("00:00") }, { "close", QVariant("23:59") } } };
*utcOffset = QVariant(QTimeZone::systemTimeZone().offsetFromUtc(QDateTime::currentDateTime()) / (float)3600);
// write the new settings to file
persistToFile();
// reload the master and user config so the merged config is correct
_configMap.loadMasterAndUserConfig(_argumentList);
}
}
unpackPermissions();

View file

@ -139,7 +139,7 @@ link_hifi_libraries(shared octree gpu gl gpu-gl procedural model render
recording fbx networking model-networking entities avatars
audio audio-client animation script-engine physics
render-utils entities-renderer ui auto-updater
controllers plugins display-plugins input-plugins steamworks-wrapper)
controllers plugins ui-plugins display-plugins input-plugins steamworks-wrapper)
# include the binary directory of render-utils for shader includes
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries/render-utils")

View file

@ -83,7 +83,6 @@
#include <PerfStat.h>
#include <PhysicsEngine.h>
#include <PhysicsHelpers.h>
#include <plugins/PluginContainer.h>
#include <plugins/PluginManager.h>
#include <RenderableWebEntityItem.h>
#include <RenderShadowTask.h>
@ -119,7 +118,6 @@
#include "InterfaceLogging.h"
#include "LODManager.h"
#include "ModelPackager.h"
#include "PluginContainerProxy.h"
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AssetMappingsScriptingInterface.h"
#include "scripting/AudioDeviceScriptingInterface.h"
@ -464,7 +462,6 @@ bool setupEssentials(int& argc, char** argv) {
// continuing to overburden Application.cpp
Cube3DOverlay* _keyboardFocusHighlight{ nullptr };
int _keyboardFocusHighlightID{ -1 };
PluginContainer* _pluginContainer;
// FIXME hack access to the internal share context for the Chromium helper
@ -504,6 +501,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
_lastFaceTrackerUpdate(0)
{
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
PluginManager::getInstance()->setContainer(pluginContainer);
// FIXME this may be excessively conservative. On the other hand
// maybe I'm used to having an 8-core machine
// Perhaps find the ideal thread count and subtract 2 or 3
@ -521,7 +523,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_entityClipboard->createRootElement();
_pluginContainer = new PluginContainerProxy();
#ifdef Q_OS_WIN
installNativeEventFilter(&MyNativeEventFilter::getInstance());
#endif
@ -2035,9 +2036,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_Return:
if (isOption) {
if (_window->isFullScreen()) {
_pluginContainer->unsetFullscreen();
unsetFullscreen();
} else {
_pluginContainer->setFullscreen(nullptr);
setFullscreen(nullptr);
}
} else {
Menu::getInstance()->triggerOption(MenuOption::AddressBar);
@ -2951,7 +2952,6 @@ void Application::loadSettings() {
//DependencyManager::get<LODManager>()->setAutomaticLODAdjust(false);
Menu::getInstance()->loadSettings();
// If there is a preferred plugin, we probably messed it up with the menu settings, so fix it.
auto pluginManager = PluginManager::getInstance();
auto plugins = pluginManager->getPreferredDisplayPlugins();
@ -5308,3 +5308,49 @@ void Application::showDesktop() {
CompositorHelper& Application::getApplicationCompositor() const {
return *DependencyManager::get<CompositorHelper>();
}
// virtual functions required for PluginContainer
ui::Menu* Application::getPrimaryMenu() {
auto appMenu = _window->menuBar();
auto uiMenu = dynamic_cast<ui::Menu*>(appMenu);
return uiMenu;
}
void Application::showDisplayPluginsTools(bool show) {
DependencyManager::get<DialogsManager>()->hmdTools(show);
}
GLWidget* Application::getPrimaryWidget() {
return _glWidget;
}
MainWindow* Application::getPrimaryWindow() {
return getWindow();
}
QOpenGLContext* Application::getPrimaryContext() {
return _glWidget->context()->contextHandle();
}
bool Application::makeRenderingContextCurrent() {
return _offscreenContext->makeCurrent();
}
void Application::releaseSceneTexture(const gpu::TexturePointer& texture) {
Q_ASSERT(QThread::currentThread() == thread());
auto& framebufferMap = _lockedFramebufferMap;
Q_ASSERT(framebufferMap.contains(texture));
auto framebufferPointer = framebufferMap[texture];
framebufferMap.remove(texture);
auto framebufferCache = DependencyManager::get<FramebufferCache>();
framebufferCache->releaseFramebuffer(framebufferPointer);
}
void Application::releaseOverlayTexture(const gpu::TexturePointer& texture) {
_applicationOverlay.releaseOverlay(texture);
}
bool Application::isForeground() const {
return _isForeground && !_window->isMinimized();
}

View file

@ -34,6 +34,7 @@
#include <PhysicsEngine.h>
#include <plugins/Forward.h>
#include <plugins/DisplayPlugin.h>
#include <ui-plugins/PluginContainer.h>
#include <ScriptEngine.h>
#include <ShapeManager.h>
#include <SimpleMovingAverage.h>
@ -86,14 +87,32 @@ class Application;
#endif
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface, public AbstractUriHandler {
class Application : public QApplication,
public AbstractViewStateInterface,
public AbstractScriptingServicesInterface,
public AbstractUriHandler,
public PluginContainer {
Q_OBJECT
// TODO? Get rid of those
friend class OctreePacketProcessor;
friend class PluginContainerProxy;
public:
// virtual functions required for PluginContainer
virtual ui::Menu* getPrimaryMenu() override;
virtual void requestReset() override { resetSensors(true); }
virtual void showDisplayPluginsTools(bool show) override;
virtual GLWidget* getPrimaryWidget() override;
virtual MainWindow* getPrimaryWindow() override;
virtual QOpenGLContext* getPrimaryContext() override;
virtual bool makeRenderingContextCurrent() override;
virtual void releaseSceneTexture(const gpu::TexturePointer& texture) override;
virtual void releaseOverlayTexture(const gpu::TexturePointer& texture) override;
virtual bool isForeground() const override;
virtual DisplayPluginPointer getActiveDisplayPlugin() const override;
enum Event {
Present = DisplayPlugin::Present,
Paint = Present + 1,
@ -163,7 +182,6 @@ public:
Overlays& getOverlays() { return _overlays; }
bool isForeground() const { return _isForeground; }
size_t getFrameCount() const { return _frameCount; }
float getFps() const { return _frameCounter.rate(); }
@ -185,8 +203,6 @@ public:
void setActiveDisplayPlugin(const QString& pluginName);
DisplayPluginPointer getActiveDisplayPlugin() const;
FileLogger* getLogger() const { return _logger; }
glm::vec2 getViewportDimensions() const;

View file

@ -1,78 +0,0 @@
#include "PluginContainerProxy.h"
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <plugins/Plugin.h>
#include <plugins/PluginManager.h>
#include <display-plugins/DisplayPlugin.h>
#include <DependencyManager.h>
#include <FramebufferCache.h>
#include "Application.h"
#include "MainWindow.h"
#include "GLCanvas.h"
#include "ui/DialogsManager.h"
#include <gl/OffscreenGLCanvas.h>
#include <QtGui/QOpenGLContext>
PluginContainerProxy::PluginContainerProxy() {
}
PluginContainerProxy::~PluginContainerProxy() {
}
ui::Menu* PluginContainerProxy::getPrimaryMenu() {
auto appMenu = qApp->_window->menuBar();
auto uiMenu = dynamic_cast<ui::Menu*>(appMenu);
return uiMenu;
}
bool PluginContainerProxy::isForeground() {
return qApp->isForeground() && !qApp->getWindow()->isMinimized();
}
void PluginContainerProxy::requestReset() {
// We could signal qApp to sequence this, but it turns out that requestReset is only used from within the main thread anyway.
qApp->resetSensors(true);
}
void PluginContainerProxy::showDisplayPluginsTools(bool show) {
DependencyManager::get<DialogsManager>()->hmdTools(show);
}
GLWidget* PluginContainerProxy::getPrimaryWidget() {
return qApp->_glWidget;
}
MainWindow* PluginContainerProxy::getPrimaryWindow() {
return qApp->getWindow();
}
QOpenGLContext* PluginContainerProxy::getPrimaryContext() {
return qApp->_glWidget->context()->contextHandle();
}
const DisplayPluginPointer PluginContainerProxy::getActiveDisplayPlugin() const {
return qApp->getActiveDisplayPlugin();
}
bool PluginContainerProxy::makeRenderingContextCurrent() {
return qApp->_offscreenContext->makeCurrent();
}
void PluginContainerProxy::releaseSceneTexture(const gpu::TexturePointer& texture) {
Q_ASSERT(QThread::currentThread() == qApp->thread());
auto& framebufferMap = qApp->_lockedFramebufferMap;
Q_ASSERT(framebufferMap.contains(texture));
auto framebufferPointer = framebufferMap[texture];
framebufferMap.remove(texture);
auto framebufferCache = DependencyManager::get<FramebufferCache>();
framebufferCache->releaseFramebuffer(framebufferPointer);
}
void PluginContainerProxy::releaseOverlayTexture(const gpu::TexturePointer& texture) {
qApp->_applicationOverlay.releaseOverlay(texture);
}

View file

@ -1,33 +0,0 @@
#pragma once
#ifndef hifi_PluginContainerProxy_h
#define hifi_PluginContainerProxy_h
#include <QtCore/QObject>
#include <QtCore/QRect>
#include <plugins/Forward.h>
#include <plugins/PluginContainer.h>
class QActionGroup;
class PluginContainerProxy : public QObject, PluginContainer {
Q_OBJECT
PluginContainerProxy();
virtual ~PluginContainerProxy();
virtual void showDisplayPluginsTools(bool show = true) override;
virtual void requestReset() override;
virtual bool makeRenderingContextCurrent() override;
virtual void releaseSceneTexture(const gpu::TexturePointer& texture) override;
virtual void releaseOverlayTexture(const gpu::TexturePointer& texture) override;
virtual GLWidget* getPrimaryWidget() override;
virtual MainWindow* getPrimaryWindow() override;
virtual ui::Menu* getPrimaryMenu() override;
virtual QOpenGLContext* getPrimaryContext() override;
virtual bool isForeground() override;
virtual const DisplayPluginPointer getActiveDisplayPlugin() const override;
friend class Application;
};
#endif

View file

@ -163,7 +163,6 @@ void Rig::destroyAnimGraph() {
}
void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) {
_geometryOffset = AnimPose(geometry.offset);
_invGeometryOffset = _geometryOffset.inverse();
setModelOffset(modelOffset);
@ -1224,8 +1223,7 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
}
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
if (_animSkeleton) {
if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._overrideFlags.size()) {
// transform all the default poses into rig space.
const AnimPose geometryToRigPose(_geometryToRigTransform);

View file

@ -269,7 +269,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
_lastSentJointData.resize(_jointData.size());
for (int i=0; i < _jointData.size(); i++) {
const JointData& data = _jointData.at(i);
const JointData& data = _jointData[i];
if (sendAll || _lastSentJointData[i].rotation != data.rotation) {
if (sendAll ||
!cullSmallChanges ||
@ -294,7 +294,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
validityBit = 0;
validity = *validityPosition++;
for (int i = 0; i < _jointData.size(); i ++) {
const JointData& data = _jointData[ i ];
const JointData& data = _jointData[i];
if (validity & (1 << validityBit)) {
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation);
}
@ -317,7 +317,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
float maxTranslationDimension = 0.0;
for (int i=0; i < _jointData.size(); i++) {
const JointData& data = _jointData.at(i);
const JointData& data = _jointData[i];
if (sendAll || _lastSentJointData[i].translation != data.translation) {
if (sendAll ||
!cullSmallChanges ||
@ -348,7 +348,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
validityBit = 0;
validity = *validityPosition++;
for (int i = 0; i < _jointData.size(); i ++) {
const JointData& data = _jointData[ i ];
const JointData& data = _jointData[i];
if (validity & (1 << validityBit)) {
destinationBuffer +=
packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
@ -425,7 +425,6 @@ bool AvatarData::shouldLogError(const quint64& now) {
// read data in packet starting at byte offset and return number of bytes parsed
int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
// lazily allocate memory for HeadData in case we're not an Avatar instance
if (!_headData) {
_headData = new HeadData(this);
@ -669,7 +668,9 @@ void AvatarData::setJointData(int index, const glm::quat& rotation, const glm::v
}
JointData& data = _jointData[index];
data.rotation = rotation;
data.rotationSet = true;
data.translation = translation;
data.translationSet = true;
}
void AvatarData::clearJointData(int index) {
@ -774,6 +775,7 @@ void AvatarData::setJointRotation(int index, const glm::quat& rotation) {
}
JointData& data = _jointData[index];
data.rotation = rotation;
data.rotationSet = true;
}
void AvatarData::setJointTranslation(int index, const glm::vec3& translation) {
@ -789,6 +791,7 @@ void AvatarData::setJointTranslation(int index, const glm::vec3& translation) {
}
JointData& data = _jointData[index];
data.translation = translation;
data.translationSet = true;
}
void AvatarData::clearJointData(const QString& name) {
@ -858,7 +861,6 @@ void AvatarData::setJointTranslations(QVector<glm::vec3> jointTranslations) {
"setJointTranslations", Qt::BlockingQueuedConnection,
Q_ARG(QVector<glm::vec3>, jointTranslations));
}
if (_jointData.size() < jointTranslations.size()) {
_jointData.resize(jointTranslations.size());
}
@ -1100,6 +1102,7 @@ void AvatarData::sendIdentityPacket() {
void AvatarData::updateJointMappings() {
_jointIndices.clear();
_jointNames.clear();
_jointData.clear();
if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
@ -1457,7 +1460,6 @@ void AvatarData::fromJson(const QJsonObject& json) {
auto joint = jointDataFromJsonValue(jointJson);
jointArray.push_back(joint);
setJointData(i, joint.rotation, joint.translation);
_jointData[i].rotationSet = true; // Have to do that to broadcast the avatar new pose
i++;
}
setRawJointData(jointArray);

View file

@ -1,6 +1,6 @@
set(TARGET_NAME display-plugins)
setup_hifi_library(OpenGL)
link_hifi_libraries(shared plugins gl gpu-gl ui)
link_hifi_libraries(shared plugins ui-plugins gl gpu-gl ui)
target_opengl()

View file

@ -11,7 +11,7 @@
#include <SettingHandle.h>
#include "DisplayPlugin.h"
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
static Setting::Handle<float> IPD_SCALE_HANDLE("hmd.ipdScale", 1.0f);

View file

@ -13,7 +13,7 @@
#include <QtGui/QGuiApplication>
#include <QtWidgets/QAction>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
const QString Basic2DWindowOpenGLDisplayPlugin::NAME("Desktop");

View file

@ -10,7 +10,7 @@
#include "NullDisplayPlugin.h"
#include <QtGui/QImage>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
const QString NullDisplayPlugin::NAME("NullDisplayPlugin");

View file

@ -22,12 +22,13 @@
#include <NumericalConstants.h>
#include <DependencyManager.h>
#include <shared/NsightHelpers.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <gl/Config.h>
#include <gl/GLEscrow.h>
#include <GLMHelpers.h>
#include <CursorManager.h>
#include "CompositorHelper.h"
#include <ui/Menu.h>
#if THREADED_PRESENT
@ -202,6 +203,7 @@ private:
#endif
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
_sceneTextureEscrow.setRecycler([this](const gpu::TexturePointer& texture){
cleanupForSceneTexture(texture);
@ -233,10 +235,11 @@ bool OpenGLDisplayPlugin::activate() {
cursorData.hotSpot = vec2(0.5f);
}
}
if (!_container) {
return false;
}
_vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported();
#if THREADED_PRESENT
// Start the present thread if necessary
QSharedPointer<PresentThread> presentThread;
@ -272,7 +275,11 @@ bool OpenGLDisplayPlugin::activate() {
_container->makeRenderingContextCurrent();
#endif
return DisplayPlugin::activate();
if (isHmd() && (getHmdScreen() >= 0)) {
_container->showDisplayPluginsTools();
}
return Parent::activate();
}
void OpenGLDisplayPlugin::deactivate() {
@ -288,7 +295,16 @@ void OpenGLDisplayPlugin::deactivate() {
_container->makeRenderingContextCurrent();
#endif
internalDeactivate();
DisplayPlugin::deactivate();
_container->showDisplayPluginsTools(false);
if (!_container->currentDisplayActions().isEmpty()) {
auto menu = _container->getPrimaryMenu();
foreach(auto itemInfo, _container->currentDisplayActions()) {
menu->removeMenuItem(itemInfo.first, itemInfo.second);
}
_container->currentDisplayActions().clear();
}
Parent::deactivate();
}

View file

@ -24,6 +24,7 @@
#define THREADED_PRESENT 1
class OpenGLDisplayPlugin : public DisplayPlugin {
protected:
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
@ -135,7 +136,9 @@ protected:
BasicFramebufferWrapperPtr _compositeFramebuffer;
bool _lockCurrentTexture { false };
private:
using Parent = DisplayPlugin;
ProgramPtr _activeProgram;
};

View file

@ -15,7 +15,7 @@
#include <QtWidgets/QWidget>
#include <GLMHelpers.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <CursorManager.h>
#include <gl/GLWidget.h>
#include <shared/NsightHelpers.h>

View file

@ -9,7 +9,7 @@
#include "SideBySideStereoDisplayPlugin.h"
#include <GLMHelpers.h>
#include <CursorManager.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <gl/GLWidget.h>
#include "../CompositorHelper.h"

View file

@ -15,7 +15,7 @@
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <gl/GLWidget.h>
#include <CursorManager.h>
#include "../CompositorHelper.h"

View file

@ -150,8 +150,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
if (!canRezPermanentEntities && (entity->getLifetime() != properties.getLifetime())) {
// we don't allow a Node that can't create permanent entities to adjust lifetimes on existing ones
qCDebug(entities) << "Refusing disallowed entity lifetime adjustment.";
return false;
if (properties.lifetimeChanged()) {
qCDebug(entities) << "Refusing disallowed entity lifetime adjustment.";
return false;
}
}
// enforce support for locked entities. If an entity is currently locked, then the only
@ -322,8 +324,8 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
bool EntityTree::permissionsAllowRez(const EntityItemProperties& properties, bool canRez, bool canRezTmp) {
float lifeTime = properties.getLifetime();
if (lifeTime == 0.0f || lifeTime > _maxTmpEntityLifetime) {
// this is an attempt to rez a permanent entity.
if (lifeTime == ENTITY_ITEM_IMMORTAL_LIFETIME || lifeTime > _maxTmpEntityLifetime) {
// this is an attempt to rez a permanent or non-temporary entity.
if (!canRez) {
return false;
}

View file

@ -24,8 +24,15 @@ GLPipeline* GLPipeline::sync(const Pipeline& pipeline) {
// No object allocated yet, let's see if it's worth it...
ShaderPointer shader = pipeline.getProgram();
// If this pipeline's shader has already failed to compile, don't try again
if (shader->compilationHasFailed()) {
return nullptr;
}
GLShader* programObject = GLShader::sync(*shader);
if (programObject == nullptr) {
shader->setCompilationHasFailed(true);
return nullptr;
}

View file

@ -120,6 +120,9 @@ public:
bool isProgram() const { return getType() > NUM_DOMAINS; }
bool isDomain() const { return getType() < NUM_DOMAINS; }
void setCompilationHasFailed(bool compilationHasFailed) { _compilationHasFailed = compilationHasFailed; }
bool compilationHasFailed() const { return _compilationHasFailed; }
const Source& getSource() const { return _source; }
const Shaders& getShaders() const { return _shaders; }
@ -180,6 +183,9 @@ protected:
// The type of the shader, the master key
Type _type;
// Whether or not the shader compilation failed
bool _compilationHasFailed { false };
};
typedef Shader::Pointer ShaderPointer;

View file

@ -1,5 +1,5 @@
set(TARGET_NAME input-plugins)
setup_hifi_library()
link_hifi_libraries(shared plugins controllers)
link_hifi_libraries(shared plugins ui-plugins controllers)
GroupSources("src/input-plugins")

View file

@ -135,7 +135,14 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
_nextOwnershipBid = 0;
}
if ((flags & Simulation::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
_body->activate();
if (_body->isKinematicObject()) {
// only force activate kinematic bodies (dynamic shouldn't need force and
// active static bodies are special (see PhysicsEngine::_activeStaticBodies))
_body->activate(true);
_lastKinematicStep = ObjectMotionState::getWorldSimulationStep();
} else {
_body->activate();
}
}
}

View file

@ -1,28 +1,6 @@
#include "DisplayPlugin.h"
#include <NumericalConstants.h>
#include <ui/Menu.h>
#include "PluginContainer.h"
bool DisplayPlugin::activate() {
if (isHmd() && (getHmdScreen() >= 0)) {
_container->showDisplayPluginsTools();
}
return Parent::activate();
}
void DisplayPlugin::deactivate() {
_container->showDisplayPluginsTools(false);
if (!_container->currentDisplayActions().isEmpty()) {
auto menu = _container->getPrimaryMenu();
foreach(auto itemInfo, _container->currentDisplayActions()) {
menu->removeMenuItem(itemInfo.first, itemInfo.second);
}
_container->currentDisplayActions().clear();
}
Parent::deactivate();
}
int64_t DisplayPlugin::getPaintDelayUsecs() const {
std::lock_guard<std::mutex> lock(_paintDelayMutex);

View file

@ -64,8 +64,6 @@ public:
Present = QEvent::User + 1
};
bool activate() override;
void deactivate() override;
virtual bool isHmd() const { return false; }
virtual int getHmdScreen() const { return -1; }
/// By default, all HMDs are stereo

View file

@ -17,7 +17,6 @@
#include "RuntimePlugin.h"
#include "DisplayPlugin.h"
#include "InputPlugin.h"
#include "PluginContainer.h"
PluginManager* PluginManager::getInstance() {
@ -133,9 +132,8 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() {
}
}
}
auto& container = PluginContainer::getInstance();
for (auto plugin : displayPlugins) {
plugin->setContainer(&container);
plugin->setContainer(_container);
plugin->init();
}
@ -171,9 +169,8 @@ const InputPluginList& PluginManager::getInputPlugins() {
}
}
auto& container = PluginContainer::getInstance();
for (auto plugin : inputPlugins) {
plugin->setContainer(&container);
plugin->setContainer(_container);
plugin->init();
}
});

View file

@ -26,4 +26,7 @@ public:
void disableDisplays(const QStringList& displays);
void disableInputs(const QStringList& inputs);
void saveSettings();
void setContainer(PluginContainer* container) { _container = container; }
private:
PluginContainer* _container { nullptr };
};

View file

@ -0,0 +1,3 @@
set(TARGET_NAME ui-plugins)
setup_hifi_library(OpenGL)
link_hifi_libraries(shared plugins ui)

View file

@ -16,7 +16,7 @@
#include <QtCore/QPair>
#include <QtCore/QRect>
#include "Forward.h"
#include <plugins/Forward.h>
class QAction;
class GLWidget;
@ -63,8 +63,8 @@ public:
virtual GLWidget* getPrimaryWidget() = 0;
virtual MainWindow* getPrimaryWindow() = 0;
virtual QOpenGLContext* getPrimaryContext() = 0;
virtual bool isForeground() = 0;
virtual const DisplayPluginPointer getActiveDisplayPlugin() const = 0;
virtual bool isForeground() const = 0;
virtual DisplayPluginPointer getActiveDisplayPlugin() const = 0;
/// settings interface
bool getBoolSetting(const QString& settingName, bool defaultValue);
@ -84,3 +84,4 @@ protected:
std::map<QString, QActionGroup*> _exclusiveGroups;
QRect _savedGeometry { 10, 120, 800, 600 };
};

View file

@ -8,5 +8,5 @@
set(TARGET_NAME hifiSixense)
setup_hifi_plugin(Script Qml Widgets)
link_hifi_libraries(shared controllers ui plugins input-plugins)
link_hifi_libraries(shared controllers ui plugins ui-plugins input-plugins)
target_sixense()

View file

@ -28,7 +28,7 @@
#include <NumericalConstants.h>
#include <PathUtils.h>
#include <PerfStat.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <SettingHandle.h>
#include <QLoggingCategory>

View file

@ -18,7 +18,6 @@
#include <UserActivityLogger.h>
#include <PathUtils.h>
#include <plugins/PluginContainer.h>
#include <controllers/UserInputMapper.h>
const QString SpacemouseManager::NAME { "Spacemouse" };

View file

@ -13,7 +13,7 @@ if (WIN32)
set(TARGET_NAME oculus)
setup_hifi_plugin(Multimedia)
link_hifi_libraries(shared gl gpu controllers ui plugins display-plugins input-plugins audio-client networking)
link_hifi_libraries(shared gl gpu controllers ui plugins ui-plugins display-plugins input-plugins audio-client networking)
include_hifi_library_headers(octree)

View file

@ -13,7 +13,7 @@
#include <QtCore/QLoggingCategory>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <controllers/UserInputMapper.h>
#include <controllers/StandardControls.h>

View file

@ -12,7 +12,7 @@ if (APPLE)
set(TARGET_NAME oculusLegacy)
setup_hifi_plugin()
link_hifi_libraries(shared gl gpu plugins ui display-plugins input-plugins)
link_hifi_libraries(shared gl gpu plugins ui ui-plugins display-plugins input-plugins)
include_hifi_library_headers(octree)

View file

@ -26,7 +26,7 @@
#include <gl/OglplusHelpers.h>
#include <ViewFrustum.h>
#include "plugins/PluginContainer.h"
#include <ui-plugins/PluginContainer.h>
#include "OculusHelpers.h"
using namespace oglplus;

View file

@ -12,7 +12,7 @@ if (WIN32)
set(TARGET_NAME openvr)
setup_hifi_plugin(OpenGL Script Qml Widgets)
link_hifi_libraries(shared gl networking controllers ui
plugins display-plugins input-plugins script-engine
plugins display-plugins ui-plugins input-plugins script-engine
render-utils model gpu render model-networking fbx)
include_hifi_library_headers(octree)

View file

@ -19,7 +19,7 @@
#include <gl/GlWindow.h>
#include <PerfStat.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <ViewFrustum.h>
#include <shared/NsightHelpers.h>
#include "OpenVrHelpers.h"

View file

@ -20,7 +20,7 @@
#include <gpu/Context.h>
#include <DeferredLightingEffect.h>
#include <NumericalConstants.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <UserActivityLogger.h>
#include <controllers/UserInputMapper.h>

View file

@ -0,0 +1,129 @@
//
// Created by Zach Pomerantz on June 16, 2016.
// Copyright 2016 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
//
var SERVER = 'https://metaverse.highfidelity.com/api/v1';
var OVERLAY = null;
// Every time you enter a domain, display the domain's metadata
location.hostChanged.connect(function(host) {
print('Detected host change:', host);
// Fetch the domain ID from the metaverse
var placeData = request(SERVER + '/places/' + host);
if (!placeData) {
print('Cannot find place name - abandoning metadata request for', host);
return;
}
var domainID = placeData.data.place.domain.id;
print('Domain ID:', domainID);
// Fetch the domain metadata from the metaverse
var domainData = request(SERVER + '/domains/' + domainID);
print(SERVER + '/domains/' + domainID);
if (!domainData) {
print('Cannot find domain data - abandoning metadata request for', domainID);
return;
}
var metadata = domainData.domain;
print('Domain metadata:', JSON.stringify(metadata));
// Display the fetched metadata in an overlay
displayMetadata(host, metadata);
});
Script.scriptEnding.connect(clearMetadata);
function displayMetadata(place, metadata) {
clearMetadata();
var COLOR_TEXT = { red: 255, green: 255, blue: 255 };
var COLOR_BACKGROUND = { red: 0, green: 0, blue: 0 };
var MARGIN = 200;
var STARTING_OPACITY = 0.8;
var FADE_AFTER_SEC = 2;
var FADE_FOR_SEC = 4;
var fade_per_sec = STARTING_OPACITY / FADE_FOR_SEC;
var properties = {
color: COLOR_TEXT,
alpha: STARTING_OPACITY,
backgroundColor: COLOR_BACKGROUND,
backgroundAlpha: STARTING_OPACITY,
font: { size: 24 },
x: MARGIN,
y: MARGIN
};
// Center the overlay on the screen
properties.width = Window.innerWidth - MARGIN*2;
properties.height = Window.innerHeight - MARGIN*2;
// Parse the metadata into text
parsed = [ 'Welcome to ' + place + '!',, ];
if (metadata.description) {
parsed.push(description);
}
if (metadata.tags && metadata.tags.length) {
parsed.push('Tags: ' + metadata.tags.join(','));
}
if (metadata.capacity) {
parsed.push('Capacity (max users): ' + metadata.capacity);
}
if (metadata.maturity) {
parsed.push('Maturity: ' + metadata.maturity);
}
if (metadata.hosts && metadata.hosts.length) {
parsed.push('Hosts: ' + metadata.tags.join(','));
}
if (metadata.online_users) {
parsed.push('Users online: ' + metadata.online_users);
}
properties.text = parsed.join('\n\n');
// Display the overlay
OVERLAY = Overlays.addOverlay('text', properties);
// Fade out the overlay over 10 seconds
!function() {
var overlay = OVERLAY;
var alpha = STARTING_OPACITY;
var fade = function() {
// Only fade so long as the same overlay is up
if (overlay == OVERLAY) {
alpha -= fade_per_sec / 10;
if (alpha <= 0) {
clearMetadata();
} else {
Overlays.editOverlay(overlay, { alpha: alpha, backgroundAlpha: alpha });
Script.setTimeout(fade, 100);
}
}
};
Script.setTimeout(fade, FADE_AFTER_SEC * 1000);
}();
}
function clearMetadata() {
if (OVERLAY) {
Overlays.deleteOverlay(OVERLAY);
}
}
// Request JSON from a url, synchronously
function request(url) {
var req = new XMLHttpRequest();
req.responseType = 'json';
req.open('GET', url, false);
req.send();
return req.status == 200 ? req.response : null;
}

View file

@ -6,7 +6,7 @@ setup_hifi_project(Script Qml)
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
# link in the shared libraries
link_hifi_libraries(shared gl script-engine plugins render-utils input-plugins display-plugins controllers)
link_hifi_libraries(shared gl script-engine plugins render-utils ui-plugins input-plugins display-plugins controllers)
if (WIN32)

View file

@ -34,7 +34,7 @@
#include <QtQml/QQmlContext>
#include <plugins/Plugin.h>
#include <plugins/PluginContainer.h>
#include <ui-plugins/PluginContainer.h>
#include <plugins/PluginManager.h>
#include <input-plugins/InputPlugin.h>
#include <input-plugins/KeyboardMouseDevice.h>
@ -90,8 +90,8 @@ public:
virtual MainWindow* getPrimaryWindow() override { return nullptr; }
virtual QOpenGLContext* getPrimaryContext() override { return nullptr; }
virtual ui::Menu* getPrimaryMenu() override { return nullptr; }
virtual bool isForeground() override { return true; }
virtual const DisplayPluginPointer getActiveDisplayPlugin() const override { return DisplayPluginPointer(); }
virtual bool isForeground() const override { return true; }
virtual DisplayPluginPointer getActiveDisplayPlugin() const override { return DisplayPluginPointer(); }
};
class MyControllerScriptingInterface : public controller::ScriptingInterface {