Merge branch 'master' of https://github.com/highfidelity/hifi into hyperlink-photo

This commit is contained in:
Stephen Birarda 2015-06-26 14:40:01 -07:00
commit 9b84eabd18
29 changed files with 280 additions and 61 deletions

View file

@ -1321,6 +1321,15 @@ PropertiesTool = function(opts) {
pushCommandForSelections();
selectionManager._update();
}
} else if (data.action == "reloadScript") {
if (selectionManager.hasSelection()) {
var timestamp = Date.now();
for (var i = 0; i < selectionManager.selections.length; i++) {
Entities.editEntity(selectionManager.selections[i], {
scriptTimestamp: timestamp,
});
}
}
} else if (data.action == "centerAtmosphereToZone") {
if (selectionManager.hasSelection()) {
selectionManager.saveProperties();

View file

@ -250,6 +250,8 @@
var elCollisionSoundURL = document.getElementById("property-collision-sound-url");
var elLifetime = document.getElementById("property-lifetime");
var elScriptURL = document.getElementById("property-script-url");
var elScriptTimestamp = document.getElementById("property-script-timestamp");
var elReloadScriptButton = document.getElementById("reload-script-button");
var elUserData = document.getElementById("property-user-data");
var elColorSection = document.getElementById("color-section");
@ -470,6 +472,7 @@
elCollisionSoundURL.value = properties.collisionSoundURL;
elLifetime.value = properties.lifetime;
elScriptURL.value = properties.script;
elScriptTimestamp.value = properties.scriptTimestamp;
elUserData.value = properties.userData;
elHyperlinkHref.value = properties.href;
@ -688,6 +691,7 @@
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script'));
elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp'));
elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData'));
var colorChangeFunction = createEmitColorPropertyUpdateFunction(
@ -889,6 +893,12 @@
percentage: parseInt(elRescaleDimensionsPct.value),
}));
});
elReloadScriptButton.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({
type: "action",
action: "reloadScript"
}));
});
elCenterAtmosphereToZone.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({
type: "action",
@ -1181,7 +1191,10 @@
</div>
<div class="property">
<div class="label">Script URL</div>
<div class="label">Script URL
<input type="hidden" id="property-script-timestamp" class="value"></input>
<input type="button" id="reload-script-button" value="Reload"></input>
</div>
<div class="value">
<input id="property-script-url" class="url"></input>
</div>

View file

@ -260,6 +260,11 @@ table#properties-list {
height: 1.2em;
}
#properties-list .label input[type=button] {
float: right;
padding: 0 5px 1px;
}
#properties-list .value > div{
padding: 3pt 0;
}

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
viewBox="0 0 100 100"
enable-background="new 0 0 100 100"
xml:space="preserve"
id="svg2"
inkscape:version="0.91 r13725"
sodipodi:docname="reload-script-43339.svg"><metadata
id="metadata14"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs12" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1184"
inkscape:window-height="655"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-12.5"
inkscape:cy="56.355932"
inkscape:window-x="424"
inkscape:window-y="79"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" /><g
id="g4"
style="fill:#c4c4c4;fill-opacity:1"
transform="matrix(1.0520186,0,0,1.0809642,-4.9561957,-7.0141066)"><g
id="g6"
style="fill:#c4c4c4;fill-opacity:1"><path
d="m 8.139,47.902 14.505,0 c 1.51,0 2.838,-0.987 3.28,-2.429 1.222,-4.042 3.425,-7.649 6.357,-10.583 4.643,-4.627 10.918,-7.442 17.982,-7.45 7.056,0.008 13.331,2.823 17.979,7.45 0.144,0.147 0.271,0.31 0.411,0.457 L 59.46,46.155 c -0.257,0.299 -0.313,0.724 -0.157,1.078 0.173,0.365 0.53,0.59 0.923,0.584 l 38.526,0.111 c 0.294,0.005 0.581,-0.129 0.771,-0.352 0.197,-0.231 0.278,-0.527 0.23,-0.818 L 93.483,8.741 C 93.421,8.353 93.137,8.038 92.753,7.933 92.375,7.828 91.968,7.952 91.714,8.248 L 82.256,19.366 C 73.983,11.441 62.706,6.512 50.337,6.491 50.279,6.488 50.206,6.488 50.122,6.491 37.396,6.527 25.801,11.73 17.469,20.08 11.119,26.417 6.604,34.634 4.776,43.81 c -0.198,1.013 0.062,2.046 0.715,2.843 0.655,0.793 1.617,1.249 2.648,1.249 z m 90.845,10.939 c -0.652,-0.798 -1.618,-1.259 -2.646,-1.259 l -14.506,0 c -1.507,0 -2.836,0.991 -3.279,2.435 -1.223,4.039 -3.427,7.649 -6.357,10.587 -4.64,4.622 -10.915,7.439 -17.982,7.45 -7.056,-0.011 -13.331,-2.828 -17.979,-7.45 -0.144,-0.146 -0.269,-0.32 -0.41,-0.464 l 9.196,-10.811 c 0.256,-0.294 0.311,-0.717 0.154,-1.076 -0.173,-0.356 -0.527,-0.587 -0.923,-0.585 L 5.727,57.561 c -0.294,0 -0.581,0.126 -0.773,0.352 -0.195,0.229 -0.277,0.524 -0.229,0.824 l 6.271,38.012 c 0.062,0.388 0.345,0.701 0.729,0.812 0.378,0.104 0.784,-0.025 1.039,-0.322 L 22.22,86.125 c 8.278,7.922 19.553,12.859 31.921,12.87 0.06,0.005 0.131,0.005 0.215,0 12.729,-0.032 24.323,-5.237 32.655,-13.583 6.348,-6.338 10.865,-14.561 12.69,-23.728 0.199,-1.012 -0.062,-2.045 -0.717,-2.843 z"
id="path8"
style="fill:#c4c4c4;fill-opacity:1"
inkscape:connector-curvature="0" /></g></g></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -4048,6 +4048,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
connect(scriptEngine, SIGNAL(finished(const QString&)), this, SLOT(scriptFinished(const QString&)));
connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool)));
connect(scriptEngine, SIGNAL(reloadScript(const QString&, bool)), this, SLOT(reloadScript(const QString&, bool)));
scriptEngine->registerGlobalObject("Overlays", &_overlays);
qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
@ -4263,7 +4264,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
}
ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded,
bool loadScriptFromEditor, bool activateMainWindow) {
bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
if (isAboutToQuit()) {
return NULL;
@ -4292,7 +4293,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError);
// get the script engine object to load the script at the designated script URL
scriptEngine->loadURL(scriptUrl);
scriptEngine->loadURL(scriptUrl, reload);
}
// restore the main window's active state
@ -4303,6 +4304,10 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
return scriptEngine;
}
void Application::reloadScript(const QString& scriptName, bool isUserLoaded) {
loadScript(scriptName, isUserLoaded, false, false, true);
}
void Application::handleScriptEngineLoaded(const QString& scriptFilename) {
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
@ -4330,14 +4335,25 @@ void Application::scriptFinished(const QString& scriptName) {
}
void Application::stopAllScripts(bool restart) {
// stops all current running scripts
if (restart) {
// Delete all running scripts from cache so that they are re-downloaded when they are restarted
auto scriptCache = DependencyManager::get<ScriptCache>();
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
it != _scriptEnginesHash.constEnd(); it++) {
if (!it.value()->isFinished()) {
scriptCache->deleteScript(it.key());
}
}
}
// Stop and possibly restart all currently running scripts
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
it != _scriptEnginesHash.constEnd(); it++) {
if (it.value()->isFinished()) {
continue;
}
if (restart && it.value()->isUserLoaded()) {
connect(it.value(), SIGNAL(finished(const QString&)), SLOT(loadScript(const QString&)));
connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
}
it.value()->stop();
qCDebug(interfaceapp) << "stopping script..." << it.key();
@ -4345,13 +4361,20 @@ void Application::stopAllScripts(bool restart) {
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
// whenever a script stops in case it happened to have been setting joint rotations.
// TODO: expose animation priorities and provide a layered animation control system.
_myAvatar->clearJointAnimationPriorities();
_myAvatar->clearScriptableSettings();
}
void Application::stopScript(const QString &scriptName) {
void Application::stopScript(const QString &scriptName, bool restart) {
const QString& scriptURLString = QUrl(scriptName).toString();
if (_scriptEnginesHash.contains(scriptURLString)) {
_scriptEnginesHash.value(scriptURLString)->stop();
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
if (restart) {
auto scriptCache = DependencyManager::get<ScriptCache>();
scriptCache->deleteScript(scriptName);
connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&)));
}
scriptEngine->stop();
qCDebug(interfaceapp) << "stopping script..." << scriptName;
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
// whenever a script stops in case it happened to have been setting joint rotations.
@ -4367,6 +4390,10 @@ void Application::reloadAllScripts() {
stopAllScripts(true);
}
void Application::reloadOneScript(const QString& scriptName) {
stopScript(scriptName, true);
}
void Application::loadDefaultScripts() {
if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) {
loadScript(DEFAULT_SCRIPTS_JS_URL);

View file

@ -409,15 +409,19 @@ public slots:
bool acceptSnapshot(const QString& urlString);
bool askToSetAvatarUrl(const QString& url);
bool askToLoadScript(const QString& scriptFilenameOrURL);
ScriptEngine* loadScript(const QString& scriptFilename = QString(), bool isUserLoaded = true,
bool loadScriptFromEditor = false, bool activateMainWindow = false);
bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
void reloadScript(const QString& scriptName, bool isUserLoaded = true);
void scriptFinished(const QString& scriptName);
void stopAllScripts(bool restart = false);
void stopScript(const QString& scriptName);
void stopScript(const QString& scriptName, bool restart = false);
void reloadAllScripts();
void reloadOneScript(const QString& scriptName);
void loadDefaultScripts();
void toggleRunningScriptsWidget();
void saveScripts();
void showFriendsWindow();
void friendsWindowClosed();

View file

@ -32,7 +32,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint |
Qt::WindowCloseButtonHint),
ui(new Ui::RunningScriptsWidget),
_signalMapper(this),
_reloadSignalMapper(this),
_stopSignalMapper(this),
_scriptsModelFilter(this),
_scriptsModel(this) {
ui->setupUi(this);
@ -64,7 +65,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
Application::getInstance(), &Application::loadDialog);
connect(ui->loadScriptFromURLButton, &QPushButton::clicked,
Application::getInstance(), &Application::loadScriptURLDialog);
connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
connect(&_reloadSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(reloadOneScript(const QString&)));
connect(&_stopSignalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
UIUtil::scaleWidgetFontSizes(this);
}
@ -115,6 +117,17 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
name->setText(name->text() + "(" + QString::number(hash.find(list.at(i)).value()) + ")");
}
++hash[list.at(i)];
QPushButton* reloadButton = new QPushButton(row);
reloadButton->setFlat(true);
reloadButton->setIcon(
QIcon(QPixmap(PathUtils::resourcesPath() + "images/reload-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT)));
reloadButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
reloadButton->setStyleSheet("border: 0;");
reloadButton->setCursor(Qt::PointingHandCursor);
connect(reloadButton, SIGNAL(clicked()), &_reloadSignalMapper, SLOT(map()));
_reloadSignalMapper.setMapping(reloadButton, url.toString());
QPushButton* closeButton = new QPushButton(row);
closeButton->setFlat(true);
closeButton->setIcon(
@ -122,9 +135,8 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
closeButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
closeButton->setStyleSheet("border: 0;");
closeButton->setCursor(Qt::PointingHandCursor);
connect(closeButton, SIGNAL(clicked()), &_signalMapper, SLOT(map()));
_signalMapper.setMapping(closeButton, url.toString());
connect(closeButton, SIGNAL(clicked()), &_stopSignalMapper, SLOT(map()));
_stopSignalMapper.setMapping(closeButton, url.toString());
row->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
@ -132,6 +144,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
row->layout()->setSpacing(0);
row->layout()->addWidget(name);
row->layout()->addWidget(reloadButton);
row->layout()->addWidget(closeButton);
row->setToolTip(url.toString());

View file

@ -36,7 +36,7 @@ public:
const ScriptsModel* getScriptsModel() { return &_scriptsModel; }
signals:
void stopScriptName(const QString& name);
void stopScriptName(const QString& name, bool restart = false);
protected:
virtual bool eventFilter(QObject* sender, QEvent* event);
@ -59,7 +59,8 @@ private slots:
private:
Ui::RunningScriptsWidget* ui;
QSignalMapper _signalMapper;
QSignalMapper _reloadSignalMapper;
QSignalMapper _stopSignalMapper;
ScriptsModelFilter _scriptsModelFilter;
ScriptsModel _scriptsModel;
ScriptsTableWidget* _recentlyLoadedScriptsTable;

View file

@ -148,13 +148,14 @@ void EntityTreeRenderer::errorInLoadingScript(const QUrl& url) {
}
}
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload) {
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload, bool reload) {
EntityItemPointer entity = static_cast<EntityTree*>(_tree)->findEntityByEntityItemID(entityItemID);
return loadEntityScript(entity, isPreload);
return loadEntityScript(entity, isPreload, reload);
}
QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut) {
QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& urlOut,
bool& reload) {
isPending = false;
QUrl url(scriptMaybeURLorText);
@ -192,7 +193,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
auto scriptCache = DependencyManager::get<ScriptCache>();
if (!scriptCache->isInBadScriptList(url)) {
scriptContents = scriptCache->getScript(url, this, isPending);
scriptContents = scriptCache->getScript(url, this, isPending, reload);
}
}
}
@ -201,7 +202,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
}
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload) {
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload, bool reload) {
if (_shuttingDown) {
return QScriptValue(); // since we're shutting down, we don't load any more scripts
}
@ -221,8 +222,8 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
if (_entityScripts.contains(entityID)) {
EntityScriptDetails details = _entityScripts[entityID];
// check to make sure our script text hasn't changed on us since we last loaded it
if (details.scriptText == entityScript) {
// check to make sure our script text hasn't changed on us since we last loaded it and we're not redownloading it
if (details.scriptText == entityScript && !reload) {
return details.scriptObject; // previously loaded
}
@ -237,7 +238,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
bool isURL = false; // loadScriptContents() will tell us if this is a URL or just text.
bool isPending = false;
QUrl url;
QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url);
QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url, reload);
if (isPending && isPreload && isURL) {
_waitingOnPreload.insert(url, entityID);
@ -1030,17 +1031,17 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) {
}
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const bool reload) {
if (_tree && !_shuttingDown) {
checkAndCallUnload(entityID);
checkAndCallPreload(entityID);
checkAndCallPreload(entityID, reload);
}
}
void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) {
void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) {
if (_tree && !_shuttingDown) {
// load the entity script if needed...
QScriptValue entityScript = loadEntityScript(entityID, true); // is preload!
QScriptValue entityScript = loadEntityScript(entityID, true, reload); // is preload!
if (entityScript.property("preload").isValid()) {
QScriptValueList entityArgs = createEntityArgs(entityID);
entityScript.property("preload").call(entityScript, entityArgs);

View file

@ -110,7 +110,7 @@ signals:
public slots:
void addingEntity(const EntityItemID& entityID);
void deletingEntity(const EntityItemID& entityID);
void entitySciptChanging(const EntityItemID& entityID);
void entitySciptChanging(const EntityItemID& entityID, const bool reload);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
// optional slots that can be wired to menu items
@ -127,7 +127,7 @@ private:
void applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone);
void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args);
void checkAndCallPreload(const EntityItemID& entityID);
void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false);
void checkAndCallUnload(const EntityItemID& entityID);
QList<Model*> _releasedModels;
@ -148,10 +148,10 @@ private:
ScriptEngine* _entitiesScriptEngine;
ScriptEngine* _sandboxScriptEngine;
QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false);
QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false);
QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false, bool reload = false);
QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false, bool reload = false);
QScriptValue getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID);
QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url);
QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url, bool& reload);
QScriptValueList createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID);
QScriptValueList createMouseEventArgs(const EntityItemID& entityID, const MouseEvent& mouseEvent);

