Merge branch 'master' of github.com:highfidelity/hifi into model-scripting-2

This commit is contained in:
Seth Alves 2017-03-21 13:49:19 -07:00
commit b5786befc3
15 changed files with 302 additions and 131 deletions

View file

@ -58,6 +58,8 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
DependencyManager::set<AudioScriptingInterface>();
DependencyManager::set<ResourceCacheSharedItems>();
DependencyManager::set<SoundCache>();
DependencyManager::set<AudioInjectorManager>();
@ -324,7 +326,26 @@ void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) {
void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) {
switch (killedNode->getType()) {
case NodeType::EntityServer: {
clear();
// Before we clear, make sure this was our only entity server.
// Otherwise we're assuming that we have "trading" entity servers
// (an old one going away and a new one coming onboard)
// and that we shouldn't clear here because we're still doing work.
bool hasAnotherEntityServer = false;
auto nodeList = DependencyManager::get<NodeList>();
nodeList->eachNodeBreakable([&hasAnotherEntityServer, &killedNode](const SharedNodePointer& node){
if (node->getType() == NodeType::EntityServer && node->getUUID() != killedNode->getUUID()) {
// we're talking to > 1 entity servers, we know we won't clear
hasAnotherEntityServer = true;
return false;
}
return true;
});
if (!hasAnotherEntityServer) {
clear();
}
break;
}
@ -395,7 +416,8 @@ void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) {
void EntityScriptServer::resetEntitiesScriptEngine() {
auto engineName = QString("about:Entities %1").arg(++_entitiesScriptEngineCount);
auto newEngine = QSharedPointer<ScriptEngine>(new ScriptEngine(ScriptEngine::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName));
auto newEngine = QSharedPointer<ScriptEngine>(new ScriptEngine(ScriptEngine::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName),
&ScriptEngine::deleteLater);
auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor);
newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);

View file

@ -740,23 +740,24 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
});
auto& audioScriptingInterface = AudioScriptingInterface::getInstance();
auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface>();
connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start);
connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit);
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
connect(audioIO.data(), &AudioClient::muteToggled, this, &Application::audioMuteToggled);
connect(audioIO.data(), &AudioClient::mutedByMixer, &audioScriptingInterface, &AudioScriptingInterface::mutedByMixer);
connect(audioIO.data(), &AudioClient::receivedFirstPacket, &audioScriptingInterface, &AudioScriptingInterface::receivedFirstPacket);
connect(audioIO.data(), &AudioClient::disconnected, &audioScriptingInterface, &AudioScriptingInterface::disconnected);
connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);
connect(audioIO.data(), &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket);
connect(audioIO.data(), &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected);
connect(audioIO.data(), &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) {
auto audioClient = DependencyManager::get<AudioClient>();
auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
auto myAvatarPosition = DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition();
float distance = glm::distance(myAvatarPosition, position);
bool shouldMute = !audioClient->isMuted() && (distance < radius);
if (shouldMute) {
audioClient->toggleMute();
AudioScriptingInterface::getInstance().environmentMuted();
audioScriptingInterface->environmentMuted();
}
});
@ -1181,10 +1182,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// set the local loopback interface for local sounds
AudioInjector::setLocalAudioInterface(audioIO.data());
AudioScriptingInterface::getInstance().setLocalAudioInterface(audioIO.data());
connect(audioIO.data(), &AudioClient::noiseGateOpened, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::noiseGateOpened);
connect(audioIO.data(), &AudioClient::noiseGateClosed, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::noiseGateClosed);
connect(audioIO.data(), &AudioClient::inputReceived, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::inputReceived);
audioScriptingInterface->setLocalAudioInterface(audioIO.data());
connect(audioIO.data(), &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened);
connect(audioIO.data(), &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed);
connect(audioIO.data(), &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived);
this->installEventFilter(this);
@ -1949,7 +1950,7 @@ void Application::initializeUi() {
// For some reason there is already an "Application" object in the QML context,
// though I can't find it. Hence, "ApplicationInterface"
rootContext->setContextProperty("ApplicationInterface", this);
rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance());
rootContext->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
rootContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
rootContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());

