mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 07:43:35 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blue
This commit is contained in:
commit
c550d5089e
67 changed files with 980 additions and 346 deletions
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <ClientServerUtils.h>
|
||||
#include <FBXBaker.h>
|
||||
#include <JSBaker.h>
|
||||
#include <NodeType.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <PathUtils.h>
|
||||
|
@ -49,10 +50,12 @@ static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
|||
|
||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||
|
||||
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
||||
static const QStringList BAKEABLE_MODEL_EXTENSIONS = {"fbx"};
|
||||
static QStringList BAKEABLE_TEXTURE_EXTENSIONS;
|
||||
static const QStringList BAKEABLE_SCRIPT_EXTENSIONS = {"js"};
|
||||
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
|
||||
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
||||
static const QString BAKED_SCRIPT_SIMPLE_NAME = "asset.js";
|
||||
|
||||
void AssetServer::bakeAsset(const AssetHash& assetHash, const AssetPath& assetPath, const QString& filePath) {
|
||||
qDebug() << "Starting bake for: " << assetPath << assetHash;
|
||||
|
@ -99,6 +102,8 @@ std::pair<BakingStatus, QString> AssetServer::getAssetStatus(const AssetPath& pa
|
|||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
|
||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
} else {
|
||||
return { Irrelevant, "" };
|
||||
}
|
||||
|
@ -186,6 +191,8 @@ bool AssetServer::needsToBeBaked(const AssetPath& path, const AssetHash& assetHa
|
|||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (loaded && BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit())) {
|
||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -228,7 +235,8 @@ void updateConsumedCores() {
|
|||
AssetServer::AssetServer(ReceivedMessage& message) :
|
||||
ThreadedAssignment(message),
|
||||
_transferTaskPool(this),
|
||||
_bakingTaskPool(this)
|
||||
_bakingTaskPool(this),
|
||||
_filesizeLimit(MAX_UPLOAD_SIZE)
|
||||
{
|
||||
// store the current state of image compression so we can reset it when this assignment is complete
|
||||
_wasColorTextureCompressionEnabled = image::isColorTexturesCompressionEnabled();
|
||||
|
@ -336,8 +344,8 @@ void AssetServer::completeSetup() {
|
|||
auto maxBandwidthValue = assetServerObject[MAX_BANDWIDTH_OPTION];
|
||||
auto maxBandwidthFloat = maxBandwidthValue.toDouble(-1);
|
||||
|
||||
const int BITS_PER_MEGABITS = 1000 * 1000;
|
||||
if (maxBandwidthFloat > 0.0) {
|
||||
const int BITS_PER_MEGABITS = 1000 * 1000;
|
||||
int maxBandwidth = maxBandwidthFloat * BITS_PER_MEGABITS;
|
||||
nodeList->setConnectionMaxBandwidth(maxBandwidth);
|
||||
qCInfo(asset_server) << "Set maximum bandwith per connection to" << maxBandwidthFloat << "Mb/s."
|
||||
|
@ -399,6 +407,15 @@ void AssetServer::completeSetup() {
|
|||
qCCritical(asset_server) << "Asset Server assignment will not continue because mapping file could not be loaded.";
|
||||
setFinished(true);
|
||||
}
|
||||
|
||||
// get file size limit for an asset
|
||||
static const QString ASSETS_FILESIZE_LIMIT_OPTION = "assets_filesize_limit";
|
||||
auto assetsFilesizeLimitJSONValue = assetServerObject[ASSETS_FILESIZE_LIMIT_OPTION];
|
||||
auto assetsFilesizeLimit = (uint64_t)assetsFilesizeLimitJSONValue.toInt(MAX_UPLOAD_SIZE);
|
||||
|
||||
if (assetsFilesizeLimit != 0 && assetsFilesizeLimit < MAX_UPLOAD_SIZE) {
|
||||
_filesizeLimit = assetsFilesizeLimit * BITS_PER_MEGABITS;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetServer::cleanupUnmappedFiles() {
|
||||
|
@ -488,6 +505,8 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, SharedNode
|
|||
bakedRootFile = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(assetPathExtension.toLocal8Bit())) {
|
||||
bakedRootFile = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(assetPathExtension)) {
|
||||
bakedRootFile = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
}
|
||||
|
||||
auto originalAssetHash = it->second;
|
||||
|
@ -721,7 +740,7 @@ void AssetServer::handleAssetUpload(QSharedPointer<ReceivedMessage> message, Sha
|
|||
if (senderNode->getCanWriteToAssetServer()) {
|
||||
qCDebug(asset_server) << "Starting an UploadAssetTask for upload from" << uuidStringWithoutCurlyBraces(senderNode->getUUID());
|
||||
|
||||
auto task = new UploadAssetTask(message, senderNode, _filesDirectory);
|
||||
auto task = new UploadAssetTask(message, senderNode, _filesDirectory, _filesizeLimit);
|
||||
_transferTaskPool.start(task);
|
||||
} else {
|
||||
// this is a node the domain told us is not allowed to rez entities
|
||||
|
@ -1141,6 +1160,7 @@ bool AssetServer::renameMapping(AssetPath oldPath, AssetPath newPath) {
|
|||
|
||||
static const QString BAKED_ASSET_SIMPLE_FBX_NAME = "asset.fbx";
|
||||
static const QString BAKED_ASSET_SIMPLE_TEXTURE_NAME = "texture.ktx";
|
||||
static const QString BAKED_ASSET_SIMPLE_JS_NAME = "asset.js";
|
||||
|
||||
QString getBakeMapping(const AssetHash& hash, const QString& relativeFilePath) {
|
||||
return HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + relativeFilePath;
|
||||
|
@ -1204,14 +1224,14 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina
|
|||
// setup the mapping for this bake file
|
||||
auto relativeFilePath = QUrl(filePath).fileName();
|
||||
qDebug() << "Relative file path is: " << relativeFilePath;
|
||||
|
||||
if (relativeFilePath.endsWith(".fbx", Qt::CaseInsensitive)) {
|
||||
// for an FBX file, we replace the filename with the simple name
|
||||
// (to handle the case where two mapped assets have the same hash but different names)
|
||||
relativeFilePath = BAKED_ASSET_SIMPLE_FBX_NAME;
|
||||
} else if (relativeFilePath.endsWith(".js", Qt::CaseInsensitive)) {
|
||||
relativeFilePath = BAKED_ASSET_SIMPLE_JS_NAME;
|
||||
} else if (!originalAssetPath.endsWith(".fbx", Qt::CaseInsensitive)) {
|
||||
relativeFilePath = BAKED_ASSET_SIMPLE_TEXTURE_NAME;
|
||||
|
||||
}
|
||||
|
||||
QString bakeMapping = getBakeMapping(originalAssetHash, relativeFilePath);
|
||||
|
@ -1364,6 +1384,8 @@ bool AssetServer::setBakingEnabled(const AssetPathList& paths, bool enabled) {
|
|||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
|
||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,8 @@ private:
|
|||
bool _wasGrayscaleTextureCompressionEnabled { false };
|
||||
bool _wasNormalTextureCompressionEnabled { false };
|
||||
bool _wasCubeTextureCompressionEnabled { false };
|
||||
|
||||
uint64_t _filesizeLimit;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <FBXBaker.h>
|
||||
#include <PathUtils.h>
|
||||
#include <JSBaker.h>
|
||||
|
||||
BakeAssetTask::BakeAssetTask(const AssetHash& assetHash, const AssetPath& assetPath, const QString& filePath) :
|
||||
_assetHash(assetHash),
|
||||
|
@ -52,6 +53,10 @@ void BakeAssetTask::run() {
|
|||
_baker = std::unique_ptr<FBXBaker> {
|
||||
new FBXBaker(QUrl("file:///" + _filePath), fn, tempOutputDir)
|
||||
};
|
||||
} else if (_assetPath.endsWith(".js", Qt::CaseInsensitive)) {
|
||||
_baker = std::unique_ptr<JSBaker>{
|
||||
new JSBaker(QUrl("file:///" + _filePath), PathUtils::generateTemporaryDir())
|
||||
};
|
||||
} else {
|
||||
tempOutputDir = PathUtils::generateTemporaryDir();
|
||||
_baker = std::unique_ptr<TextureBaker> {
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
|
||||
|
||||
UploadAssetTask::UploadAssetTask(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode,
|
||||
const QDir& resourcesDir) :
|
||||
const QDir& resourcesDir, uint64_t filesizeLimit) :
|
||||
_receivedMessage(receivedMessage),
|
||||
_senderNode(senderNode),
|
||||
_resourcesDir(resourcesDir)
|
||||
_resourcesDir(resourcesDir),
|
||||
_filesizeLimit(filesizeLimit)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -48,7 +49,7 @@ void UploadAssetTask::run() {
|
|||
auto replyPacket = NLPacket::create(PacketType::AssetUploadReply, -1, true);
|
||||
replyPacket->writePrimitive(messageID);
|
||||
|
||||
if (fileSize > MAX_UPLOAD_SIZE) {
|
||||
if (fileSize > _filesizeLimit) {
|
||||
replyPacket->writePrimitive(AssetServerError::AssetTooLarge);
|
||||
} else {
|
||||
QByteArray fileData = buffer.read(fileSize);
|
||||
|
|
|
@ -26,7 +26,8 @@ class Node;
|
|||
|
||||
class UploadAssetTask : public QRunnable {
|
||||
public:
|
||||
UploadAssetTask(QSharedPointer<ReceivedMessage> message, QSharedPointer<Node> senderNode, const QDir& resourcesDir);
|
||||
UploadAssetTask(QSharedPointer<ReceivedMessage> message, QSharedPointer<Node> senderNode,
|
||||
const QDir& resourcesDir, uint64_t filesizeLimit);
|
||||
|
||||
void run() override;
|
||||
|
||||
|
@ -34,6 +35,7 @@ private:
|
|||
QSharedPointer<ReceivedMessage> _receivedMessage;
|
||||
QSharedPointer<Node> _senderNode;
|
||||
QDir _resourcesDir;
|
||||
uint64_t _filesizeLimit;
|
||||
};
|
||||
|
||||
#endif // hifi_UploadAssetTask_h
|
||||
|
|
|
@ -858,6 +858,14 @@
|
|||
"help": "The path to the directory assets are stored in.<br/>If this path is relative, it will be relative to the application data directory.<br/>If you change this path you will need to manually copy any existing assets from the previous directory.",
|
||||
"default": "",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "assets_filesize_limit",
|
||||
"type": "int",
|
||||
"label": "File Size Limit",
|
||||
"help": "The file size limit of an asset that can be imported into the asset server in MBytes. 0 (default) means no limit on file size.",
|
||||
"default": 0,
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -17,6 +17,7 @@ import "./hifi/audio" as HifiAudio
|
|||
Hifi.AvatarInputs {
|
||||
id: root;
|
||||
objectName: "AvatarInputs"
|
||||
property int modality: Qt.NonModal
|
||||
width: audio.width;
|
||||
height: audio.height;
|
||||
x: 10; y: 5;
|
||||
|
|
|
@ -8,6 +8,9 @@ Item {
|
|||
|
||||
anchors.leftMargin: 300
|
||||
objectName: "StatsItem"
|
||||
property int modality: Qt.NonModal
|
||||
implicitHeight: row.height
|
||||
implicitWidth: row.width
|
||||
|
||||
Component.onCompleted: {
|
||||
stats.parentChanged.connect(fill);
|
||||
|
@ -18,8 +21,9 @@ Item {
|
|||
}
|
||||
|
||||
function fill() {
|
||||
// Explicitly fill in order to avoid warnings at shutdown
|
||||
anchors.fill = parent;
|
||||
// This will cause a warning at shutdown, need to find another way to remove
|
||||
// the warning other than filling the anchors to the parent
|
||||
anchors.horizontalCenter = parent.horizontalCenter
|
||||
}
|
||||
|
||||
Hifi.Stats {
|
||||
|
|
|
@ -124,7 +124,7 @@ Rectangle {
|
|||
selectByMouse: false
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key == Qt.Key_Return) {
|
||||
if (event.key == Qt.Key_Return || event.key == Qt.Key_Space) {
|
||||
mirrorText.text = "";
|
||||
event.accepted = true;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,20 @@ TextField {
|
|||
|
||||
y: textFieldLabel.visible ? textFieldLabel.height + textFieldLabel.anchors.bottomMargin : 0
|
||||
|
||||
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
event.accepted = true;
|
||||
|
||||
// emit accepted signal manually
|
||||
if (acceptableInput) {
|
||||
accepted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style: TextFieldStyle {
|
||||
textColor: {
|
||||
if (isLightColorScheme) {
|
||||
|
|
|
@ -301,15 +301,19 @@ FocusScope {
|
|||
function isPointOnWindow(point) {
|
||||
for (var i = 0; i < desktop.visibleChildren.length; i++) {
|
||||
var child = desktop.visibleChildren[i];
|
||||
if (child.visible) {
|
||||
if (child.hasOwnProperty("modality")) {
|
||||
var mappedPoint = child.mapFromGlobal(point.x, point.y);
|
||||
if (child.hasOwnProperty("modality")) {
|
||||
var mappedPoint = mapToItem(child, point.x, point.y);
|
||||
if (child.hasOwnProperty("frame")) {
|
||||
var outLine = child.frame.children[2];
|
||||
var framePoint = outLine.mapFromGlobal(point.x, point.y);
|
||||
if (child.contains(mappedPoint) || outLine.contains(framePoint)) {
|
||||
if (outLine.contains(framePoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (child.contains(mappedPoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -79,8 +79,6 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
#include <HFActionEvent.h>
|
||||
#include <HFBackEvent.h>
|
||||
#include <InfoView.h>
|
||||
#include <input-plugins/InputPlugin.h>
|
||||
#include <controllers/UserInputMapper.h>
|
||||
|
@ -2858,10 +2856,6 @@ bool Application::event(QEvent* event) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (HFActionEvent::types().contains(event->type())) {
|
||||
_controllerScriptingInterface->handleMetaEvent(static_cast<HFMetaEvent*>(event));
|
||||
}
|
||||
|
||||
return QApplication::event(event);
|
||||
}
|
||||
|
||||
|
@ -3166,25 +3160,8 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
case Qt::Key_Equal:
|
||||
getMyAvatar()->resetSize();
|
||||
break;
|
||||
case Qt::Key_Space: {
|
||||
if (!event->isAutoRepeat()) {
|
||||
// FIXME -- I don't think we've tested the HFActionEvent in a while... this looks possibly dubious
|
||||
// this starts an HFActionEvent
|
||||
HFActionEvent startActionEvent(HFActionEvent::startType(),
|
||||
computePickRay(getMouse().x, getMouse().y));
|
||||
sendEvent(this, &startActionEvent);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Escape: {
|
||||
getActiveDisplayPlugin()->abandonCalibration();
|
||||
if (!event->isAutoRepeat()) {
|
||||
// this starts the HFCancelEvent
|
||||
HFBackEvent startBackEvent(HFBackEvent::startType());
|
||||
sendEvent(this, &startBackEvent);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3210,30 +3187,6 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
|||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->keyReleaseEvent(event);
|
||||
}
|
||||
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Space: {
|
||||
if (!event->isAutoRepeat()) {
|
||||
// FIXME -- I don't think we've tested the HFActionEvent in a while... this looks possibly dubious
|
||||
// this ends the HFActionEvent
|
||||
HFActionEvent endActionEvent(HFActionEvent::endType(),
|
||||
computePickRay(getMouse().x, getMouse().y));
|
||||
sendEvent(this, &endActionEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Escape: {
|
||||
if (!event->isAutoRepeat()) {
|
||||
// this ends the HFCancelEvent
|
||||
HFBackEvent endBackEvent(HFBackEvent::endType());
|
||||
sendEvent(this, &endBackEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
event->ignore();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::focusOutEvent(QFocusEvent* event) {
|
||||
|
@ -3370,13 +3323,6 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->mousePressEvent(event);
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
// nobody handled this - make it an action event on the _window object
|
||||
HFActionEvent actionEvent(HFActionEvent::startType(),
|
||||
computePickRay(mappedEvent.x(), mappedEvent.y()));
|
||||
sendEvent(this, &actionEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3431,13 +3377,6 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
|
|||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
// fire an action end event
|
||||
HFActionEvent actionEvent(HFActionEvent::endType(),
|
||||
computePickRay(mappedEvent.x(), mappedEvent.y()));
|
||||
sendEvent(this, &actionEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4024,9 +3963,14 @@ void Application::calibrateEyeTracker5Points() {
|
|||
}
|
||||
#endif
|
||||
|
||||
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset) {
|
||||
bool Application::exportEntities(const QString& filename,
|
||||
const QVector<EntityItemID>& entityIDs,
|
||||
const glm::vec3* givenOffset) {
|
||||
QHash<EntityItemID, EntityItemPointer> entities;
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid myAvatarID = nodeList->getSessionUUID();
|
||||
|
||||
auto entityTree = getEntities()->getTree();
|
||||
auto exportTree = std::make_shared<EntityTree>();
|
||||
exportTree->createRootElement();
|
||||
|
@ -4042,8 +3986,12 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
|||
|
||||
if (!givenOffset) {
|
||||
EntityItemID parentID = entityItem->getParentID();
|
||||
if (parentID.isInvalidID() || !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID)) {
|
||||
auto position = entityItem->getPosition(); // If parent wasn't selected, we want absolute position, which isn't in properties.
|
||||
bool parentIsAvatar = (parentID == AVATAR_SELF_ID || parentID == myAvatarID);
|
||||
if (!parentIsAvatar && (parentID.isInvalidID() ||
|
||||
!entityIDs.contains(parentID) ||
|
||||
!entityTree->findEntityByEntityItemID(parentID))) {
|
||||
// If parent wasn't selected, we want absolute position, which isn't in properties.
|
||||
auto position = entityItem->getPosition();
|
||||
root.x = glm::min(root.x, position.x);
|
||||
root.y = glm::min(root.y, position.y);
|
||||
root.z = glm::min(root.z, position.z);
|
||||
|
@ -4063,12 +4011,16 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
|||
for (EntityItemPointer& entityDatum : entities) {
|
||||
auto properties = entityDatum->getProperties();
|
||||
EntityItemID parentID = properties.getParentID();
|
||||
if (parentID.isInvalidID()) {
|
||||
properties.setPosition(properties.getPosition() - root);
|
||||
bool parentIsAvatar = (parentID == AVATAR_SELF_ID || parentID == myAvatarID);
|
||||
if (parentIsAvatar) {
|
||||
properties.setParentID(AVATAR_SELF_ID);
|
||||
} else {
|
||||
if (parentID.isInvalidID()) {
|
||||
properties.setPosition(properties.getPosition() - root);
|
||||
} else if (!entities.contains(parentID)) {
|
||||
entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root);
|
||||
} // else valid parent -- don't offset
|
||||
}
|
||||
else if (!entities.contains(parentID)) {
|
||||
entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root);
|
||||
} // else valid parent -- don't offset
|
||||
exportTree->addEntity(entityDatum->getEntityItemID(), properties);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -53,7 +53,7 @@ const QUuid MY_AVATAR_KEY; // NULL key
|
|||
|
||||
AvatarManager::AvatarManager(QObject* parent) :
|
||||
_avatarsToFade(),
|
||||
_myAvatar(std::make_shared<MyAvatar>(qApp->thread()))
|
||||
_myAvatar(new MyAvatar(qApp->thread()), [](MyAvatar* ptr) { ptr->deleteLater(); })
|
||||
{
|
||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
|
||||
|
@ -297,7 +297,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
}
|
||||
|
||||
AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||
return std::make_shared<OtherAvatar>(qApp->thread());
|
||||
return AvatarSharedPointer(new OtherAvatar(qApp->thread()), [](OtherAvatar* ptr) { ptr->deleteLater(); });
|
||||
}
|
||||
|
||||
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
|
||||
|
|
|
@ -3238,3 +3238,9 @@ void MyAvatar::setModelScale(float scale) {
|
|||
emit sensorToWorldScaleChanged(sensorToWorldScale);
|
||||
}
|
||||
}
|
||||
|
||||
SpatialParentTree* MyAvatar::getParentTree() const {
|
||||
auto entityTreeRenderer = qApp->getEntities();
|
||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
return entityTree.get();
|
||||
}
|
||||
|
|
|
@ -544,6 +544,8 @@ public:
|
|||
float getUserHeight() const;
|
||||
float getUserEyeHeight() const;
|
||||
|
||||
virtual SpatialParentTree* getParentTree() const override;
|
||||
|
||||
public slots:
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
|
|
|
@ -13,23 +13,10 @@
|
|||
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <avatar/MyAvatar.h>
|
||||
#include <HFBackEvent.h>
|
||||
#include <plugins/PluginManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) {
|
||||
if (event->type() == HFActionEvent::startType()) {
|
||||
emit actionStartEvent(static_cast<HFActionEvent&>(*event));
|
||||
} else if (event->type() == HFActionEvent::endType()) {
|
||||
emit actionEndEvent(static_cast<HFActionEvent&>(*event));
|
||||
} else if (event->type() == HFBackEvent::startType()) {
|
||||
emit backStartEvent();
|
||||
} else if (event->type() == HFBackEvent::endType()) {
|
||||
emit backEndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const {
|
||||
return isKeyCaptured(KeyEvent(*event));
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <controllers/UserInputMapper.h>
|
||||
#include <controllers/ScriptingInterface.h>
|
||||
|
||||
#include <HFActionEvent.h>
|
||||
#include <KeyEvent.h>
|
||||
#include <MouseEvent.h>
|
||||
#include <SpatialEvent.h>
|
||||
|
@ -36,8 +35,6 @@ public:
|
|||
void emitKeyPressEvent(QKeyEvent* event);
|
||||
void emitKeyReleaseEvent(QKeyEvent* event);
|
||||
|
||||
void handleMetaEvent(HFMetaEvent* event);
|
||||
|
||||
void emitMouseMoveEvent(QMouseEvent* event);
|
||||
void emitMousePressEvent(QMouseEvent* event);
|
||||
void emitMouseDoublePressEvent(QMouseEvent* event);
|
||||
|
@ -72,12 +69,6 @@ signals:
|
|||
void keyPressEvent(const KeyEvent& event);
|
||||
void keyReleaseEvent(const KeyEvent& event);
|
||||
|
||||
void actionStartEvent(const HFActionEvent& event);
|
||||
void actionEndEvent(const HFActionEvent& event);
|
||||
|
||||
void backStartEvent();
|
||||
void backEndEvent();
|
||||
|
||||
void mouseMoveEvent(const MouseEvent& event);
|
||||
void mousePressEvent(const MouseEvent& event);
|
||||
void mouseDoublePressEvent(const MouseEvent& event);
|
||||
|
|
|
@ -32,6 +32,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
|||
Q_PROPERTY(bool showTablet READ getShouldShowTablet)
|
||||
Q_PROPERTY(QUuid tabletID READ getCurrentTabletFrameID WRITE setCurrentTabletFrameID)
|
||||
Q_PROPERTY(QUuid homeButtonID READ getCurrentHomeButtonID WRITE setCurrentHomeButtonID)
|
||||
Q_PROPERTY(QUuid homeButtonHighlightID READ getCurrentHomeButtonHightlightID WRITE setCurrentHomeButtonHightlightID)
|
||||
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
|
||||
|
||||
public:
|
||||
|
@ -97,6 +98,9 @@ public:
|
|||
void setCurrentHomeButtonID(QUuid homeButtonID) { _homeButtonID = homeButtonID; }
|
||||
QUuid getCurrentHomeButtonID() const { return _homeButtonID; }
|
||||
|
||||
void setCurrentHomeButtonHightlightID(QUuid homeButtonHightlightID) { _homeButtonHightlightID = homeButtonHightlightID; }
|
||||
QUuid getCurrentHomeButtonHightlightID() const { return _homeButtonHightlightID; }
|
||||
|
||||
void setCurrentTabletScreenID(QUuid tabletID) { _tabletScreenID = tabletID; }
|
||||
QUuid getCurrentTabletScreenID() const { return _tabletScreenID; }
|
||||
|
||||
|
@ -105,6 +109,7 @@ private:
|
|||
QUuid _tabletUIID; // this is the entityID of the tablet frame
|
||||
QUuid _tabletScreenID; // this is the overlayID which is part of (a child of) the tablet-ui.
|
||||
QUuid _homeButtonID;
|
||||
QUuid _homeButtonHightlightID;
|
||||
QUuid _tabletEntityID;
|
||||
|
||||
// Get the position of the HMD
|
||||
|
|
|
@ -106,14 +106,15 @@ extern std::atomic<size_t> DECIMATED_TEXTURE_COUNT;
|
|||
extern std::atomic<size_t> RECTIFIED_TEXTURE_COUNT;
|
||||
|
||||
void Stats::updateStats(bool force) {
|
||||
QQuickItem* parent = parentItem();
|
||||
if (!force) {
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
||||
if (isVisible()) {
|
||||
setVisible(false);
|
||||
if (parent->isVisible()) {
|
||||
parent->setVisible(false);
|
||||
}
|
||||
return;
|
||||
} else if (!isVisible()) {
|
||||
setVisible(true);
|
||||
} else if (!parent->isVisible()) {
|
||||
parent->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -305,3 +305,9 @@ Transform Base3DOverlay::evalRenderTransform() {
|
|||
void Base3DOverlay::setRenderTransform(const Transform& transform) {
|
||||
_renderTransform = transform;
|
||||
}
|
||||
|
||||
SpatialParentTree* Base3DOverlay::getParentTree() const {
|
||||
auto entityTreeRenderer = qApp->getEntities();
|
||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
return entityTree.get();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
virtual AABox getBounds() const override = 0;
|
||||
|
||||
void update(float deltatime) override;
|
||||
|
||||
|
||||
void notifyRenderTransformChange() const;
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
|
@ -69,6 +69,8 @@ public:
|
|||
return findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||
}
|
||||
|
||||
virtual SpatialParentTree* getParentTree() const override;
|
||||
|
||||
protected:
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
virtual void parentDeleted() override;
|
||||
|
|
|
@ -161,33 +161,33 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties)
|
|||
Overlay::Pointer thisOverlay = nullptr;
|
||||
|
||||
if (type == ImageOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<ImageOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility
|
||||
thisOverlay = std::make_shared<Image3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Image3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == TextOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<TextOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Text3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Text3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Text3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Shape3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Shape3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Shape3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Cube3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Cube3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Cube3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Sphere3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Sphere3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Sphere3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Circle3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Circle3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Circle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Rectangle3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Rectangle3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Rectangle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Line3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Line3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Line3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Grid3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Grid3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Grid3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == ModelOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<ModelOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new ModelOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == Web3DOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<Web3DOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new Web3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
} else if (type == RectangleOverlay::TYPE) {
|
||||
thisOverlay = std::make_shared<RectangleOverlay>();
|
||||
thisOverlay = Overlay::Pointer(new RectangleOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
|
||||
}
|
||||
|
||||
if (thisOverlay) {
|
||||
|
@ -230,7 +230,7 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
|||
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||
|
||||
if (thisOverlay) {
|
||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone()));
|
||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); }));
|
||||
#if OVERLAY_PANELS
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
||||
if (attachable && attachable->getParentPanel()) {
|
||||
|
|
247
libraries/baking/src/JSBaker.cpp
Normal file
247
libraries/baking/src/JSBaker.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
//
|
||||
// JSBaker.cpp
|
||||
// libraries/baking/src
|
||||
//
|
||||
// Created by Utkarsh Gautam on 9/18/17.
|
||||
// Copyright 2017 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 <PathUtils.h>
|
||||
|
||||
#include "JSBaker.h"
|
||||
#include "Baker.h"
|
||||
|
||||
const int ASCII_CHARACTERS_UPPER_LIMIT = 126;
|
||||
|
||||
JSBaker::JSBaker(const QUrl& jsURL, const QString& bakedOutputDir) :
|
||||
_jsURL(jsURL),
|
||||
_bakedOutputDir(bakedOutputDir)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void JSBaker::bake() {
|
||||
qCDebug(js_baking) << "JS Baker " << _jsURL << "bake starting";
|
||||
|
||||
// Import file to start baking
|
||||
QFile jsFile(_jsURL.toLocalFile());
|
||||
if (!jsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
handleError("Error opening " + _jsURL.fileName() + " for reading");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read file into an array
|
||||
QByteArray inputJS = jsFile.readAll();
|
||||
QByteArray outputJS;
|
||||
|
||||
// Call baking on inputJS and store result in outputJS
|
||||
bool success = bakeJS(inputJS, outputJS);
|
||||
if (!success) {
|
||||
qCDebug(js_baking) << "Bake Failed";
|
||||
handleError("Unterminated multi-line comment");
|
||||
return;
|
||||
}
|
||||
|
||||
// Bake Successful. Export the file
|
||||
auto fileName = _jsURL.fileName();
|
||||
auto baseName = fileName.left(fileName.lastIndexOf('.'));
|
||||
auto bakedFilename = baseName + BAKED_JS_EXTENSION;
|
||||
|
||||
_bakedJSFilePath = _bakedOutputDir + "/" + bakedFilename;
|
||||
|
||||
QFile bakedFile;
|
||||
bakedFile.setFileName(_bakedJSFilePath);
|
||||
if (!bakedFile.open(QIODevice::WriteOnly)) {
|
||||
handleError("Error opening " + _bakedJSFilePath + " for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
bakedFile.write(outputJS);
|
||||
|
||||
// Export successful
|
||||
_outputFiles.push_back(_bakedJSFilePath);
|
||||
qCDebug(js_baking) << "Exported" << _jsURL << "minified to" << _bakedJSFilePath;
|
||||
|
||||
// emit signal to indicate the JS baking is finished
|
||||
emit finished();
|
||||
}
|
||||
|
||||
bool JSBaker::bakeJS(const QByteArray& inputFile, QByteArray& outputFile) {
|
||||
// Read from inputFile and write to outputFile per character
|
||||
QTextStream in(inputFile, QIODevice::ReadOnly);
|
||||
QTextStream out(outputFile, QIODevice::WriteOnly);
|
||||
|
||||
// Algorithm requires the knowledge of previous and next character for each character read
|
||||
QChar currentCharacter;
|
||||
QChar nextCharacter;
|
||||
// Initialize previousCharacter with new line
|
||||
QChar previousCharacter = '\n';
|
||||
|
||||
in >> currentCharacter;
|
||||
|
||||
while (!in.atEnd()) {
|
||||
in >> nextCharacter;
|
||||
|
||||
if (currentCharacter == '\r') {
|
||||
out << '\n';
|
||||
} else if (currentCharacter == '/') {
|
||||
// Check if single line comment i.e. //
|
||||
if (nextCharacter == '/') {
|
||||
handleSingleLineComments(in);
|
||||
|
||||
//Start fresh after handling comments
|
||||
previousCharacter = '\n';
|
||||
in >> currentCharacter;
|
||||
continue;
|
||||
} else if (nextCharacter == '*') {
|
||||
// Check if multi line comment i.e. /*
|
||||
bool success = handleMultiLineComments(in);
|
||||
if (!success) {
|
||||
// Errors present return false
|
||||
return false;
|
||||
}
|
||||
//Start fresh after handling comments
|
||||
previousCharacter = '\n';
|
||||
in >> currentCharacter;
|
||||
continue;
|
||||
} else {
|
||||
// If '/' is not followed by '/' or '*' print '/'
|
||||
out << currentCharacter;
|
||||
}
|
||||
} else if (isSpaceOrTab(currentCharacter)) {
|
||||
// Check if white space or tab
|
||||
|
||||
// Skip multiple spaces or tabs
|
||||
while (isSpaceOrTab(nextCharacter)) {
|
||||
in >> nextCharacter;
|
||||
if (nextCharacter == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if space can be omitted
|
||||
if (!canOmitSpace(previousCharacter, nextCharacter)) {
|
||||
out << ' ';
|
||||
}
|
||||
} else if (currentCharacter == '\n') {
|
||||
// Check if new line
|
||||
|
||||
//Skip multiple new lines
|
||||
//Skip new line followed by space or tab
|
||||
while (nextCharacter == '\n' || isSpaceOrTab(nextCharacter)) {
|
||||
in >> nextCharacter;
|
||||
}
|
||||
|
||||
// Check if new line can be omitted
|
||||
if (!canOmitNewLine(previousCharacter, nextCharacter)) {
|
||||
out << '\n';
|
||||
}
|
||||
} else if (isQuote(currentCharacter)) {
|
||||
// Print the current quote and nextCharacter as is
|
||||
out << currentCharacter;
|
||||
out << nextCharacter;
|
||||
|
||||
// Store the type of quote we are processing
|
||||
QChar quote = currentCharacter;
|
||||
|
||||
// Don't modify the quoted strings
|
||||
while (nextCharacter != quote) {
|
||||
in >> nextCharacter;
|
||||
out << nextCharacter;
|
||||
}
|
||||
|
||||
//Start fresh after handling quoted strings
|
||||
previousCharacter = nextCharacter;
|
||||
in >> currentCharacter;
|
||||
continue;
|
||||
} else {
|
||||
// In all other cases write the currentCharacter to outputFile
|
||||
out << currentCharacter;
|
||||
}
|
||||
|
||||
previousCharacter = currentCharacter;
|
||||
currentCharacter = nextCharacter;
|
||||
}
|
||||
|
||||
//write currentCharacter to output file when nextCharacter reaches EOF
|
||||
if (currentCharacter != '\n') {
|
||||
out << currentCharacter;
|
||||
}
|
||||
|
||||
// Successful bake. Return true
|
||||
return true;
|
||||
}
|
||||
|
||||
void JSBaker::handleSingleLineComments(QTextStream& in) {
|
||||
QChar character;
|
||||
while (!in.atEnd()) {
|
||||
in >> character;
|
||||
if (character == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool JSBaker::handleMultiLineComments(QTextStream& in) {
|
||||
QChar character;
|
||||
while (!in.atEnd()) {
|
||||
in >> character;
|
||||
if (character == '*') {
|
||||
if (in.read(1) == '/') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSBaker::canOmitSpace(QChar previousCharacter, QChar nextCharacter) {
|
||||
return(!((isAlphanum(previousCharacter) || isNonAscii(previousCharacter) || isSpecialCharacter(previousCharacter)) &&
|
||||
(isAlphanum(nextCharacter) || isNonAscii(nextCharacter) || isSpecialCharacter(nextCharacter)))
|
||||
);
|
||||
}
|
||||
|
||||
bool JSBaker::canOmitNewLine(QChar previousCharacter, QChar nextCharacter) {
|
||||
return (!((isAlphanum(previousCharacter) || isNonAscii(previousCharacter) || isSpecialCharacterPrevious(previousCharacter)) &&
|
||||
(isAlphanum(nextCharacter) || isNonAscii(nextCharacter) || isSpecialCharacterNext(nextCharacter)))
|
||||
);
|
||||
}
|
||||
|
||||
//Check if character is alphabet, number or one of the following: '_', '$', '\\' or a non-ASCII character
|
||||
bool JSBaker::isAlphanum(QChar c) {
|
||||
return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
|
||||
|| c == '_' || c == '$' || c == '\\' || c > ASCII_CHARACTERS_UPPER_LIMIT);
|
||||
}
|
||||
|
||||
bool JSBaker::isNonAscii(QChar c) {
|
||||
return ((int)c.toLatin1() > ASCII_CHARACTERS_UPPER_LIMIT);
|
||||
}
|
||||
|
||||
// If previous and next characters are special characters, don't omit space
|
||||
bool JSBaker::isSpecialCharacter(QChar c) {
|
||||
return (c == '\'' || c == '$' || c == '_' || c == '/' || c== '+' || c == '-');
|
||||
}
|
||||
|
||||
// If previous character is a special character, maybe don't omit new line (depends on next character as well)
|
||||
bool JSBaker::isSpecialCharacterPrevious(QChar c) {
|
||||
return (c == '\'' || c == '$' || c == '_' || c == '}' || c == ']' || c == ')' || c == '+' || c == '-'
|
||||
|| c == '"' || c == "'");
|
||||
}
|
||||
|
||||
// If next character is a special character, maybe don't omit new line (depends on previous character as well)
|
||||
bool JSBaker::isSpecialCharacterNext(QChar c) {
|
||||
return (c == '\'' || c == '$' || c == '_' || c == '{' || c == '[' || c == '(' || c == '+' || c == '-');
|
||||
}
|
||||
|
||||
// Check if white space or tab
|
||||
bool JSBaker::isSpaceOrTab(QChar c) {
|
||||
return (c == ' ' || c == '\t');
|
||||
}
|
||||
|
||||
// Check If the currentCharacter is " or ' or `
|
||||
bool JSBaker::isQuote(QChar c) {
|
||||
return (c == '"' || c == "'" || c == '`');
|
||||
}
|
49
libraries/baking/src/JSBaker.h
Normal file
49
libraries/baking/src/JSBaker.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// JSBaker.h
|
||||
// libraries/baking/src
|
||||
//
|
||||
// Created by Utkarsh Gautam on 9/18/17.
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
#ifndef hifi_JSBaker_h
|
||||
#define hifi_JSBaker_h
|
||||
|
||||
#include "Baker.h"
|
||||
#include "JSBakingLoggingCategory.h"
|
||||
|
||||
static const QString BAKED_JS_EXTENSION = ".baked.js";
|
||||
|
||||
class JSBaker : public Baker {
|
||||
Q_OBJECT
|
||||
public:
|
||||
JSBaker(const QUrl& jsURL, const QString& bakedOutputDir);
|
||||
static bool bakeJS(const QByteArray& inputFile, QByteArray& outputFile);
|
||||
|
||||
public slots:
|
||||
virtual void bake() override;
|
||||
|
||||
private:
|
||||
QUrl _jsURL;
|
||||
QString _bakedOutputDir;
|
||||
QString _bakedJSFilePath;
|
||||
|
||||
static void handleSingleLineComments(QTextStream& in);
|
||||
static bool handleMultiLineComments(QTextStream& in);
|
||||
|
||||
static bool canOmitSpace(QChar previousCharacter, QChar nextCharacter);
|
||||
static bool canOmitNewLine(QChar previousCharacter, QChar nextCharacter);
|
||||
|
||||
static bool isAlphanum(QChar c);
|
||||
static bool isNonAscii(QChar c);
|
||||
static bool isSpecialCharacter(QChar c);
|
||||
static bool isSpecialCharacterPrevious(QChar c);
|
||||
static bool isSpecialCharacterNext(QChar c);
|
||||
static bool isSpaceOrTab(QChar c);
|
||||
static bool isQuote(QChar c);
|
||||
};
|
||||
|
||||
#endif // !hifi_JSBaker_h
|
14
libraries/baking/src/JSBakingLoggingCategory.cpp
Normal file
14
libraries/baking/src/JSBakingLoggingCategory.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// JSBakingLoggingCategory.cpp
|
||||
// libraries/baking/src
|
||||
//
|
||||
// Created by Utkarsh Gautam on 9/18/17.
|
||||
// Copyright 2017 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 "JSBakingLoggingCategory.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(js_baking, "hifi.JS-baking");
|
19
libraries/baking/src/JSBakingLoggingCategory.h
Normal file
19
libraries/baking/src/JSBakingLoggingCategory.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// JSBakingLoggingCategory.h
|
||||
// libraries/baking/src
|
||||
//
|
||||
// Created by Utkarsh Gautam on 9/18/17.
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
#ifndef hifi_JSBakingLoggingCategory_h
|
||||
#define hifi_JSBakingLoggingCategory_h
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(js_baking)
|
||||
|
||||
#endif // hifi_ModelBakingLoggingCategory_h
|
|
@ -60,7 +60,8 @@ bool ModelEntityWrapper::isModelLoaded() const {
|
|||
}
|
||||
|
||||
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()) };
|
||||
EntityItemPointer entity(new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()),
|
||||
[](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ void loop3(const T& start, const T& end, F f) {
|
|||
}
|
||||
|
||||
EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
std::shared_ptr<RenderablePolyVoxEntityItem> entity{ new RenderablePolyVoxEntityItem(entityID) };
|
||||
std::shared_ptr<RenderablePolyVoxEntityItem> entity(new RenderablePolyVoxEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
entity->initializePolyVox();
|
||||
return entity;
|
||||
|
|
|
@ -45,7 +45,7 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type,
|
|||
}
|
||||
EntityItemPointer entity = entityTree->findEntityByEntityItemID(entityItemID);
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityEditPacketSender::queueEditEntityMessage can't find entity.";
|
||||
qCDebug(entities) << "EntityEditPacketSender::queueEditAvatarEntityMessage can't find entity: " << entityItemID;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1848,7 +1848,13 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void
|
|||
|
||||
QHash<EntityItemID, EntityItemID>::iterator iter = args->map->find(oldID);
|
||||
if (iter == args->map->end()) {
|
||||
EntityItemID newID = QUuid::createUuid();
|
||||
EntityItemID newID;
|
||||
if (oldID == AVATAR_SELF_ID) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
newID = EntityItemID(nodeList->getSessionUUID());
|
||||
} else {
|
||||
newID = QUuid::createUuid();
|
||||
}
|
||||
args->map->insert(oldID, newID);
|
||||
return newID;
|
||||
}
|
||||
|
@ -1865,8 +1871,8 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void
|
|||
properties.setPosition(properties.getPosition() + args->root);
|
||||
} else {
|
||||
EntityItemPointer parentEntity = args->ourTree->findEntityByEntityItemID(oldParentID);
|
||||
if (parentEntity) { // map the parent
|
||||
properties.setParentID(getMapped(parentEntity->getID()));
|
||||
if (parentEntity || oldParentID == AVATAR_SELF_ID) { // map the parent
|
||||
properties.setParentID(getMapped(oldParentID));
|
||||
// But do not add root offset in this case.
|
||||
} else { // Should not happen, but let's try to be helpful...
|
||||
item->globalizeProperties(properties, "Cannot find %3 parent of %2 %1", args->root);
|
||||
|
@ -1941,6 +1947,12 @@ bool EntityTree::readFromMap(QVariantMap& map) {
|
|||
entityItemID = EntityItemID(QUuid::createUuid());
|
||||
}
|
||||
|
||||
if (properties.getClientOnly()) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||
properties.setOwningAvatarID(myNodeID);
|
||||
}
|
||||
|
||||
EntityItemPointer entity = addEntity(entityItemID, properties);
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType();
|
||||
|
|
|
@ -30,7 +30,7 @@ const float LightEntityItem::DEFAULT_CUTOFF = PI / 2.0f;
|
|||
bool LightEntityItem::_lightsArePickable = false;
|
||||
|
||||
EntityItemPointer LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new LightEntityItem(entityID) };
|
||||
EntityItemPointer entity(new LightEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const int LineEntityItem::MAX_POINTS_PER_LINE = 70;
|
|||
|
||||
|
||||
EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new LineEntityItem(entityID) };
|
||||
EntityItemPointer entity(new LineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
@ -214,4 +214,4 @@ void LineEntityItem::resetPointsChanged() {
|
|||
withWriteLock([&] {
|
||||
_pointsChanged = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const QString ModelEntityItem::DEFAULT_MODEL_URL = QString("");
|
|||
const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString("");
|
||||
|
||||
EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ModelEntityItem(entityID) };
|
||||
EntityItemPointer entity(new ModelEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ uint64_t Properties::emitIntervalUsecs() const {
|
|||
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
||||
EntityItemPointer entity(new ParticleEffectEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 70;
|
|||
|
||||
|
||||
EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new PolyLineEntityItem(entityID) };
|
||||
EntityItemPointer entity(new PolyLineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ const QString PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL = QString("");
|
|||
const QString PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL = QString("");
|
||||
|
||||
EntityItemPointer PolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new PolyVoxEntityItem(entityID) };
|
||||
EntityItemPointer entity(new PolyVoxEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace entity {
|
|||
}
|
||||
|
||||
ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity { new ShapeEntityItem(entityID) };
|
||||
Pointer entity(new ShapeEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ const xColor TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
|
|||
const bool TextEntityItem::DEFAULT_FACE_CAMERA = false;
|
||||
|
||||
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new TextEntityItem(entityID) };
|
||||
EntityItemPointer entity(new TextEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
const QString WebEntityItem::DEFAULT_SOURCE_URL("http://www.google.com");
|
||||
|
||||
EntityItemPointer WebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new WebEntityItem(entityID) };
|
||||
EntityItemPointer entity(new WebEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const bool ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED = true;
|
|||
const QString ZoneEntityItem::DEFAULT_FILTER_URL = "";
|
||||
|
||||
EntityItemPointer ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ZoneEntityItem(entityID) };
|
||||
EntityItemPointer entity(new ZoneEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -1202,10 +1202,6 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage&
|
|||
formatGPU = HDR_FORMAT;
|
||||
}
|
||||
|
||||
if (image.format() != QIMAGE_HDR_FORMAT) {
|
||||
image = convertToHDRFormat(image, HDR_FORMAT);
|
||||
}
|
||||
|
||||
// Find the layout of the cubemap in the 2D image
|
||||
// Use the original image size since processSourceImage may have altered the size / aspect ratio
|
||||
int foundLayout = CubeLayout::findLayout(srcImage.width(), srcImage.height());
|
||||
|
@ -1233,6 +1229,13 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage&
|
|||
faces.push_back(faceImage);
|
||||
}
|
||||
}
|
||||
|
||||
if (image.format() != QIMAGE_HDR_FORMAT) {
|
||||
for (auto& face : faces) {
|
||||
face = convertToHDRFormat(face, HDR_FORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
qCDebug(imagelogging) << "Failed to find a known cube map layout from this image:" << QString(srcImageName.c_str());
|
||||
return nullptr;
|
||||
|
|
|
@ -620,6 +620,12 @@ void NetworkTexture::ktxMipRequestFinished() {
|
|||
|
||||
texture->assignStoredMip(mipLevel, data.size(), reinterpret_cast<const uint8_t*>(data.data()));
|
||||
|
||||
// If mip level assigned above is still unavailable, then we assume future requests will also fail.
|
||||
auto minMipLevel = texture->minAvailableMipLevel();
|
||||
if (minMipLevel > mipLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(resource.data(), "setImage",
|
||||
Q_ARG(gpu::TexturePointer, texture),
|
||||
Q_ARG(int, texture->getWidth()),
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "HFActionEvent.h"
|
||||
#include "KeyEvent.h"
|
||||
#include "MouseEvent.h"
|
||||
#include "SpatialEvent.h"
|
||||
|
@ -20,7 +19,6 @@
|
|||
#include "EventTypes.h"
|
||||
|
||||
void registerEventTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, HFActionEvent::toScriptValue, HFActionEvent::fromScriptValue);
|
||||
qScriptRegisterMetaType(engine, KeyEvent::toScriptValue, KeyEvent::fromScriptValue);
|
||||
qScriptRegisterMetaType(engine, MouseEvent::toScriptValue, MouseEvent::fromScriptValue);
|
||||
qScriptRegisterMetaType(engine, PointerEvent::toScriptValue, PointerEvent::fromScriptValue);
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// HFActionEvent.cpp
|
||||
// script-engine/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-10-27.
|
||||
// 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 "HFActionEvent.h"
|
||||
|
||||
HFActionEvent::HFActionEvent(QEvent::Type type, const PickRay& actionRay) :
|
||||
HFMetaEvent(type),
|
||||
actionRay(actionRay)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QEvent::Type HFActionEvent::startType() {
|
||||
static QEvent::Type startType = HFMetaEvent::newEventType();
|
||||
return startType;
|
||||
}
|
||||
|
||||
QEvent::Type HFActionEvent::endType() {
|
||||
static QEvent::Type endType = HFMetaEvent::newEventType();
|
||||
return endType;
|
||||
}
|
||||
|
||||
QScriptValue HFActionEvent::toScriptValue(QScriptEngine* engine, const HFActionEvent& event) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("actionRay", pickRayToScriptValue(engine, event.actionRay));
|
||||
return obj;
|
||||
}
|
||||
|
||||
void HFActionEvent::fromScriptValue(const QScriptValue& object, HFActionEvent& event) {
|
||||
// not yet implemented
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// HFActionEvent.h
|
||||
// script-engine/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-10-27.
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef hifi_HFActionEvent_h
|
||||
#define hifi_HFActionEvent_h
|
||||
|
||||
|
||||
#include <qscriptengine.h>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "HFMetaEvent.h"
|
||||
|
||||
class HFActionEvent : public HFMetaEvent {
|
||||
public:
|
||||
HFActionEvent() {};
|
||||
HFActionEvent(QEvent::Type type, const PickRay& actionRay);
|
||||
|
||||
static QEvent::Type startType();
|
||||
static QEvent::Type endType();
|
||||
|
||||
static QScriptValue toScriptValue(QScriptEngine* engine, const HFActionEvent& event);
|
||||
static void fromScriptValue(const QScriptValue& object, HFActionEvent& event);
|
||||
|
||||
PickRay actionRay;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(HFActionEvent)
|
||||
|
||||
#endif // hifi_HFActionEvent_h
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// HFBackEvent.cpp
|
||||
// script-engine/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-10-27.
|
||||
// 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 "HFBackEvent.h"
|
||||
|
||||
HFBackEvent::HFBackEvent(QEvent::Type type) :
|
||||
HFMetaEvent(type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QEvent::Type HFBackEvent::startType() {
|
||||
static QEvent::Type startType = HFMetaEvent::newEventType();
|
||||
return startType;
|
||||
}
|
||||
|
||||
QEvent::Type HFBackEvent::endType() {
|
||||
static QEvent::Type endType = HFMetaEvent::newEventType();
|
||||
return endType;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// HFBackEvent.h
|
||||
// script-engine/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-10-27.
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef hifi_HFBackEvent_h
|
||||
#define hifi_HFBackEvent_h
|
||||
|
||||
#include <qevent.h>
|
||||
#include <qscriptengine.h>
|
||||
|
||||
#include "HFMetaEvent.h"
|
||||
|
||||
class HFBackEvent : public HFMetaEvent {
|
||||
public:
|
||||
HFBackEvent() {};
|
||||
HFBackEvent(QEvent::Type type);
|
||||
|
||||
static QEvent::Type startType();
|
||||
static QEvent::Type endType();
|
||||
};
|
||||
|
||||
#endif // hifi_HFBackEvent_h
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// HFMetaEvent.cpp
|
||||
// script-engine/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-10-27.
|
||||
// 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 "HFMetaEvent.h"
|
||||
|
||||
QSet<QEvent::Type> HFMetaEvent::_types = QSet<QEvent::Type>();
|
||||
|
||||
QEvent::Type HFMetaEvent::newEventType() {
|
||||
QEvent::Type newType = static_cast<QEvent::Type>(QEvent::registerEventType());
|
||||
_types.insert(newType);
|
||||
return newType;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// HFMetaEvent.h
|
||||
// script-engine/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-10-27.
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef hifi_HFMetaEvent_h
|
||||
#define hifi_HFMetaEvent_h
|
||||
|
||||
#include <qevent.h>
|
||||
|
||||
class HFMetaEvent : public QEvent {
|
||||
public:
|
||||
HFMetaEvent() : QEvent(HFMetaEvent::newEventType()) {};
|
||||
HFMetaEvent(QEvent::Type type) : QEvent(type) {};
|
||||
static const QSet<QEvent::Type>& types() { return HFMetaEvent::_types; }
|
||||
protected:
|
||||
static QEvent::Type newEventType();
|
||||
|
||||
static QSet<QEvent::Type> _types;
|
||||
};
|
||||
|
||||
#endif // hifi_HFMetaEvent_h
|
|
@ -102,8 +102,11 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) cons
|
|||
if (parent && parent->getID() == parentID) {
|
||||
// parent pointer is up-to-date
|
||||
if (!_parentKnowsMe) {
|
||||
parent->beParentOfChild(getThisPointer());
|
||||
_parentKnowsMe = true;
|
||||
SpatialParentTree* parentTree = parent->getParentTree();
|
||||
if (!parentTree || parentTree == getParentTree()) {
|
||||
parent->beParentOfChild(getThisPointer());
|
||||
_parentKnowsMe = true;
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
return parent;
|
||||
|
@ -129,8 +132,15 @@ SpatiallyNestablePointer SpatiallyNestable::getParentPointer(bool& success) cons
|
|||
|
||||
parent = _parent.lock();
|
||||
if (parent) {
|
||||
parent->beParentOfChild(getThisPointer());
|
||||
_parentKnowsMe = true;
|
||||
|
||||
// it's possible for an entity with a parent of AVATAR_SELF_ID can be imported into a side-tree
|
||||
// such as the clipboard's. if this is the case, we don't want the parent to consider this a
|
||||
// child.
|
||||
SpatialParentTree* parentTree = parent->getParentTree();
|
||||
if (!parentTree || parentTree == getParentTree()) {
|
||||
parent->beParentOfChild(getThisPointer());
|
||||
_parentKnowsMe = true;
|
||||
}
|
||||
}
|
||||
|
||||
success = (parent || parentID.isNull());
|
||||
|
|
|
@ -546,6 +546,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseEquip", args);
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
ensureDynamic(this.targetEntityID);
|
||||
this.targetEntityID = null;
|
||||
this.messageGrabEntity = false;
|
||||
|
|
|
@ -144,6 +144,12 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
Entities.deleteAction(this.targetEntityID, this.actionID);
|
||||
this.actionID = null;
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
this.targetEntityID = null;
|
||||
};
|
||||
|
||||
|
|
|
@ -138,6 +138,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args);
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
};
|
||||
|
|
|
@ -148,6 +148,12 @@ Script.include("/~/system/libraries/utils.js");
|
|||
}
|
||||
}
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.grabbedThingID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
this.grabbedThingID = null;
|
||||
};
|
||||
|
||||
|
|
|
@ -264,6 +264,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (!this.stylusTip.valid || this.overlayLaserActive(controllerData) || this.otherModuleNeedsToRun(controllerData)) {
|
||||
this.pointFinger(false);
|
||||
this.hideStylus();
|
||||
this.stylusTouchingTarget = false;
|
||||
this.relinquishTouchFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,6 +150,23 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
|
|||
parentJointIndex: -1
|
||||
});
|
||||
|
||||
this.homeButtonHighlightID = Overlays.addOverlay("circle3d", {
|
||||
name: "homeButtonHighlight",
|
||||
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET + 0.003, z: -0.0158 },
|
||||
localRotation: { x: 0, y: 1, z: 0, w: 0 },
|
||||
dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor },
|
||||
solid: true,
|
||||
outerRadius: 25 * tabletScaleFactor,
|
||||
innerRadius: 20 * tabletScaleFactor,
|
||||
ignoreIntersection: true,
|
||||
alpha: 1.0,
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
visible: visible,
|
||||
drawInFront: false,
|
||||
parentID: this.tabletEntityID,
|
||||
parentJointIndex: -1
|
||||
});
|
||||
|
||||
this.receive = function (channel, senderID, senderUUID, localOnly) {
|
||||
if (_this.homeButtonID == senderID) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
|
@ -170,6 +187,23 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
|
|||
}
|
||||
};
|
||||
|
||||
this.myOnHoverEnterOverlay = function (overlayID, pointerEvent) {
|
||||
_this.onHoverEnterOverlay(overlayID, pointerEvent);
|
||||
};
|
||||
|
||||
Overlays.hoverEnterOverlay.connect(this.myOnHoverEnterOverlay);
|
||||
|
||||
this.myOnHoverLeaveOverlay = function (overlayID, pointerEvent) {
|
||||
_this.onHoverLeaveOverlay(overlayID, pointerEvent);
|
||||
};
|
||||
|
||||
Overlays.hoverLeaveOverlay.connect(this.myOnHoverLeaveOverlay);
|
||||
|
||||
this.myOnHoverOverOverlay = function (overlayID, pointerEvent) {
|
||||
_this.onHoverOverOverlay(overlayID, pointerEvent);
|
||||
};
|
||||
Overlays.hoverOverOverlay.connect(this.myOnHoverOverOverlay);
|
||||
|
||||
this.state = "idle";
|
||||
|
||||
this.getRoot = function() {
|
||||
|
@ -273,9 +307,14 @@ WebTablet.prototype.setWidth = function (width) {
|
|||
};
|
||||
|
||||
WebTablet.prototype.destroy = function () {
|
||||
Overlays.hoverEnterOverlay.disconnect(this.myOnHoverEnterOverlay);
|
||||
Overlays.hoverLeaveOverlay.disconnect(this.myOnHoverLeaveOverlay);
|
||||
Overlays.hoverOverOverlay.disconnect(this.myOnHoverOverOverlay);
|
||||
|
||||
Overlays.deleteOverlay(this.webOverlayID);
|
||||
Overlays.deleteOverlay(this.tabletEntityID);
|
||||
Overlays.deleteOverlay(this.homeButtonID);
|
||||
Overlays.deleteOverlay(this.homeButtonHighlightID);
|
||||
HMD.displayModeChanged.disconnect(this.myOnHmdChanged);
|
||||
|
||||
Controller.mousePressEvent.disconnect(this.myMousePressEvent);
|
||||
|
@ -367,6 +406,24 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos
|
|||
};
|
||||
};
|
||||
|
||||
WebTablet.prototype.onHoverEnterOverlay = function (overlayID, pointerEvent) {
|
||||
if (overlayID === this.homeButtonID) {
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 1.0 });
|
||||
}
|
||||
}
|
||||
|
||||
WebTablet.prototype.onHoverOverOverlay = function (overlayID, pointerEvent) {
|
||||
if (overlayID !== this.homeButtonID) {
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 });
|
||||
}
|
||||
}
|
||||
|
||||
WebTablet.prototype.onHoverLeaveOverlay = function (overlayID, pointerEvent) {
|
||||
if (overlayID === this.homeButtonID) {
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 });
|
||||
}
|
||||
}
|
||||
|
||||
// compute position, rotation & parentJointIndex of the tablet
|
||||
WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMouse, tabletProperties) {
|
||||
if (HMD.active) {
|
||||
|
@ -504,6 +561,22 @@ WebTablet.prototype.scheduleMouseMoveProcessor = function() {
|
|||
}
|
||||
};
|
||||
|
||||
WebTablet.prototype.handleHomeButtonHover = function(x, y) {
|
||||
var pickRay = Camera.computePickRay(x, y);
|
||||
var entityPickResults;
|
||||
var homebuttonHovered = false;
|
||||
entityPickResults = Overlays.findRayIntersection(pickRay, true, [this.tabletEntityID]);
|
||||
if (entityPickResults.intersects && (entityPickResults.entityID === this.tabletEntityID ||
|
||||
entityPickResults.overlayID === this.tabletEntityID)) {
|
||||
var overlayPickResults = Overlays.findRayIntersection(pickRay, true, [this.homeButtonID], []);
|
||||
if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) {
|
||||
homebuttonHovered = true;
|
||||
}
|
||||
}
|
||||
|
||||
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: homebuttonHovered ? 1.0 : 0.0 });
|
||||
}
|
||||
|
||||
WebTablet.prototype.mouseMoveEvent = function (event) {
|
||||
if (this.dragging) {
|
||||
this.currentMouse = {
|
||||
|
@ -511,6 +584,8 @@ WebTablet.prototype.mouseMoveEvent = function (event) {
|
|||
y: event.y
|
||||
};
|
||||
this.scheduleMouseMoveProcessor();
|
||||
} else {
|
||||
this.handleHomeButtonHover(event.x, event.y);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -537,6 +612,8 @@ WebTablet.prototype.mouseMoveProcessor = function () {
|
|||
});
|
||||
}
|
||||
this.scheduleMouseMoveProcessor();
|
||||
} else {
|
||||
this.handleHomeButtonHover(this.currentMouse.x, this.currentMouse.y);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ getControllerJointIndex = function (hand) {
|
|||
return controllerJointIndex;
|
||||
}
|
||||
|
||||
return MyAvatar.getJointIndex("Head");
|
||||
return -1;
|
||||
};
|
||||
|
||||
propsArePhysical = function (props) {
|
||||
|
|
|
@ -370,7 +370,7 @@ getTabletWidthFromSettings = function () {
|
|||
|
||||
resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) {
|
||||
|
||||
if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID) {
|
||||
if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID || !HMD.homeButtonHighlightID) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -413,4 +413,11 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
|
|||
localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0},
|
||||
dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor}
|
||||
});
|
||||
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, {
|
||||
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET + 0.003, z: -0.0158 },
|
||||
dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor },
|
||||
outerRadius: 25 * tabletScaleFactor,
|
||||
innerRadius: 20 * tabletScaleFactor
|
||||
});
|
||||
};
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
UIWebTablet.register();
|
||||
HMD.tabletID = UIWebTablet.tabletEntityID;
|
||||
HMD.homeButtonID = UIWebTablet.homeButtonID;
|
||||
HMD.homeButtonHighlightID = UIWebTablet.homeButtonHighlightID;
|
||||
HMD.tabletScreenID = UIWebTablet.webOverlayID;
|
||||
HMD.displayModeChanged.connect(onHmdChanged);
|
||||
MyAvatar.sensorToWorldScaleChanged.connect(onSensorToWorldScaleChanged);
|
||||
|
@ -127,6 +128,7 @@
|
|||
tabletProperties.visible = true;
|
||||
Overlays.editOverlay(HMD.tabletID, tabletProperties);
|
||||
Overlays.editOverlay(HMD.homeButtonID, { visible: true });
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { visible: true });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 });
|
||||
updateTabletWidthFromSettings(true);
|
||||
|
@ -147,6 +149,7 @@
|
|||
|
||||
Overlays.editOverlay(HMD.tabletID, { visible: false });
|
||||
Overlays.editOverlay(HMD.homeButtonID, { visible: false });
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { visible: false });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 1 });
|
||||
}
|
||||
|
@ -167,6 +170,7 @@
|
|||
UIWebTablet = null;
|
||||
HMD.tabletID = null;
|
||||
HMD.homeButtonID = null;
|
||||
HMD.homeButtonHighlightID = null;
|
||||
HMD.tabletScreenID = null;
|
||||
} else if (debugTablet) {
|
||||
print("TABLET closeTabletUI, UIWebTablet is null");
|
||||
|
@ -319,6 +323,7 @@
|
|||
Overlays.deleteOverlay(tabletID);
|
||||
HMD.tabletID = null;
|
||||
HMD.homeButtonID = null;
|
||||
HMD.homeButtonHighlightID = null;
|
||||
HMD.tabletScreenID = null;
|
||||
});
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
10
tests/baking/CMakeLists.txt
Normal file
10
tests/baking/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
# Declare dependencies
|
||||
macro (setup_testcase_dependencies)
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(shared baking)
|
||||
|
||||
package_libraries_for_deployment()
|
||||
endmacro ()
|
||||
|
||||
setup_hifi_testcase()
|
92
tests/baking/src/JSBakerTest.cpp
Normal file
92
tests/baking/src/JSBakerTest.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// JSBakerTest.cpp
|
||||
// tests/networking/src
|
||||
//
|
||||
// Created by Utkarsh Gautam on 09/26/17.
|
||||
// Copyright 2015 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 "JSBakerTest.h"
|
||||
QTEST_MAIN(JSBakerTest)
|
||||
|
||||
void JSBakerTest::setTestCases() {
|
||||
// Test cases contain a std::pair(input, desiredOutput)
|
||||
|
||||
_testCases.emplace_back("var a=1;", "var a=1;");
|
||||
_testCases.emplace_back("var a=1;//single line comment\nvar b=2;", "var a=1;var b=2;");
|
||||
_testCases.emplace_back("a\rb", "a\nb");
|
||||
_testCases.emplace_back("a/*multi\n line \n comment*/ b", "ab");
|
||||
_testCases.emplace_back("a/b", "a/b");
|
||||
_testCases.emplace_back("var a = 1;", "var a=1;"); // Multiple spaces omitted
|
||||
_testCases.emplace_back("var a=\t\t\t1;", "var a=1;"); // Multiple tabs omitted
|
||||
|
||||
// Cases for space not omitted
|
||||
_testCases.emplace_back("var x", "var x");
|
||||
_testCases.emplace_back("a '", "a '");
|
||||
_testCases.emplace_back("a $", "a $");
|
||||
_testCases.emplace_back("a _", "a _");
|
||||
_testCases.emplace_back("a /", "a /");
|
||||
_testCases.emplace_back("a 1", "a 1");
|
||||
_testCases.emplace_back("1 a", "1 a");
|
||||
_testCases.emplace_back("$ a", "$ a");
|
||||
_testCases.emplace_back("_ a", "_ a");
|
||||
_testCases.emplace_back("/ a", "/ a");
|
||||
_testCases.emplace_back("$ $", "$ $");
|
||||
_testCases.emplace_back("_ _", "_ _");
|
||||
_testCases.emplace_back("/ /", "/ /");
|
||||
|
||||
_testCases.emplace_back("a\n\n\n\nb", "a\nb"); // Skip multiple new lines
|
||||
_testCases.emplace_back("a\n\n b", "a\nb"); // Skip multiple new lines followed by whitespace
|
||||
_testCases.emplace_back("a\n\n b", "a\nb"); // Skip multiple new lines followed by tab
|
||||
|
||||
//Cases for new line not omitted
|
||||
_testCases.emplace_back("a\nb", "a\nb");
|
||||
_testCases.emplace_back("a\n9", "a\n9");
|
||||
_testCases.emplace_back("9\na", "9\na");
|
||||
_testCases.emplace_back("a\n$", "a\n$");
|
||||
_testCases.emplace_back("a\n[", "a\n[");
|
||||
_testCases.emplace_back("a\n{", "a\n{");
|
||||
_testCases.emplace_back("a\n(", "a\n(");
|
||||
_testCases.emplace_back("a\n+", "a\n+");
|
||||
_testCases.emplace_back("a\n'", "a\n'");
|
||||
_testCases.emplace_back("a\n-", "a\n-");
|
||||
_testCases.emplace_back("$\na", "$\na");
|
||||
_testCases.emplace_back("$\na", "$\na");
|
||||
_testCases.emplace_back("_\na", "_\na");
|
||||
_testCases.emplace_back("]\na", "]\na");
|
||||
_testCases.emplace_back("}\na", "}\na");
|
||||
_testCases.emplace_back(")\na", ")\na");
|
||||
_testCases.emplace_back("+\na", "+\na");
|
||||
_testCases.emplace_back("-\na", "-\na");
|
||||
|
||||
// Cases to check quoted strings are not modified
|
||||
_testCases.emplace_back("'abcd1234$%^&[](){}'\na", "'abcd1234$%^&[](){}'\na");
|
||||
_testCases.emplace_back("\"abcd1234$%^&[](){}\"\na", "\"abcd1234$%^&[](){}\"\na");
|
||||
_testCases.emplace_back("`abcd1234$%^&[](){}`\na", "`abcd1234$%^&[](){}`a");
|
||||
|
||||
// Edge Cases
|
||||
|
||||
//No semicolon to terminate an expression, instead a new line used for termination
|
||||
_testCases.emplace_back("var x=5\nvar y=6;", "var x=5\nvar y=6;");
|
||||
|
||||
//a + ++b is minified as a+ ++b.
|
||||
_testCases.emplace_back("a + ++b", "a + ++b");
|
||||
|
||||
//a - --b is minified as a- --b.
|
||||
_testCases.emplace_back("a - --b", "a - --b");
|
||||
}
|
||||
|
||||
void JSBakerTest::testJSBaking() {
|
||||
|
||||
for (int i = 0;i < _testCases.size();i++) {
|
||||
QByteArray output;
|
||||
auto input = _testCases.at(i).first;
|
||||
JSBaker::bakeJS(input, output);
|
||||
|
||||
auto desiredOutput = _testCases.at(i).second;
|
||||
QCOMPARE(output, desiredOutput);
|
||||
}
|
||||
}
|
29
tests/baking/src/JSBakerTest.h
Normal file
29
tests/baking/src/JSBakerTest.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// JSBakerTest.h
|
||||
// tests/networking/src
|
||||
//
|
||||
// Created by Utkarsh Gautam on 9/26/17.
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
#ifndef hifi_JSBakerTest_h
|
||||
#define hifi_JSBakerTest_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <JSBaker.h>
|
||||
|
||||
class JSBakerTest : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void setTestCases();
|
||||
void testJSBaking();
|
||||
|
||||
private:
|
||||
std::vector<std::pair<QByteArray, QByteArray>> _testCases;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global CreatePalette: true, App, Feedback, History, UIT */
|
||||
/* global CreatePalette:true, App, Feedback, History, Preload, UIT */
|
||||
|
||||
CreatePalette = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
||||
// Tool menu displayed on top of forearm.
|
||||
|
@ -332,6 +332,11 @@ CreatePalette = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
}
|
||||
|
||||
|
||||
function getAssetURLs() {
|
||||
return Preload.findURLs([PALETTE_HEADER_HEADING_PROPERTIES, PALETTE_HEADER_BAR_PROPERTIES, PALETTE_TITLE_PROPERTIES,
|
||||
PALETTE_ITEMS]);
|
||||
}
|
||||
|
||||
function setHand(hand) {
|
||||
// Assumes UI is not displaying.
|
||||
var NUMBER_OF_HANDS = 2;
|
||||
|
@ -533,6 +538,7 @@ CreatePalette = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
}
|
||||
|
||||
return {
|
||||
assetURLs: getAssetURLs,
|
||||
setHand: setHand,
|
||||
overlayIDs: getOverlayIDs,
|
||||
setVisible: setVisible,
|
||||
|
|
175
unpublishedScripts/marketplace/shapes/modules/preload.js
Normal file
175
unpublishedScripts/marketplace/shapes/modules/preload.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// preload.js
|
||||
//
|
||||
// Created by David Rowe on 11 Oct 2017.
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
/* global Preload:true, App */
|
||||
|
||||
Preload = (function () {
|
||||
// Provide facility to preload asset files so that they are in disk cache.
|
||||
// Global object.
|
||||
|
||||
"use strict";
|
||||
|
||||
var loadTimer = null,
|
||||
urlsToLoad = [],
|
||||
nextURLToLoad = 0,
|
||||
LOAD_INTERVAL = 50, // ms
|
||||
overlays = [],
|
||||
deleteTimer = null,
|
||||
DELETE_INTERVAL = LOAD_INTERVAL; // ms
|
||||
|
||||
function findURLs(items) {
|
||||
var urls = [],
|
||||
i,
|
||||
length;
|
||||
|
||||
function findURLsInObject(item) {
|
||||
var property;
|
||||
|
||||
for (property in item) {
|
||||
if (item.hasOwnProperty(property)) {
|
||||
if (property === "url" || property === "imageURL" || property === "imageOverlayURL") {
|
||||
if (item[property]) {
|
||||
urls.push(item[property]);
|
||||
}
|
||||
} else if (typeof item[property] === "object") {
|
||||
findURLsInObject(item[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, length = items.length; i < length; i++) {
|
||||
switch (typeof items[i]) {
|
||||
case "string":
|
||||
urls.push(items[i]);
|
||||
break;
|
||||
case "object":
|
||||
findURLsInObject(items[i]);
|
||||
break;
|
||||
default:
|
||||
App.log("ERROR: Cannot find URL in item type " + (typeof items[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
function deleteOverlay() {
|
||||
if (overlays.length === 0) { // Just in case.
|
||||
deleteTimer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Overlays.deleteOverlay(overlays[0]);
|
||||
overlays.shift();
|
||||
|
||||
if (overlays.length > 0) {
|
||||
deleteTimer = Script.setTimeout(deleteOverlay, DELETE_INTERVAL);
|
||||
} else {
|
||||
deleteTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function loadNextURL() {
|
||||
|
||||
function loadURL(url) {
|
||||
var DOMAIN_CORNER = { x: -16382, y: -16382, z: -16382 }, // Near but not right on domain corner.
|
||||
DUMMY_OVERLAY_PROPERTIES = {
|
||||
fbx: {
|
||||
overlay: "model",
|
||||
dimensions: { x: 0.001, y: 0.001, z: 0.001 },
|
||||
position: DOMAIN_CORNER,
|
||||
ignoreRayIntersection: false,
|
||||
alpha: 0.0,
|
||||
visible: false
|
||||
},
|
||||
svg: {
|
||||
overlay: "image3d",
|
||||
scale: 0.001,
|
||||
position: DOMAIN_CORNER,
|
||||
ignoreRayIntersection: true,
|
||||
alpha: 0.0,
|
||||
visible: false
|
||||
},
|
||||
png: {
|
||||
overlay: "image3d",
|
||||
scale: 0.001,
|
||||
position: DOMAIN_CORNER,
|
||||
ignoreRayIntersection: true,
|
||||
alpha: 0.0,
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
fileType,
|
||||
properties;
|
||||
|
||||
fileType = url.slice(-3);
|
||||
if (DUMMY_OVERLAY_PROPERTIES.hasOwnProperty(fileType)) {
|
||||
properties = Object.clone(DUMMY_OVERLAY_PROPERTIES[fileType]);
|
||||
properties.url = url;
|
||||
overlays.push(Overlays.addOverlay(properties.overlay, properties));
|
||||
if (deleteTimer === null) {
|
||||
// Can't delete overlay straight away otherwise asset load is abandoned.
|
||||
deleteTimer = Script.setTimeout(deleteOverlay, DELETE_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
App.log("ERROR: Cannot preload asset " + url);
|
||||
}
|
||||
}
|
||||
|
||||
// Find next URL that hasn't already been loaded;
|
||||
while (nextURLToLoad < urlsToLoad.length && urlsToLoad.indexOf(urlsToLoad[nextURLToLoad]) < nextURLToLoad) {
|
||||
nextURLToLoad += 1;
|
||||
}
|
||||
|
||||
// Load the URL if there's one to load.
|
||||
if (nextURLToLoad < urlsToLoad.length) {
|
||||
// Load the URL.
|
||||
loadURL(urlsToLoad[nextURLToLoad]);
|
||||
nextURLToLoad += 1;
|
||||
|
||||
// Load the next, if any, after a short delay.
|
||||
loadTimer = Script.setTimeout(loadNextURL, LOAD_INTERVAL);
|
||||
} else {
|
||||
loadTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function load(urls) {
|
||||
urlsToLoad = urlsToLoad.concat(urls);
|
||||
if (loadTimer === null) {
|
||||
loadNextURL();
|
||||
}
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
var i,
|
||||
length;
|
||||
|
||||
if (loadTimer) {
|
||||
Script.clearTimeout(loadTimer);
|
||||
}
|
||||
|
||||
if (deleteTimer) {
|
||||
Script.clearTimeout(deleteTimer);
|
||||
for (i = 0, length = overlays.length; i < length; i++) {
|
||||
Overlays.deleteOverlay(overlays[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(tearDown);
|
||||
|
||||
return {
|
||||
findURLs: findURLs,
|
||||
load: load
|
||||
};
|
||||
|
||||
}());
|
|
@ -72,6 +72,10 @@ ToolIcon = function (side) {
|
|||
return new ToolIcon();
|
||||
}
|
||||
|
||||
function getAssetURLs() {
|
||||
return [MODEL_PROPERTIES.url];
|
||||
}
|
||||
|
||||
function setHand(side) {
|
||||
// Assumes UI is not displaying.
|
||||
if (side === LEFT_HAND) {
|
||||
|
@ -154,6 +158,7 @@ ToolIcon = function (side) {
|
|||
}
|
||||
|
||||
return {
|
||||
assetURLs: getAssetURLs,
|
||||
setHand: setHand,
|
||||
display: display,
|
||||
clear: clear,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global ToolsMenu: true, App, Feedback, UIT */
|
||||
/* global ToolsMenu:true, App, Feedback, Preload, UIT */
|
||||
|
||||
ToolsMenu = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
||||
// Tool menu displayed on top of forearm.
|
||||
|
@ -2042,6 +2042,12 @@ ToolsMenu = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
return new ToolsMenu();
|
||||
}
|
||||
|
||||
function getAssetURLs() {
|
||||
return Preload.findURLs([MENU_HEADER_HEADING_PROPERTIES, MENU_HEADER_BAR_PROPERTIES, MENU_HEADER_BACK_PROPERTIES,
|
||||
MENU_HEADER_TITLE_PROPERTIES, MENU_HEADER_TITLE_BACK_URL, MENU_HEADER_ICON_PROPERTIES, UI_ELEMENTS,
|
||||
PICKLIST_UP_ARROW, PICKLIST_DOWN_ARROW, OPTONS_PANELS, MENU_ITEMS, FOOTER_ITEMS]);
|
||||
}
|
||||
|
||||
controlHand = side === LEFT_HAND ? rightInputs.hand() : leftInputs.hand();
|
||||
|
||||
function setHand(hand) {
|
||||
|
@ -3672,6 +3678,7 @@ ToolsMenu = function (side, leftInputs, rightInputs, uiCommandCallback) {
|
|||
}
|
||||
|
||||
return {
|
||||
assetURLs: getAssetURLs,
|
||||
COLOR_TOOL: COLOR_TOOL,
|
||||
SCALE_TOOL: SCALE_TOOL,
|
||||
CLONE_TOOL: CLONE_TOOL,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global Feedback, History */
|
||||
/* global Feedback, History, Preload */
|
||||
|
||||
(function () {
|
||||
|
||||
|
@ -87,6 +87,7 @@
|
|||
Script.include("./modules/highlights.js");
|
||||
Script.include("./modules/history.js");
|
||||
Script.include("./modules/laser.js");
|
||||
Script.include("./modules/preload.js");
|
||||
Script.include("./modules/selection.js");
|
||||
Script.include("./modules/toolIcon.js");
|
||||
Script.include("./modules/toolsMenu.js");
|
||||
|
@ -235,8 +236,12 @@
|
|||
}
|
||||
|
||||
toolIcon = new ToolIcon(otherHand(side));
|
||||
toolsMenu = new ToolsMenu(side, leftInputs, rightInputs, uiCommandCallback);
|
||||
createPalette = new CreatePalette(side, leftInputs, rightInputs, uiCommandCallback);
|
||||
toolsMenu = new ToolsMenu(side, leftInputs, rightInputs, uiCommandCallback);
|
||||
|
||||
Preload.load(toolIcon.assetURLs());
|
||||
Preload.load(createPalette.assetURLs());
|
||||
Preload.load(toolsMenu.assetURLs());
|
||||
|
||||
getIntersection = side === LEFT_HAND ? rightInputs.intersection : leftInputs.intersection;
|
||||
|
||||
|
|
Loading…
Reference in a new issue