View file

@ -16,6 +16,9 @@
#include <DeferredLightingEffect.h>
#include <GeometryCache.h>
#include <PerfStat.h>
#include <Transform.h>
#include "RenderableTextEntityItem.h"
#include "GLMHelpers.h"
@ -37,14 +40,22 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
transformToTopLeft.postTranslate(glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
// Render background
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
// Batch render calls
Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch;
batch.setModelTransform(transformToTopLeft);
// Render background
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
//rotate about vertical to face the camera
if (getFaceCamera()) {
transformToTopLeft.postRotate(args->_viewFrustum->getOrientation());
batch.setModelTransform(transformToTopLeft);
}
DependencyManager::get<DeferredLightingEffect>()->renderQuad(batch, minCorner, maxCorner, backgroundColor);
float scale = _lineHeight / _textRenderer->getFontSize();
@ -55,6 +66,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
dimensions.y - 2.0f * topMargin);
_textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale);
}

View file

@ -54,6 +54,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
_friction(ENTITY_ITEM_DEFAULT_FRICTION),
_lifetime(ENTITY_ITEM_DEFAULT_LIFETIME),
_script(ENTITY_ITEM_DEFAULT_SCRIPT),
_scriptTimestamp(ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP),
_collisionSoundURL(ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
_registrationPoint(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT),
_angularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY),
@ -107,6 +108,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
requestedProperties += PROP_FRICTION;
requestedProperties += PROP_LIFETIME;
requestedProperties += PROP_SCRIPT;
requestedProperties += PROP_SCRIPT_TIMESTAMP;
requestedProperties += PROP_COLLISION_SOUND_URL;
requestedProperties += PROP_REGISTRATION_POINT;
requestedProperties += PROP_ANGULAR_VELOCITY;
@ -238,6 +240,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
APPEND_ENTITY_PROPERTY(PROP_FRICTION, getFriction());
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, getLifetime());
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript());
APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, getScriptTimestamp());
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getAngularVelocity());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
@ -555,6 +558,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
//READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
@ -901,6 +905,7 @@ EntityItemProperties EntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(created, getCreated);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getAngularVelocity);
@ -967,6 +972,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
// non-simulation properties below
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(scriptTimestamp, setScriptTimestamp);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);