View file

@ -431,7 +431,9 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
thisFace, thisSurfaceNormal, thisExtraInfo)) {
bool isDrawInFront = thisOverlay->getDrawInFront();
if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) {
if ((bestIsFront && isDrawInFront && thisDistance < bestDistance)
|| (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) {
bestIsFront = isDrawInFront;
bestDistance = thisDistance;
result.intersects = true;

View file

@ -19,11 +19,6 @@ void registerAudioMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, soundSharedPointerToScriptValue, soundSharedPointerFromScriptValue);
}
AudioScriptingInterface& AudioScriptingInterface::getInstance() {
static AudioScriptingInterface staticInstance;
return staticInstance;
}
AudioScriptingInterface::AudioScriptingInterface() :
_localAudioInterface(NULL)
{

View file

@ -14,18 +14,20 @@
#include <AbstractAudioInterface.h>
#include <AudioInjector.h>
#include <DependencyManager.h>
#include <Sound.h>
class ScriptAudioInjector;
class AudioScriptingInterface : public QObject {
class AudioScriptingInterface : public QObject, public Dependency {
Q_OBJECT
public:
static AudioScriptingInterface& getInstance();
SINGLETON_DEPENDENCY
public:
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; }
protected:
// this method is protected to stop C++ callers from calling, but invokable from script
Q_INVOKABLE ScriptAudioInjector* playSound(SharedSoundPointer sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions());
@ -42,6 +44,7 @@ signals:
private:
AudioScriptingInterface();
AbstractAudioInterface* _localAudioInterface;
};

View file

@ -464,17 +464,17 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
void ScriptEngine::scriptErrorMessage(const QString& message) {
qCCritical(scriptengine) << qPrintable(message);
emit errorMessage(message);
emit errorMessage(message, getFilename());
}
void ScriptEngine::scriptWarningMessage(const QString& message) {
qCWarning(scriptengine) << message;
emit warningMessage(message);
emit warningMessage(message, getFilename());
}
void ScriptEngine::scriptInfoMessage(const QString& message) {
qCInfo(scriptengine) << message;
emit infoMessage(message);
emit infoMessage(message, getFilename());
}
// Even though we never pass AnimVariantMap directly to and from javascript, the queued invokeMethod of
@ -627,6 +627,9 @@ void ScriptEngine::init() {
qScriptRegisterMetaType(this, qWSCloseCodeToScriptValue, qWSCloseCodeFromScriptValue);
qScriptRegisterMetaType(this, wscReadyStateToScriptValue, wscReadyStateFromScriptValue);
// NOTE: You do not want to end up creating new instances of singletons here. They will be on the ScriptEngine thread
// and are likely to be unusable if we "reset" the ScriptEngine by creating a new one (on a whole new thread).
registerGlobalObject("Script", this);
{
@ -638,7 +641,8 @@ void ScriptEngine::init() {
resetModuleCache();
}
registerGlobalObject("Audio", &AudioScriptingInterface::getInstance());
registerGlobalObject("Audio", DependencyManager::get<AudioScriptingInterface>().data());
registerGlobalObject("Entities", entityScriptingInterface.data());
registerGlobalObject("Quat", &_quatLibrary);
registerGlobalObject("Vec3", &_vec3Library);
@ -1347,7 +1351,7 @@ QUrl ScriptEngine::resourcesPath() const {
}
void ScriptEngine::print(const QString& message) {
emit printedMessage(message);
emit printedMessage(message, getFilename());
}
// Script.require.resolve -- like resolvePath, but performs more validation and throws exceptions on invalid module identifiers (for consistency with Node.js)

View file

@ -236,10 +236,10 @@ signals:
void scriptEnding();
void finished(const QString& fileNameString, ScriptEngine* engine);
void cleanupMenuItem(const QString& menuItemString);
void printedMessage(const QString& message);
void errorMessage(const QString& message);
void warningMessage(const QString& message);
void infoMessage(const QString& message);
void printedMessage(const QString& message, const QString& scriptName);
void errorMessage(const QString& message, const QString& scriptName);
void warningMessage(const QString& message, const QString& scriptName);
void infoMessage(const QString& message, const QString& scriptName);
void runningStateChanged();
void loadScript(const QString& scriptName, bool isUserLoaded);
void reloadScript(const QString& scriptName, bool isUserLoaded);

View file

@ -34,34 +34,24 @@ ScriptsModel& getScriptsModel() {
return scriptsModel;
}
void ScriptEngines::onPrintedMessage(const QString& message) {
auto scriptEngine = qobject_cast<ScriptEngine*>(sender());
auto scriptName = scriptEngine ? scriptEngine->getFilename() : "";
void ScriptEngines::onPrintedMessage(const QString& message, const QString& scriptName) {
emit printedMessage(message, scriptName);
}
void ScriptEngines::onErrorMessage(const QString& message) {
auto scriptEngine = qobject_cast<ScriptEngine*>(sender());
auto scriptName = scriptEngine ? scriptEngine->getFilename() : "";
void ScriptEngines::onErrorMessage(const QString& message, const QString& scriptName) {
emit errorMessage(message, scriptName);
}
void ScriptEngines::onWarningMessage(const QString& message) {
auto scriptEngine = qobject_cast<ScriptEngine*>(sender());
auto scriptName = scriptEngine ? scriptEngine->getFilename() : "";
void ScriptEngines::onWarningMessage(const QString& message, const QString& scriptName) {
emit warningMessage(message, scriptName);
}
void ScriptEngines::onInfoMessage(const QString& message) {
auto scriptEngine = qobject_cast<ScriptEngine*>(sender());
auto scriptName = scriptEngine ? scriptEngine->getFilename() : "";
void ScriptEngines::onInfoMessage(const QString& message, const QString& scriptName) {
emit infoMessage(message, scriptName);
}
void ScriptEngines::onErrorLoadingScript(const QString& url) {
auto scriptEngine = qobject_cast<ScriptEngine*>(sender());
auto scriptName = scriptEngine ? scriptEngine->getFilename() : "";
emit errorLoadingScript(url, scriptName);
emit errorLoadingScript(url);
}
ScriptEngines::ScriptEngines(ScriptEngine::Context context)

View file

@ -79,13 +79,13 @@ signals:
void errorMessage(const QString& message, const QString& engineName);
void warningMessage(const QString& message, const QString& engineName);
void infoMessage(const QString& message, const QString& engineName);
void errorLoadingScript(const QString& url, const QString& engineName);
void errorLoadingScript(const QString& url);
public slots:
void onPrintedMessage(const QString& message);
void onErrorMessage(const QString& message);
void onWarningMessage(const QString& message);
void onInfoMessage(const QString& message);
void onPrintedMessage(const QString& message, const QString& scriptName);
void onErrorMessage(const QString& message, const QString& scriptName);
void onWarningMessage(const QString& message, const QString& scriptName);
void onInfoMessage(const QString& message, const QString& scriptName);
void onErrorLoadingScript(const QString& url);
protected slots:

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path d="M331.8,283.4c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C342.1,306.6,331.8,296.2,331.8,283.4z"/>
<path d="M277.8,350.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C288.1,374.2,277.8,363.8,277.8,350.9z"/>
<path d="M216.3,368.8c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C226.7,392,216.3,381.6,216.3,368.8z"/>
<path d="M169.9,308.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C180.3,332.1,169.9,321.7,169.9,308.9z"/>
<path d="M251.2,447.4c-4.9-3.6-8.3-9.1-9.2-15.3c-0.9-6,0.6-12.3,4.2-17.2c3.6-4.9,9.1-8.3,15.2-9.1c6-0.9,12.3,0.6,17.3,4.3
c4.9,3.6,8.3,9.1,9.1,15.2c0.9,6-0.6,12.3-4.2,17.2s-9.1,8.3-15.2,9.1C262.4,452.6,256.1,451,251.2,447.4z"/>
<path d="M67.6,246.1c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C78,269.3,67.6,258.8,67.6,246.1z"/>
<path d="M178.8,199.5c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C189.1,222.7,178.8,212.2,178.8,199.5z"/>
<path d="M250.3,293.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C260.7,317.1,250.3,306.6,250.3,293.9z"/>
<path d="M413,242.1c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C423.5,265.3,413,255,413,242.1z"/>
<path d="M302.1,203.7c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C312.6,226.9,302.1,216.5,302.1,203.7z"/>
<path d="M132.3,113.5c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C142.8,136.6,132.3,126.2,132.3,113.5z"/>
<path d="M366.6,136.7c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
C377.1,159.9,366.6,149.5,366.6,136.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 960 560" style="enable-background:new 0 0 960 560;" xml:space="preserve">
<g>
<g>
<path style="fill:#333333;" d="M478.879,127.676c-83.872,0-152.325,68.454-152.325,152.325s68.454,152.325,152.325,152.325
s152.325-67.837,152.325-152.325C631.204,196.13,563.366,127.676,478.879,127.676z"/>
<path style="fill:#FFFFFF;" d="M478.881,437.281C392.156,437.281,321.6,366.725,321.6,280s70.557-157.281,157.281-157.281
S636.157,193.275,636.157,280S565.606,437.281,478.881,437.281z M478.881,132.627c-81.263,0-147.373,66.115-147.373,147.373
s66.11,147.373,147.373,147.373c81.258,0,147.368-66.115,147.368-147.373S560.138,132.627,478.881,132.627z"/>
</g>
<g>
<rect x="459.145" y="4.952" style="fill:#333333;" width="40.086" height="75.237"/>
<path style="fill:#FFFFFF;" d="M504.183,85.147h-49.99V0h49.99V85.147z M464.1,75.239h30.174V9.908H464.1V75.239z"/>
</g>
<g>
<rect x="272.766" y="90.696" transform="matrix(-0.707 -0.7072 0.7072 -0.707 451.5123 408.5368)" style="fill:#333333;" width="75.236" height="40.085"/>
<path style="fill:#FFFFFF;" d="M322.809,158.519l-60.198-60.212l35.351-35.346l60.198,60.212L322.809,158.519z M276.621,98.307
l46.188,46.202l21.34-21.335l-46.188-46.202L276.621,98.307z"/>
</g>
<g>
<rect x="201.98" y="257.8" style="fill:#333333;" width="75.237" height="40.086"/>
<path style="fill:#FFFFFF;" d="M282.17,302.845h-85.142V252.85h85.142V302.845z M206.936,292.937h65.327v-30.179h-65.327V292.937z
"/>
</g>
<g>
<rect x="287.46" y="408.97" transform="matrix(0.7072 0.707 -0.707 0.7072 405.7749 -86.6482)" style="fill:#333333;" width="40.085" height="75.236"/>
<path style="fill:#FFFFFF;" d="M295.083,494.359l-35.355-35.346l60.198-60.212l35.355,35.346L295.083,494.359z M273.738,459.013
l21.345,21.335l46.187-46.202l-21.345-21.335L273.738,459.013z"/>
</g>
<g>
<rect x="454.827" y="479.812" style="fill:#333333;" width="40.086" height="75.237"/>
<path style="fill:#FFFFFF;" d="M499.868,560h-49.995v-85.137h49.995V560z M459.781,550.091h30.179V484.77h-30.179V550.091z"/>
</g>
<g>
<rect x="606.017" y="429.505" transform="matrix(0.707 0.7072 -0.7072 0.707 506.5034 -323.4691)" style="fill:#333333;" width="75.236" height="40.085"/>
<path style="fill:#FFFFFF;" d="M656.06,497.32l-60.198-60.212l35.351-35.346l60.198,60.212L656.06,497.32z M609.872,437.107
l46.187,46.202l21.34-21.335l-46.188-46.202L609.872,437.107z"/>
</g>
<g>
<rect x="676.839" y="262.117" style="fill:#333333;" width="75.237" height="40.086"/>
<path style="fill:#FFFFFF;" d="M757.032,307.16h-85.147v-49.995h85.147V307.16z M681.792,297.252h65.332v-30.179h-65.332V297.252z
"/>
</g>
<g>
<rect x="626.205" y="75.756" transform="matrix(-0.7072 -0.707 0.707 -0.7072 1023.1211 650.4535)" style="fill:#333333;" width="40.085" height="75.236"/>
<path style="fill:#FFFFFF;" d="M633.825,161.161l-35.351-35.346l60.198-60.212l35.351,35.346L633.825,161.161z M612.485,125.815
l21.34,21.335l46.188-46.202l-21.34-21.335L612.485,125.815z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="3.44 0 735.338 557.9" style="enable-background:new 3.44 0 735.338 557.9;" xml:space="preserve">
<g>
<g>
<rect x="503.95" y="260.767" style="fill:#333333;" width="227.728" height="36.376"/>
<path style="fill:#FFFFFF;" d="M738.778,304.24H496.854v-50.566h241.924V304.24z M511.052,290.042H724.58v-22.17H511.052V290.042z
"/>
</g>
<g>
<g>
<g>
<rect x="426.085" y="465.518" transform="matrix(-0.9213 -0.3888 0.3888 -0.9213 849.3369 1139.2869)" style="fill:#333333;" width="227.719" height="36.374"/>
<path style="fill:#FFFFFF;" d="M641.55,554.032l-222.88-94.06l19.668-46.6l222.88,94.06L641.55,554.032z M437.277,452.401
l196.717,83.024l8.617-20.423l-196.717-83.024L437.277,452.401z"/>
</g>
<g>
<rect x="426.295" y="56.081" transform="matrix(0.9213 -0.3888 0.3888 0.9213 13.624 215.8596)" style="fill:#333333;" width="227.719" height="36.374"/>
<path style="fill:#FFFFFF;" d="M438.545,144.598l-19.668-46.6l222.887-94.06l19.667,46.6L438.545,144.598z M437.484,105.568
l8.617,20.423l196.724-83.024l-8.617-20.423L437.484,105.568z"/>
</g>
</g>
<g>
<path style="fill:#333333;" d="M430.774,280.311c0-50.839-32.955-93.895-78.642-109.198V13.262L124.404,165.081H10.54v227.728
h113.864l227.728,151.819V389.51C397.818,374.206,430.774,331.151,430.774,280.311z"/>
<path style="fill:#FFFFFF;" d="M359.23,557.9L122.257,399.908H3.44V157.978h118.816L359.23,0v166.117
c47.245,18.038,78.642,63.308,78.642,114.192s-31.397,96.154-78.642,114.192V557.9z M17.638,385.711h108.917l218.478,145.652
V384.407l4.846-1.622c44.139-14.794,73.796-55.973,73.796-102.476s-29.657-87.682-73.796-102.476l-4.846-1.622V26.538
L126.555,172.176H17.638V385.711z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -33,13 +33,27 @@ Script.include([
"libraries/gridTool.js",
"libraries/entityList.js",
"particle_explorer/particleExplorerTool.js",
"libraries/lightOverlayManager.js"
"libraries/entityIconOverlayManager.js"
]);
var selectionDisplay = SelectionDisplay;
var selectionManager = SelectionManager;
var lightOverlayManager = new LightOverlayManager();
const PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg");
const POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg");
const SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg");
entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) {
var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']);
if (properties.type === 'Light') {
return {
url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL,
}
} else {
return {
url: PARTICLE_SYSTEM_URL,
}
}
});
var cameraManager = new CameraManager();
@ -53,7 +67,45 @@ var entityListTool = new EntityListTool();
selectionManager.addEventListener(function () {
selectionDisplay.updateHandles();
lightOverlayManager.updatePositions();
entityIconOverlayManager.updatePositions();
// Update particle explorer
var needToDestroyParticleExplorer = false;
if (selectionManager.selections.length === 1) {
var selectedEntityID = selectionManager.selections[0];
if (selectedEntityID === selectedParticleEntityID) {
return;
}
var type = Entities.getEntityProperties(selectedEntityID, "type").type;
if (type === "ParticleEffect") {
// Destroy the old particles web view first
particleExplorerTool.destroyWebView();
particleExplorerTool.createWebView();
var properties = Entities.getEntityProperties(selectedEntityID);
var particleData = {
messageType: "particle_settings",
currentProperties: properties
};
selectedParticleEntityID = selectedEntityID;
particleExplorerTool.setActiveParticleEntity(selectedParticleEntityID);
particleExplorerTool.webView.webEventReceived.connect(function (data) {
data = JSON.parse(data);
if (data.messageType === "page_loaded") {
particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData));
}
});
} else {
needToDestroyParticleExplorer = true;
}
} else {
needToDestroyParticleExplorer = true;
}
if (needToDestroyParticleExplorer && selectedParticleEntityID !== null) {
selectedParticleEntityID = null;
particleExplorerTool.destroyWebView();
}
});
const KEY_P = 80; //Key code for letter p used for Parenting hotkey.
@ -82,13 +134,13 @@ var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode";
var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Edit Mode";
var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Edit Mode";
var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled";
var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect";
var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode";
var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode";
var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode";
@ -506,7 +558,7 @@ var toolBar = (function () {
toolBar.writeProperty("shown", false);
toolBar.writeProperty("shown", true);
}
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
};
@ -571,8 +623,8 @@ function findClickedEntity(event) {
}
var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking
var lightResult = lightOverlayManager.findRayIntersection(pickRay);
lightResult.accurate = true;
var iconResult = entityIconOverlayManager.findRayIntersection(pickRay);
iconResult.accurate = true;
if (pickZones) {
Entities.setZonesArePickable(false);
@ -580,18 +632,12 @@ function findClickedEntity(event) {
var result;
if (!entityResult.intersects && !lightResult.intersects) {
return null;
} else if (entityResult.intersects && !lightResult.intersects) {
if (iconResult.intersects) {
result = iconResult;
} else if (entityResult.intersects) {
result = entityResult;
} else if (!entityResult.intersects && lightResult.intersects) {
result = lightResult;
} else {
if (entityResult.distance < lightResult.distance) {
result = entityResult;
} else {
result = lightResult;
}
return null;
}
if (!result.accurate) {
@ -945,18 +991,18 @@ function setupModelMenus() {
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE,
afterItem: MENU_EASE_ON_FOCUS,
isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) === "true",
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE,
isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) === "true",
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false",
grouping: "Advanced"
});
@ -987,7 +1033,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE);
Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE);
}
@ -995,7 +1041,7 @@ Script.scriptEnding.connect(function () {
toolBar.setActive(false);
Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT));
Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
Settings.setValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
progressDialog.cleanup();
@ -1184,7 +1230,7 @@ function parentSelectedEntities() {
}
function deleteSelectedEntities() {
if (SelectionManager.hasSelection()) {
selectedParticleEntity = 0;
selectedParticleEntityID = null;
particleExplorerTool.destroyWebView();
SelectionManager.saveProperties();
var savedProperties = [];
@ -1283,8 +1329,8 @@ function handeMenuEvent(menuItem) {
selectAllEtitiesInCurrentSelectionBox(false);
} else if (menuItem === "Select All Entities Touching Box") {
selectAllEtitiesInCurrentSelectionBox(true);
} else if (menuItem === MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
} else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) {
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
} else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
}
@ -1959,43 +2005,13 @@ var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
var propertiesTool = new PropertiesTool();
var particleExplorerTool = new ParticleExplorerTool();
var selectedParticleEntity = 0;
var selectedParticleEntityID = null;
entityListTool.webView.webEventReceived.connect(function (data) {
data = JSON.parse(data);
if(data.type === 'parent') {
if (data.type === 'parent') {
parentSelectedEntities();
} else if(data.type === 'unparent') {
unparentSelectedEntities();
} else if (data.type === "selectionUpdate") {
var ids = data.entityIds;
if (ids.length === 1) {
if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") {
if (JSON.stringify(selectedParticleEntity) === JSON.stringify(ids[0])) {
// This particle entity is already selected, so return
return;
}
// Destroy the old particles web view first
particleExplorerTool.destroyWebView();
particleExplorerTool.createWebView();
var properties = Entities.getEntityProperties(ids[0]);
var particleData = {
messageType: "particle_settings",
currentProperties: properties
};
selectedParticleEntity = ids[0];
particleExplorerTool.setActiveParticleEntity(ids[0]);
particleExplorerTool.webView.webEventReceived.connect(function (data) {
data = JSON.parse(data);
if (data.messageType === "page_loaded") {
particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData));
}
});
} else {
selectedParticleEntity = 0;
particleExplorerTool.destroyWebView();
}
}
}
});