View file

@ -276,6 +276,10 @@ public:
const QString& getScript() const { return _script; }
void setScript(const QString& value) { _script = value; }
quint64 getScriptTimestamp() const { return _scriptTimestamp; }
void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; }
const QString& getCollisionSoundURL() const { return _collisionSoundURL; }
void setCollisionSoundURL(const QString& value) { _collisionSoundURL = value; }
@ -313,7 +317,7 @@ public:
const QString& getUserData() const { return _userData; }
void setUserData(const QString& value) { _userData = value; }
QUuid getSimulatorID() const { return _simulatorID; }
void setSimulatorID(const QUuid& value);
void updateSimulatorID(const QUuid& value);
@ -412,6 +416,7 @@ protected:
float _friction;
float _lifetime;
QString _script;
quint64 _scriptTimestamp;
QString _collisionSoundURL;
glm::vec3 _registrationPoint;
glm::vec3 _angularVelocity;

View file

@ -51,6 +51,7 @@ CONSTRUCT_PROPERTY(friction, ENTITY_ITEM_DEFAULT_FRICTION),
CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME),
CONSTRUCT_PROPERTY(created, UNKNOWN_CREATED_TIME),
CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT),
CONSTRUCT_PROPERTY(scriptTimestamp, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP),
CONSTRUCT_PROPERTY(collisionSoundURL, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL),
CONSTRUCT_PROPERTY(color, ),
CONSTRUCT_PROPERTY(modelURL, ""),
@ -98,6 +99,7 @@ CONSTRUCT_PROPERTY(backgroundMode, BACKGROUND_MODE_INHERIT),
CONSTRUCT_PROPERTY(sourceUrl, ""),
CONSTRUCT_PROPERTY(lineWidth, LineEntityItem::DEFAULT_LINE_WIDTH),
CONSTRUCT_PROPERTY(linePoints, QVector<glm::vec3>()),
CONSTRUCT_PROPERTY(faceCamera, TextEntityItem::DEFAULT_FACE_CAMERA),
_id(UNKNOWN_ENTITY_ID),
@ -299,6 +301,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_FRICTION, friction);
CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime);
CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script);
CHECK_PROPERTY_CHANGE(PROP_SCRIPT_TIMESTAMP, scriptTimestamp);
CHECK_PROPERTY_CHANGE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
CHECK_PROPERTY_CHANGE(PROP_COLOR, color);
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
@ -349,6 +352,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_LINE_POINTS, linePoints);
CHECK_PROPERTY_CHANGE(PROP_HREF, href);
CHECK_PROPERTY_CHANGE(PROP_DESCRIPTION, description);
CHECK_PROPERTY_CHANGE(PROP_FACE_CAMERA, faceCamera);
changedProperties += _stage.getChangedProperties();
changedProperties += _atmosphere.getChangedProperties();
@ -391,6 +395,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(created, created.toString(Qt::ISODate));
COPY_PROPERTY_TO_QSCRIPTVALUE(script);
COPY_PROPERTY_TO_QSCRIPTVALUE(scriptTimestamp);
COPY_PROPERTY_TO_QSCRIPTVALUE(registrationPoint);
COPY_PROPERTY_TO_QSCRIPTVALUE(angularVelocity);
COPY_PROPERTY_TO_QSCRIPTVALUE(angularDamping);
@ -444,6 +449,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(linePoints);
COPY_PROPERTY_TO_QSCRIPTVALUE(href);
COPY_PROPERTY_TO_QSCRIPTVALUE(description);
COPY_PROPERTY_TO_QSCRIPTVALUE(faceCamera);
// Sitting properties support
if (!skipDefaults) {
@ -503,6 +509,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(friction, float, setFriction);
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifetime, float, setLifetime);
COPY_PROPERTY_FROM_QSCRIPTVALUE(script, QString, setScript);
COPY_PROPERTY_FROM_QSCRIPTVALUE(scriptTimestamp, quint64, setScriptTimestamp);
COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, glmVec3, setRegistrationPoint);
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
@ -555,7 +562,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(linePoints, qVectorVec3, setLinePoints);
COPY_PROPERTY_FROM_QSCRIPTVALUE(href, QString, setHref);
COPY_PROPERTY_FROM_QSCRIPTVALUE(description, QString, setDescription);
COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera);
if (!honorReadOnly) {
// this is used by the json reader to set things that we don't want javascript to able to affect.
@ -710,6 +717,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_FRICTION, properties.getFriction());
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, properties.getLifetime());
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, properties.getScript());
APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, properties.getScriptTimestamp());
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, properties.getRegistrationPoint());
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity());
@ -723,6 +731,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_HREF, properties.getHref());
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, properties.getDescription());
if (properties.getType() == EntityTypes::Web) {
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
}
@ -732,6 +741,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight());
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, properties.getTextColor());
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, properties.getBackgroundColor());
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, properties.getFaceCamera());
}
if (properties.getType() == EntityTypes::Model) {
@ -961,7 +971,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RESTITUTION, float, setRestitution);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FRICTION, float, setFriction);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFETIME, float, setLifetime);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT,QString, setScript);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT, QString, setScript);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
@ -975,6 +986,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HREF, QString, setHref);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DESCRIPTION, QString, setDescription);
if (properties.getType() == EntityTypes::Web) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
}
@ -984,6 +996,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_COLOR, xColor, setTextColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_COLOR, xColor, setBackgroundColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FACE_CAMERA, bool, setFaceCamera);
}
if (properties.getType() == EntityTypes::Model) {
@ -1099,6 +1112,7 @@ void EntityItemProperties::markAllChanged() {
_userDataChanged = true;
_simulatorIDChanged = true;
_scriptChanged = true;
_scriptTimestampChanged = true;
_collisionSoundURLChanged = true;
_registrationPointChanged = true;
_angularVelocityChanged = true;
@ -1161,7 +1175,9 @@ void EntityItemProperties::markAllChanged() {
_hrefChanged = true;
_descriptionChanged = true;
_faceCameraChanged = true;
}
/// The maximum bounding cube for the entity, independent of it's rotation.

View file

@ -98,6 +98,7 @@ public:
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float);
DEFINE_PROPERTY(PROP_CREATED, Created, created, quint64);
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString);
DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64);
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString);
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor);
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
@ -150,7 +151,8 @@ public:
DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>);
DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString);
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString);
DEFINE_PROPERTY(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool);
static QString getBackgroundModeString(BackgroundMode mode);
@ -261,6 +263,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Friction, friction, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifetime, lifetime, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ScriptTimestamp, scriptTimestamp, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionSoundURL, collisionSoundURL, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");

View file

@ -32,6 +32,7 @@ const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f;
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0;
const QString ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL = QString("");
const glm::vec3 ENTITY_ITEM_DEFAULT_REGISTRATION_POINT = ENTITY_ITEM_HALF_VEC3; // center
@ -66,6 +67,7 @@ const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f;
const bool ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS = false;
const bool ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE = false;
const bool ENTITY_ITEM_DEFAULT_BILLBOARDED = false;
const float ENTITY_ITEM_DEFAULT_CUTOFF = PI / 2;

View file

@ -92,6 +92,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { r
inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, quint32 v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, quint64 v) { return QScriptValue((qsreal)v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { return QScriptValue(v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { return xColorToScriptValue(e, v); }
@ -134,6 +135,7 @@ typedef glm::vec3 glmVec3;
typedef glm::quat glmQuat;
typedef QVector<glm::vec3> qVectorVec3;
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }

View file

@ -55,6 +55,7 @@ enum EntityPropertyList {
PROP_DAMPING,
PROP_LIFETIME,
PROP_SCRIPT,
PROP_SCRIPT_TIMESTAMP,
// these properties are supported by some derived classes
PROP_COLOR,
@ -122,6 +123,8 @@ enum EntityPropertyList {
PROP_HREF,
PROP_DESCRIPTION,
PROP_FACE_CAMERA,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties ABOVE this line
PROP_AFTER_LAST_ITEM,

View file

@ -185,6 +185,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
// else client accepts what the server says
QString entityScriptBefore = entity->getScript();
quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
QString collisionSoundURLBefore = entity->getCollisionSoundURL();
uint32_t preFlags = entity->getDirtyFlags();
UpdateEntityOperator theOperator(this, containingElement, entity, properties);
@ -206,8 +207,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
}
QString entityScriptAfter = entity->getScript();
if (entityScriptBefore != entityScriptAfter) {
emitEntityScriptChanging(entity->getEntityItemID()); // the entity script has changed
quint64 entityScriptTimestampAfter = entity->getScriptTimestamp();
bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
if (entityScriptBefore != entityScriptAfter || reload) {
emitEntityScriptChanging(entity->getEntityItemID(), reload); // the entity script has changed
}
maybeNotifyNewCollisionSoundURL(collisionSoundURLBefore, entity->getCollisionSoundURL());
}
@ -266,9 +269,10 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
return result;
}
void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) {
emit entityScriptChanging(entityItemID);
void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload) {
emit entityScriptChanging(entityItemID, reload);
}
void EntityTree::maybeNotifyNewCollisionSoundURL(const QString& previousCollisionSoundURL, const QString& nextCollisionSoundURL) {
if (!nextCollisionSoundURL.isEmpty() && (nextCollisionSoundURL != previousCollisionSoundURL)) {
emit newCollisionSoundURL(QUrl(nextCollisionSoundURL));

View file

@ -155,7 +155,7 @@ public:
void entityChanged(EntityItemPointer entity);
void emitEntityScriptChanging(const EntityItemID& entityItemID);
void emitEntityScriptChanging(const EntityItemID& entityItemID, const bool reload);
void setSimulation(EntitySimulation* simulation);
EntitySimulation* getSimulation() const { return _simulation; }
@ -171,7 +171,7 @@ public:
signals:
void deletingEntity(const EntityItemID& entityID);
void addingEntity(const EntityItemID& entityID);
void entityScriptChanging(const EntityItemID& entityItemID);
void entityScriptChanging(const EntityItemID& entityItemID, const bool reload);
void newCollisionSoundURL(const QUrl& url);
void clearingEntities();

View file

@ -733,6 +733,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
// 3) remember the old cube for the entity so we can mark it as dirty
if (entityItem) {
QString entityScriptBefore = entityItem->getScript();
quint64 entityScriptTimestampBefore = entityItem->getScriptTimestamp();
bool bestFitBefore = bestFitEntityBounds(entityItem);
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
@ -755,8 +756,10 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
}
QString entityScriptAfter = entityItem->getScript();
if (entityScriptBefore != entityScriptAfter) {
_myTree->emitEntityScriptChanging(entityItemID); // the entity script has changed
quint64 entityScriptTimestampAfter = entityItem->getScriptTimestamp();
bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
if (entityScriptBefore != entityScriptAfter || reload) {
_myTree->emitEntityScriptChanging(entityItemID, reload); // the entity script has changed
}
} else {

View file

@ -27,6 +27,7 @@ const QString TextEntityItem::DEFAULT_TEXT("");
const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f;
const xColor TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 };
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) {
return EntityItemPointer(new TextEntityItem(entityID, properties));
@ -54,6 +55,7 @@ EntityItemProperties TextEntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textColor, getTextColorX);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundColor, getBackgroundColorX);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(faceCamera, getFaceCamera);
return properties;
}
@ -65,6 +67,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textColor, setTextColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundColor, setBackgroundColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(faceCamera, setFaceCamera);
if (somethingChanged) {
bool wantDebug = false;
@ -91,7 +94,8 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight);
READ_ENTITY_PROPERTY(PROP_TEXT_COLOR, rgbColor, setTextColor);
READ_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, rgbColor, setBackgroundColor);
READ_ENTITY_PROPERTY(PROP_FACE_CAMERA, bool, setFaceCamera);
return bytesRead;
}
@ -103,6 +107,7 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_LINE_HEIGHT;
requestedProperties += PROP_TEXT_COLOR;
requestedProperties += PROP_BACKGROUND_COLOR;
requestedProperties += PROP_FACE_CAMERA;
return requestedProperties;
}
@ -120,6 +125,8 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight());
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, getTextColor());
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, getBackgroundColor());
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, getFaceCamera());
}