View file

@ -1,9 +1,6 @@
var POINT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/point-light.svg";
var SPOT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/spot-light.svg";
LightOverlayManager = function() {
var self = this;
/* globals EntityIconOverlayManager:true */
EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
var visible = false;
// List of all created overlays
@ -22,9 +19,16 @@ LightOverlayManager = function() {
for (var id in entityIDs) {
var entityID = entityIDs[id];
var properties = Entities.getEntityProperties(entityID);
Overlays.editOverlay(entityOverlays[entityID], {
var overlayProperties = {
position: properties.position
});
};
if (getOverlayPropertiesFunc) {
var customProperties = getOverlayPropertiesFunc(entityID, properties);
for (var key in customProperties) {
overlayProperties[key] = customProperties[key];
}
}
Overlays.editOverlay(entityOverlays[entityID], overlayProperties);
}
};
@ -34,7 +38,7 @@ LightOverlayManager = function() {
if (result.intersects) {
for (var id in entityOverlays) {
if (result.overlayID == entityOverlays[id]) {
if (result.overlayID === entityOverlays[id]) {
result.entityID = entityIDs[id];
found = true;
break;
@ -50,7 +54,7 @@ LightOverlayManager = function() {
};
this.setVisible = function(isVisible) {
if (visible != isVisible) {
if (visible !== isVisible) {
visible = isVisible;
for (var id in entityOverlays) {
Overlays.editOverlay(entityOverlays[id], {
@ -62,12 +66,13 @@ LightOverlayManager = function() {
// Allocate or get an unused overlay
function getOverlay() {
if (unusedOverlays.length == 0) {
var overlay = Overlays.addOverlay("image3d", {});
var overlay;
if (unusedOverlays.length === 0) {
overlay = Overlays.addOverlay("image3d", {});
allOverlays.push(overlay);
} else {
var overlay = unusedOverlays.pop();
};
overlay = unusedOverlays.pop();
}
return overlay;
}
@ -79,24 +84,32 @@ LightOverlayManager = function() {
}
function addEntity(entityID) {
var properties = Entities.getEntityProperties(entityID);
if (properties.type == "Light" && !(entityID in entityOverlays)) {
var properties = Entities.getEntityProperties(entityID, ['position', 'type']);
if (entityTypes.indexOf(properties.type) > -1 && !(entityID in entityOverlays)) {
var overlay = getOverlay();
entityOverlays[entityID] = overlay;
entityIDs[entityID] = entityID;
Overlays.editOverlay(overlay, {
var overlayProperties = {
position: properties.position,
url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL,
rotation: Quat.fromPitchYawRollDegrees(0, 0, 270),
visible: visible,
alpha: 0.9,
scale: 0.5,
drawInFront: true,
isFacingAvatar: true,
color: {
red: 255,
green: 255,
blue: 255
}
});
};
if (getOverlayPropertiesFunc) {
var customProperties = getOverlayPropertiesFunc(entityID, properties);
for (var key in customProperties) {
overlayProperties[key] = customProperties[key];
}
}
Overlays.editOverlay(overlay, overlayProperties);
}
}
@ -130,4 +143,4 @@ LightOverlayManager = function() {
Overlays.deleteOverlay(allOverlays[i]);
}
});
};
};

View file

@ -1032,10 +1032,12 @@ SelectionDisplay = (function() {
var pickRay = controllerComputePickRay();
if (pickRay) {
var entityIntersection = Entities.findRayIntersection(pickRay, true);
var iconIntersection = entityIconOverlayManager.findRayIntersection(pickRay);
var overlayIntersection = Overlays.findRayIntersection(pickRay);
if (entityIntersection.intersects &&
if (iconIntersection.intersects) {
selectionManager.setSelections([iconIntersection.entityID]);
} else if (entityIntersection.intersects &&
(!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) {
if (HMD.tabletID === entityIntersection.entityID) {