View file

@ -79,12 +79,17 @@ public:
_backgroundColor[GREEN_INDEX] = value.green;
_backgroundColor[BLUE_INDEX] = value.blue;
}
static const bool DEFAULT_FACE_CAMERA;
bool getFaceCamera() const { return _faceCamera; }
void setFaceCamera(bool value) { _faceCamera = value; }
protected:
QString _text;
float _lineHeight;
rgbColor _textColor;
rgbColor _backgroundColor;
bool _faceCamera;
};
#endif // hifi_TextEntityItem_h

View file

@ -73,7 +73,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketTypeEntityAdd:
case PacketTypeEntityEdit:
case PacketTypeEntityData:
return VERSION_ENTITIES_LINE_POINTS;
return VERSION_ENTITIES_SCRIPT_TIMESTAMP;
case PacketTypeEntityErase:
return 2;
case PacketTypeAudioStreamStats:

View file

@ -183,5 +183,7 @@ const PacketVersion VERSION_ENTITIES_HAVE_FRICTION = 26;
const PacketVersion VERSION_NO_ENTITY_ID_SWAP = 27;
const PacketVersion VERSION_ENTITIES_PARTICLE_FIX = 28;
const PacketVersion VERSION_ENTITIES_LINE_POINTS = 29;
const PacketVersion VERSION_ENTITIES_FACE_CAMERA = 30;
const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP = 31;
#endif // hifi_PacketHeaders_h

View file

@ -16,18 +16,22 @@
#include <QNetworkReply>
#include <QObject>
#include <assert.h>
#include <NetworkAccessManager.h>
#include <SharedUtil.h>
#include "ScriptEngineLogging.h"
#include "ScriptCache.h"
#include "ScriptEngineLogging.h"
ScriptCache::ScriptCache(QObject* parent) {
// nothing to do here...
}
QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending) {
QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending, bool reload) {
assert(!_scriptCache.contains(url) || !reload);
QString scriptContents;
if (_scriptCache.contains(url)) {
if (_scriptCache.contains(url) && !reload) {
qCDebug(scriptengine) << "Found script in cache:" << url.toString();
scriptContents = _scriptCache[url];
scriptUser->scriptContentsAvailable(url, scriptContents);
@ -43,8 +47,13 @@ QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& is
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
if (reload) {
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
qCDebug(scriptengine) << "Redownloading script at:" << url.toString();
} else {
qCDebug(scriptengine) << "Downloading script at:" << url.toString();
}
qCDebug(scriptengine) << "Downloading script at" << url.toString();
QNetworkReply* reply = networkAccessManager.get(networkRequest);
connect(reply, &QNetworkReply::finished, this, &ScriptCache::scriptDownloaded);
}
@ -52,6 +61,13 @@ QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& is
return scriptContents;
}
void ScriptCache::deleteScript(const QUrl& url) {
if (_scriptCache.contains(url)) {
qCDebug(scriptengine) << "Delete script from cache:" << url.toString();
_scriptCache.remove(url);
}
}
void ScriptCache::scriptDownloaded() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QUrl url = reply->url();

View file

@ -26,7 +26,8 @@ class ScriptCache : public QObject, public Dependency {
SINGLETON_DEPENDENCY
public:
QString getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending);
QString getScript(const QUrl& url, ScriptUser* scriptUser, bool& isPending, bool redownload = false);
void deleteScript(const QUrl& url);
void addScriptToBadScriptList(const QUrl& url) { _badScripts.insert(url); }
bool isInBadScriptList(const QUrl& url) { return _badScripts.contains(url); }

View file

@ -94,6 +94,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
_vec3Library(),
_uuidLibrary(),
_isUserLoaded(false),
_isReloading(false),
_arrayBufferClass(new ArrayBufferClass(this))
{
_allScriptsMutex.lock();
@ -251,12 +252,13 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin
return true;
}
void ScriptEngine::loadURL(const QUrl& scriptURL) {
void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
if (_isRunning) {
return;
}
_fileNameString = scriptURL.toString();
_isReloading = reload;
QUrl url(scriptURL);
@ -283,8 +285,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL) {
} else {
bool isPending;
auto scriptCache = DependencyManager::get<ScriptCache>();
scriptCache->getScript(url, this, isPending);
scriptCache->getScript(url, this, isPending, reload);
}
}
}
@ -904,7 +905,13 @@ void ScriptEngine::load(const QString& loadFile) {
}
QUrl url = resolvePath(loadFile);
emit loadScript(url.toString(), false);
if (_isReloading) {
auto scriptCache = DependencyManager::get<ScriptCache>();
scriptCache->deleteScript(url.toString());
emit reloadScript(url.toString(), false);
} else {
emit loadScript(url.toString(), false);
}
}
void ScriptEngine::nodeKilled(SharedNodePointer node) {

View file

@ -104,7 +104,7 @@ public:
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
public slots:
void loadURL(const QUrl& scriptURL);
void loadURL(const QUrl& scriptURL, bool reload);
void stop();
QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
@ -132,6 +132,7 @@ signals:
void runningStateChanged();
void evaluationFinished(QScriptValue result, bool isException);
void loadScript(const QString& scriptName, bool isUserLoaded);
void reloadScript(const QString& scriptName, bool isUserLoaded);
void doneRunning();
protected:
@ -165,6 +166,7 @@ private:
Vec3 _vec3Library;
ScriptUUID _uuidLibrary;
bool _isUserLoaded;
bool _isReloading;
ArrayBufferClass* _arrayBufferClass;