diff --git a/BUILD.md b/BUILD.md index 6613786903..c86e34823c 100644 --- a/BUILD.md +++ b/BUILD.md @@ -6,6 +6,7 @@ * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 +* [Bullet Physics Engine](http://bulletphysics.org) ~> 2.82 ### OS Specific Build Guides * [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X. @@ -59,5 +60,5 @@ OS X users who tap our [homebrew formulas repository](https://github.com/highfid ####Devices -You can support external input/output devices such as Leap Motion, Faceplus, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. +You can support external input/output devices such as Leap Motion, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a6118bb87..367fb88a26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,10 @@ if (POLICY CMP0043) cmake_policy(SET CMP0043 OLD) endif () +if (POLICY CMP0042) + cmake_policy(SET CMP0042 OLD) +endif () + project(hifi) add_definitions(-DGLM_FORCE_RADIANS) @@ -34,17 +38,19 @@ elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-strict-aliasing") endif(WIN32) -include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +if (NOT MSVC12) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) -if (COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -elseif(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") -else() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") -endif() + if (COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else() + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + endif() +endif () if (APPLE) set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x") diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 6e31182f0d..b56eea5c90 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -6,7 +6,7 @@ include_glm() # link in the shared libraries link_hifi_libraries( - audio avatars octree voxels fbx entities metavoxels + audio avatars octree environment gpu model fbx entities metavoxels networking animation shared script-engine embedded-webserver physics ) @@ -15,4 +15,4 @@ if (UNIX) target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) endif (UNIX) -link_shared_dependencies() +include_dependency_includes() diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f3efccf31a..eab67818c4 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -25,7 +24,6 @@ #include #include #include -#include #include // TODO: consider moving to scriptengine.h @@ -37,9 +35,8 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; Agent::Agent(const QByteArray& packet) : ThreadedAssignment(packet), - _voxelEditSender(), _entityEditSender(), - _receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, + _receivedAudioStream(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, InboundAudioStream::Settings(0, false, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, false, DEFAULT_WINDOW_STARVE_THRESHOLD, DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES, DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION, false)), @@ -48,14 +45,13 @@ Agent::Agent(const QByteArray& packet) : // be the parent of the script engine so it gets moved when we do _scriptEngine.setParent(this); - _scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); _scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender); } void Agent::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { @@ -69,11 +65,6 @@ void Agent::readPendingDatagrams() { if (matchedNode) { // PacketType_JURISDICTION, first byte is the node type... switch (receivedPacket[headerBytes]) { - case NodeType::VoxelServer: - _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()-> - queueReceivedPacket(matchedNode,receivedPacket); - break; - break; case NodeType::EntityServer: _scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()-> queueReceivedPacket(matchedNode, receivedPacket); @@ -93,7 +84,6 @@ void Agent::readPendingDatagrams() { sourceNode->setLastHeardMicrostamp(usecTimestampNow()); } else if (datagramPacketType == PacketTypeOctreeStats - || datagramPacketType == PacketTypeVoxelData || datagramPacketType == PacketTypeEntityData || datagramPacketType == PacketTypeEntityErase ) { @@ -113,7 +103,7 @@ void Agent::readPendingDatagrams() { // TODO: this needs to be fixed, the goal is to test the packet version for the piggyback, but // this is testing the version and hash of the original packet // need to use numBytesArithmeticCodingFromBuffer()... - if (!NodeList::getInstance()->packetVersionAndHashMatch(receivedPacket)) { + if (!DependencyManager::get()->packetVersionAndHashMatch(receivedPacket)) { return; // bail since piggyback data doesn't match our versioning } } else { @@ -127,10 +117,6 @@ void Agent::readPendingDatagrams() { _entityViewer.processDatagram(mutablePacket, sourceNode); } - if (datagramPacketType == PacketTypeVoxelData) { - _voxelViewer.processDatagram(mutablePacket, sourceNode); - } - } else if (datagramPacketType == PacketTypeMixedAudio || datagramPacketType == PacketTypeSilentAudioFrame) { _receivedAudioStream.parseData(receivedPacket); @@ -141,7 +127,7 @@ void Agent::readPendingDatagrams() { // let this continue through to the NodeList so it updates last heard timestamp // for the sending audio mixer - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } else if (datagramPacketType == PacketTypeBulkAvatarData || datagramPacketType == PacketTypeAvatarIdentity || datagramPacketType == PacketTypeAvatarBillboard @@ -151,9 +137,9 @@ void Agent::readPendingDatagrams() { // let this continue through to the NodeList so it updates last heard timestamp // for the sending avatar-mixer - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } else { - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } } } @@ -164,11 +150,10 @@ const QString AGENT_LOGGING_NAME = "agent"; void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::VoxelServer << NodeType::EntityServer ); @@ -176,7 +161,7 @@ void Agent::run() { QUrl scriptURL; if (_payload.isEmpty()) { scriptURL = QUrl(QString("http://%1:%2/assignment/%3") - .arg(NodeList::getInstance()->getDomainHandler().getIP().toString()) + .arg(DependencyManager::get()->getDomainHandler().getIP().toString()) .arg(DOMAIN_SERVER_HTTP_PORT) .arg(uuidStringWithoutCurlyBraces(_uuid))); } else { @@ -199,6 +184,7 @@ void Agent::run() { loop.exec(); QString scriptContents(reply->readAll()); + delete reply; qDebug() << "Downloaded script:" << scriptContents; @@ -221,12 +207,6 @@ void Agent::run() { _scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance()); - _scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer); - // connect the VoxelViewer and the VoxelScriptingInterface to each other - _voxelViewer.setJurisdictionListener(_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()); - _voxelViewer.init(); - _scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree()); - _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); _entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()); _entityViewer.init(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 28af2a392d..ffae3c6c21 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include "MixedAudioStream.h" @@ -60,10 +58,7 @@ public slots: private: ScriptEngine _scriptEngine; - VoxelEditPacketSender _voxelEditSender; EntityEditPacketSender _entityEditSender; - - VoxelTreeHeadlessViewer _voxelViewer; EntityTreeHeadlessViewer _entityViewer; MixedAudioStream _receivedAudioStream; diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 386d6e8a1d..7a5ad26726 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,12 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : setOrganizationDomain("highfidelity.io"); setApplicationName("assignment-client"); QSettings::setDefaultFormat(QSettings::IniFormat); - + + // create a NodeList as an unassigned client + DependencyManager::registerInheritance(); + auto addressManager = DependencyManager::set(); + auto nodeList = DependencyManager::set(NodeType::Unassigned); + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 installNativeEventFilter(&ShutdownEventListener::getInstance()); @@ -91,9 +97,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } - - // create a NodeList as an unassigned client - NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned); quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; @@ -136,7 +139,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : void AssignmentClient::sendAssignmentRequest() { if (!_currentAssignment) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted @@ -173,7 +176,7 @@ void AssignmentClient::sendAssignmentRequest() { } void AssignmentClient::readPendingDatagrams() { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); QByteArray receivedPacket; HifiSockAddr senderSockAddr; @@ -260,7 +263,7 @@ void AssignmentClient::assignmentCompleted() { qDebug("Assignment finished or never started - waiting for new assignment."); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // have us handle incoming NodeList datagrams again disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment.data(), 0); diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 63c87313fe..78e905edfa 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -17,7 +17,6 @@ #include "avatars/AvatarMixer.h" #include "metavoxels/MetavoxelServer.h" #include "entities/EntityServer.h" -#include "voxels/VoxelServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { QDataStream packetStream(packet); @@ -35,8 +34,6 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet return new AvatarMixer(packet); case Assignment::AgentType: return new Agent(packet); - case Assignment::VoxelServerType: - return new VoxelServer(packet); case Assignment::MetavoxelServerType: return new MetavoxelServer(packet); case Assignment::EntityServerType: diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index e8ff072cc7..b7dfdd9b24 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -60,7 +60,7 @@ #include "AudioMixer.h" const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f; -const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.18; +const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.18f; const float DEFAULT_NOISE_MUTING_THRESHOLD = 0.003f; const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer"; const QString AUDIO_ENV_GROUP_KEY = "audio_env"; @@ -273,8 +273,8 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l // Mono input to stereo output (item 1 above) int OUTPUT_SAMPLES_PER_INPUT_SAMPLE = 2; - int inputSampleCount = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / OUTPUT_SAMPLES_PER_INPUT_SAMPLE; - int maxOutputIndex = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; + int inputSampleCount = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO / OUTPUT_SAMPLES_PER_INPUT_SAMPLE; + int maxOutputIndex = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; // attenuation and fade applied to all samples (item 2 above) float attenuationAndFade = attenuationCoefficient * repeatedFrameFadeFactor; @@ -352,9 +352,10 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l float attenuationAndFade = attenuationCoefficient * repeatedFrameFadeFactor; - for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s++) { + for (int s = 0; s < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; s++) { _preMixSamples[s] = glm::clamp(_preMixSamples[s] + (int)(streamPopOutput[s / stereoDivider] * attenuationAndFade), - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); + AudioConstants::MIN_SAMPLE_VALUE, + AudioConstants::MAX_SAMPLE_VALUE); } } @@ -416,14 +417,15 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l AudioFilterHSF1s& penumbraFilter = listenerNodeData->getListenerSourcePairData(streamUUID)->getPenumbraFilter(); // set the gain on both filter channels - penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope); - penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope); - penumbraFilter.render(_preMixSamples, _preMixSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2); + penumbraFilter.setParameters(0, 0, AudioConstants::SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope); + penumbraFilter.setParameters(0, 1, AudioConstants::SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope); + penumbraFilter.render(_preMixSamples, _preMixSamples, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO / 2); } // Actually mix the _preMixSamples into the _mixSamples here. - for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s++) { - _mixSamples[s] = glm::clamp(_mixSamples[s] + _preMixSamples[s], MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); + for (int s = 0; s < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; s++) { + _mixSamples[s] = glm::clamp(_mixSamples[s] + _preMixSamples[s], AudioConstants::MIN_SAMPLE_VALUE, + AudioConstants::MAX_SAMPLE_VALUE); } return 1; @@ -440,7 +442,7 @@ int AudioMixer::prepareMixForListeningNode(Node* node) { // loop through all other nodes that have sufficient audio to mix int streamsMixed = 0; - NodeList::getInstance()->eachNode([&](const SharedNodePointer& otherNode){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& otherNode){ if (otherNode->getLinkedData()) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); @@ -520,12 +522,12 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) { memcpy(envDataAt, &wetLevel, sizeof(float)); envDataAt += sizeof(float); } - NodeList::getInstance()->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); + DependencyManager::get()->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); } } void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { // pull any new audio data from nodes off of the network stack @@ -606,7 +608,7 @@ void AudioMixer::sendStatsPacket() { somethingToSend = true; sizeOfStats += property.size() + value.size(); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); int clientNumber = 0; @@ -639,7 +641,7 @@ void AudioMixer::run() { ThreadedAssignment::commonInit(AUDIO_MIXER_LOGGING_TARGET_NAME, NodeType::AudioMixer); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // we do not want this event loop to be the handler for UDP datagrams, so disconnect disconnect(&nodeList->getNodeSocket(), 0, this, 0); @@ -702,7 +704,7 @@ void AudioMixer::run() { char clientMixBuffer[MAX_PACKET_SIZE]; - int usecToSleep = BUFFER_SEND_INTERVAL_USECS; + int usecToSleep = AudioConstants::NETWORK_FRAME_USECS; const int TRAILING_AVERAGE_FRAMES = 100; int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; @@ -721,7 +723,7 @@ void AudioMixer::run() { } _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) - + (usecToSleep * CURRENT_FRAME_RATIO / (float) BUFFER_SEND_INTERVAL_USECS); + + (usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); float lastCutoffRatio = _performanceThrottlingRatio; bool hasRatioChanged = false; @@ -800,8 +802,8 @@ void AudioMixer::run() { mixDataAt += sizeof(quint16); // pack mixed audio samples - memcpy(mixDataAt, _mixSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); - mixDataAt += NETWORK_BUFFER_LENGTH_BYTES_STEREO; + memcpy(mixDataAt, _mixSamples, AudioConstants::NETWORK_FRAME_BYTES_STEREO); + mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO; } else { // pack header int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); @@ -813,7 +815,7 @@ void AudioMixer::run() { mixDataAt += sizeof(quint16); // pack number of silent audio samples - quint16 numSilentSamples = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; + quint16 numSilentSamples = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; memcpy(mixDataAt, &numSilentSamples, sizeof(quint16)); mixDataAt += sizeof(quint16); } @@ -844,7 +846,7 @@ void AudioMixer::run() { break; } - usecToSleep = (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - timer.nsecsElapsed() / 1000; // ns to us + usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us if (usecToSleep > 0) { usleep(usecToSleep); @@ -892,7 +894,7 @@ void AudioMixer::perSecondActions() { _timeSpentPerHashMatchCallStats.getWindowSum() / WINDOW_LENGTH_USECS * 100.0, _timeSpentPerHashMatchCallStats.getCurrentIntervalSum() / USECS_PER_SECOND * 100.0); - NodeList::getInstance()->eachNode([](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([](const SharedNodePointer& node) { if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index cc88e368b2..6cee557ff9 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -55,11 +55,11 @@ private: // used on a per stream basis to run the filter on before mixing, large enough to handle the historical // data from a phase delay as well as an entire network buffer - int16_t _preMixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; + int16_t _preMixSamples[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; // client samples capacity is larger than what will be sent to optimize mixing // we are MMX adding 4 samples at a time so we need client samples to have an extra 4 - int16_t _mixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; + int16_t _mixSamples[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; void perSecondActions(); diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 26178eb2af..61f9e544e4 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -147,7 +147,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& removeDeadInjectedStreams(); char packet[MAX_PACKET_SIZE]; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // The append flag is a boolean value that will be packed right after the header. The first packet sent // inside this method will have 0 for this flag, while every subsequent packet will have 1 for this flag. diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index ce43229286..322c7057da 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -24,7 +24,7 @@ class PerListenerSourcePairData { public: PerListenerSourcePairData() { - _penumbraFilter.initialize(SAMPLE_RATE, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2); + _penumbraFilter.initialize(AudioConstants::SAMPLE_RATE, AudioConstants::NETWORK_FRAME_SAMPLES_STEREO / 2); }; AudioFilterHSF1s& getPenumbraFilter() { return _penumbraFilter; } diff --git a/assignment-client/src/audio/AvatarAudioStream.cpp b/assignment-client/src/audio/AvatarAudioStream.cpp index 90dcefa09d..87581a637c 100644 --- a/assignment-client/src/audio/AvatarAudioStream.cpp +++ b/assignment-client/src/audio/AvatarAudioStream.cpp @@ -40,7 +40,9 @@ int AvatarAudioStream::parseStreamProperties(PacketType type, const QByteArray& // if isStereo value has changed, restart the ring buffer with new frame size if (isStereo != _isStereo) { - _ringBuffer.resizeForFrameSize(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _ringBuffer.resizeForFrameSize(isStereo + ? AudioConstants::NETWORK_FRAME_SAMPLES_STEREO + : AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); _isStereo = isStereo; } diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 671fb17bc8..9616c8cb21 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -41,7 +41,7 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) : _sumIdentityPackets(0) { // make sure we hear about node kills so we can tell the other nodes - connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); + connect(DependencyManager::get().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); } AvatarMixer::~AvatarMixer() { @@ -117,7 +117,7 @@ void AvatarMixer::broadcastAvatarData() { int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); AvatarMixerClientData* nodeData = NULL; AvatarMixerClientData* otherNodeData = NULL; @@ -222,7 +222,7 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); killPacket += killedNode->getUUID().toRfc4122(); - NodeList::getInstance()->broadcastToNodes(killPacket, + DependencyManager::get()->broadcastToNodes(killPacket, NodeSet() << NodeType::Agent); } } @@ -231,7 +231,7 @@ void AvatarMixer::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { @@ -309,7 +309,7 @@ void AvatarMixer::sendStatsPacket() { void AvatarMixer::run() { ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); nodeList->linkedDataCreateCallback = attachAvatarDataToNode; diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index af450782a2..d882ea19ac 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -76,7 +76,7 @@ void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePo copyAt += sizeof(entityID); packetLength += sizeof(entityID); - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, senderNode); + DependencyManager::get()->writeDatagram((char*) outputBuffer, packetLength, senderNode); } @@ -114,7 +114,8 @@ int EntityServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNo hasMoreToSend = tree->encodeEntitiesDeletedSince(queryNode->getSequenceNumber(), deletedEntitiesSentAt, outputBuffer, MAX_PACKET_SIZE, packetLength); - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); + DependencyManager::get()->writeDatagram((char*) outputBuffer, packetLength, + SharedNodePointer(node)); queryNode->packetSent(outputBuffer, packetLength); packetsSent++; } @@ -132,7 +133,7 @@ void EntityServer::pruneDeletedEntities() { quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future - NodeList::getInstance()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) { if (node->getLinkedData()) { EntityNodeData* nodeData = static_cast(node->getLinkedData()); quint64 nodeLastDeletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 89b3102391..43c24f218d 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -60,11 +60,11 @@ const QString METAVOXEL_SERVER_LOGGING_NAME = "metavoxel-server"; void MetavoxelServer::run() { commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); - connect(nodeList, &NodeList::nodeAdded, this, &MetavoxelServer::maybeAttachSession); - connect(nodeList, &NodeList::nodeKilled, this, &MetavoxelServer::maybeDeleteSession); + connect(nodeList.data(), &NodeList::nodeAdded, this, &MetavoxelServer::maybeAttachSession); + connect(nodeList.data(), &NodeList::nodeKilled, this, &MetavoxelServer::maybeDeleteSession); // initialize Bitstream before using it in multiple threads Bitstream::preThreadingInit(); @@ -101,7 +101,7 @@ void MetavoxelServer::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index e880615b71..8a560984a6 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -148,7 +148,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin qDebug() << " --- inside while loop ---"; qDebug() << " maxSize=" << maxSize; qDebug("OctreeInboundPacketProcessor::processPacket() %c " - "packetData=%p packetLength=%d voxelData=%p atByte=%d maxSize=%d", + "packetData=%p packetLength=%d editData=%p atByte=%d maxSize=%d", packetType, packetData, packet.size(), editData, atByte, maxSize); } @@ -174,7 +174,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin processTime += thisProcessTime; lockWaitTime += thisLockWaitTime; - // skip to next voxel edit record in the packet + // skip to next edit record in the packet editData += editDataBytesRead; atByte += editDataBytesRead; @@ -188,7 +188,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin if (debugProcessPacket) { qDebug("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %c " - "packetData=%p packetLength=%d voxelData=%p atByte=%d", + "packetData=%p packetLength=%d editData=%p atByte=%d", packetType, packetData, packet.size(), editData, atByte); } @@ -261,7 +261,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() { continue; } - const SharedNodePointer& destinationNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + const SharedNodePointer& destinationNode = DependencyManager::get()->nodeWithUUID(nodeUUID); // retrieve sequence number stats of node, prune its missing set SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats(); @@ -299,7 +299,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() { numSequenceNumbersAvailable -= numSequenceNumbers; // send it - NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); + DependencyManager::get()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); packetsSent++; qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID; diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h index 2fb83123c4..8f07f9d566 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.h +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.h @@ -5,7 +5,7 @@ // Created by Brad Hefta-Gaub on 8/21/13. // Copyright 2013 High Fidelity, Inc. // -// Threaded or non-threaded network packet processor for the voxel-server +// Threaded or non-threaded network packet processor for octree servers // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -53,7 +53,7 @@ typedef QHash::iterator NodeToSenderStatsMapIterator; typedef QHash::const_iterator NodeToSenderStatsMapConstIterator; -/// Handles processing of incoming network packets for the voxel-server. As with other ReceivedPacketProcessor classes +/// Handles processing of incoming network packets for the octee servers. As with other ReceivedPacketProcessor classes /// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket() class OctreeInboundPacketProcessor : public ReceivedPacketProcessor { Q_OBJECT @@ -89,7 +89,7 @@ private: private: void trackInboundPacket(const QUuid& nodeUUID, unsigned short int sequence, quint64 transitTime, - int voxelsInPacket, quint64 processTime, quint64 lockWaitTime); + int elementsInPacket, quint64 processTime, quint64 lockWaitTime); OctreeServer* _myServer; int _receivedPacketCount; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 46ea49e9a7..277d4fac1f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -147,10 +147,10 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes int statsMessageLength = nodeData->stats.getStatsMessageLength(); int piggyBackSize = nodeData->getPacketLength() + statsMessageLength; - // If the size of the stats message and the voxel message will fit in a packet, then piggyback them + // If the size of the stats message and the octree message will fit in a packet, then piggyback them if (piggyBackSize < MAX_PACKET_SIZE) { - // copy voxel message to back of stats message + // copy octree message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); statsMessageLength += nodeData->getPacketLength(); @@ -179,12 +179,12 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // actually send it OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node); + DependencyManager::get()->writeDatagram((char*) statsMessage, statsMessageLength, _node); packetSent = true; } else { // not enough room in the packet, send two packets OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node); + DependencyManager::get()->writeDatagram((char*) statsMessage, statsMessageLength, _node); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // there was nothing else to send. @@ -213,7 +213,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes packetsSent++; OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); + DependencyManager::get()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -240,9 +240,9 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes } else { // If there's actually a packet waiting, then send it. if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) { - // just send the voxel packet + // just send the octree packet OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); + DependencyManager::get()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -279,7 +279,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes return packetsSent; } -/// Version of voxel distributor that sends the deepest LOD level at once +/// Version of octree element distributor that sends the deepest LOD level at once int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) { OctreeServer::didPacketDistributor(this); @@ -404,6 +404,13 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus bool lastNodeDidntFit = false; // assume each node fits if (!nodeData->elementBag.isEmpty()) { + + quint64 lockWaitStart = usecTimestampNow(); + _myServer->getOctree()->lockForRead(); + quint64 lockWaitEnd = usecTimestampNow(); + lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart); + quint64 encodeStart = usecTimestampNow(); + OctreeElement* subTree = nodeData->elementBag.extract(); /* TODO: Looking for a way to prevent locking and encoding a tree that is not @@ -430,7 +437,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus bool wantOcclusionCulling = nodeData->getWantOcclusionCulling(); CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP; - float voxelSizeScale = nodeData->getOctreeSizeScale(); + float octreeSizeScale = nodeData->getOctreeSizeScale(); int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust(); int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged && nodeData->getWantLowResMoving() @@ -438,7 +445,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, - wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale, + wantOcclusionCulling, coverageMap, boundaryLevelAdjust, octreeSizeScale, nodeData->getLastTimeBagEmpty(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData); @@ -447,12 +454,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // it seems like it may be a good idea to include the lock time as part of the encode time // are reported to client. Since you can encode without the lock nodeData->stats.encodeStarted(); - - quint64 lockWaitStart = usecTimestampNow(); - _myServer->getOctree()->lockForRead(); - quint64 lockWaitEnd = usecTimestampNow(); - lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart); - quint64 encodeStart = usecTimestampNow(); bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params); @@ -574,7 +575,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus while (nodeData->hasNextNackedPacket() && packetsSentThisInterval < maxPacketsPerInterval) { const QByteArray* packet = nodeData->getNextNackedPacket(); if (packet) { - NodeList::getInstance()->writeDatagram(*packet, _node); + DependencyManager::get()->writeDatagram(*packet, _node); truePacketsSent++; packetsSentThisInterval++; @@ -595,7 +596,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus //int elapsedCompressTimeMsecs = endCompressTimeMsecs - startCompressTimeMsecs; // if after sending packets we've emptied our bag, then we want to remember that we've sent all - // the voxels from the current view frustum + // the octree elements from the current view frustum if (nodeData->elementBag.isEmpty()) { nodeData->updateLastKnownViewFrustum(); nodeData->setViewSent(true); diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index d8eed27802..d0507fc83d 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -5,7 +5,7 @@ // Created by Brad Hefta-Gaub on 8/21/13. // Copyright 2013 High Fidelity, Inc. // -// Threaded or non-threaded object for sending voxels to a client +// Threaded or non-threaded object for sending octree data packets to a client // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -22,7 +22,7 @@ class OctreeServer; -/// Threaded processor for sending voxel packets to a single client +/// Threaded processor for sending octree packets to a single client class OctreeSendThread : public GenericThread { Q_OBJECT public: diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 4be2c9873f..aaf37c2beb 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include @@ -358,7 +359,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url statsString += "Uptime: " + getUptime(); statsString += "\r\n\r\n"; - // display voxel file load time + // display octree file load time if (isInitialLoadComplete()) { if (isPersistEnabled()) { statsString += QString("%1 File Persist Enabled...\r\n").arg(getMyServerName()); @@ -373,7 +374,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url statsString += "\r\n"; } else { - statsString += "Voxels not yet loaded...\r\n"; + statsString += "Octree file not yet loaded...\r\n"; } statsString += "\r\n\r\n"; @@ -712,7 +713,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } statsString += QString().sprintf("Element Node Memory Usage: %8.2f %s\r\n", - OctreeElement::getVoxelMemoryUsage() / memoryScale, memoryScaleLabel); + OctreeElement::getOctreeMemoryUsage() / memoryScale, memoryScaleLabel); statsString += QString().sprintf("Octcode Memory Usage: %8.2f %s\r\n", OctreeElement::getOctcodeMemoryUsage() / memoryScale, memoryScaleLabel); statsString += QString().sprintf("External Children Memory Usage: %8.2f %s\r\n", @@ -829,7 +830,7 @@ void OctreeServer::parsePayload() { } void OctreeServer::readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType packetType = packetTypeForPacket(receivedPacket); @@ -865,13 +866,13 @@ void OctreeServer::readPendingDatagram(const QByteArray& receivedPacket, const H _octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, receivedPacket); } else { // let processNodeData handle it. - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } } } void OctreeServer::setupDatagramProcessingThread() { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // we do not want this event loop to be the handler for UDP datagrams, so disconnect disconnect(&nodeList->getNodeSocket(), 0, this, 0); @@ -960,7 +961,7 @@ void OctreeServer::readConfiguration() { } // wait until we have the domain-server settings, otherwise we bail - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); DomainHandler& domainHandler = nodeList->getDomainHandler(); qDebug() << "Waiting for domain settings from domain-server."; @@ -978,6 +979,7 @@ void OctreeServer::readConfiguration() { const QJsonObject& settingsObject = domainHandler.getSettingsObject(); QString settingsKey = getMyDomainSettingsKey(); QJsonObject settingsSectionObject = settingsObject[settingsKey].toObject(); + _settings = settingsSectionObject; // keep this for later if (!readOptionString(QString("statusHost"), settingsSectionObject, _statusHost) || _statusHost.isEmpty()) { _statusHost = getLocalAddress().toString(); @@ -1042,20 +1044,8 @@ void OctreeServer::readConfiguration() { _wantBackup = !noBackup; qDebug() << "wantBackup=" << _wantBackup; - if (_wantBackup) { - _backupExtensionFormat = OctreePersistThread::DEFAULT_BACKUP_EXTENSION_FORMAT; - readOptionString(QString("backupExtensionFormat"), settingsSectionObject, _backupExtensionFormat); - qDebug() << "backupExtensionFormat=" << _backupExtensionFormat; - - _backupInterval = OctreePersistThread::DEFAULT_BACKUP_INTERVAL; - readOptionInt(QString("backupInterval"), settingsSectionObject, _backupInterval); - qDebug() << "backupInterval=" << _backupInterval; - - _maxBackupVersions = OctreePersistThread::DEFAULT_MAX_BACKUP_VERSIONS; - readOptionInt(QString("maxBackupVersions"), settingsSectionObject, _maxBackupVersions); - qDebug() << "maxBackupVersions=" << _maxBackupVersions; - } - + //qDebug() << "settingsSectionObject:" << settingsSectionObject; + } else { qDebug("persistFilename= DISABLED"); } @@ -1106,7 +1096,7 @@ void OctreeServer::run() { _tree->setIsServer(true); // make sure our NodeList knows what type we are - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->setOwnerType(getMyNodeType()); @@ -1120,8 +1110,8 @@ void OctreeServer::run() { beforeRun(); // after payload has been processed - connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer))); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)),SLOT(nodeKilled(SharedNodePointer))); + connect(nodeList.data(), SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer))); + connect(nodeList.data(), SIGNAL(nodeKilled(SharedNodePointer)),SLOT(nodeKilled(SharedNodePointer))); // we need to ask the DS about agents so we can ping/reply with them @@ -1140,8 +1130,7 @@ void OctreeServer::run() { // now set up PersistThread _persistThread = new OctreePersistThread(_tree, _persistFilename, _persistInterval, - _wantBackup, _backupInterval, _backupExtensionFormat, - _maxBackupVersions, _debugTimestampNow); + _wantBackup, _settings, _debugTimestampNow); if (_persistThread) { _persistThread->initialize(true); } @@ -1223,7 +1212,7 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; _octreeInboundPacketProcessor->shuttingDown(); - NodeList::getInstance()->eachNode([this](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([this](const SharedNodePointer& node) { qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; forceNodeShutdown(node); }); @@ -1388,7 +1377,7 @@ void OctreeServer::sendStatsPacket() { statsObject2[baseName + QString(".2.outbound.timing.5.avgSendTime")] = getAveragePacketSendingTime(); statsObject2[baseName + QString(".2.outbound.timing.5.nodeWaitTime")] = getAverageNodeWaitTime(); - NodeList::getInstance()->sendStatsToDomainServer(statsObject2); + DependencyManager::get()->sendStatsToDomainServer(statsObject2); static QJsonObject statsObject3; @@ -1407,7 +1396,7 @@ void OctreeServer::sendStatsPacket() { statsObject3[baseName + QString(".3.inbound.timing.5.avgLockWaitTimePerElement")] = (double)_octreeInboundPacketProcessor->getAverageLockWaitTimePerElement(); - NodeList::getInstance()->sendStatsToDomainServer(statsObject3); + DependencyManager::get()->sendStatsToDomainServer(statsObject3); } QMap OctreeServer::_threadsDidProcess; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 4999594a98..0f90c2941e 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -121,7 +121,7 @@ public: void forceNodeShutdown(SharedNodePointer node); public slots: - /// runs the voxel server assignment + /// runs the octree server assignment void run(); void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); @@ -150,6 +150,7 @@ protected: int _argc; const char** _argv; char** _parsedArgV; + QJsonObject _settings; HTTPManager* _httpManager; int _statusPort; diff --git a/assignment-client/src/octree/OctreeServerConsts.h b/assignment-client/src/octree/OctreeServerConsts.h index a10c81494c..02f59f3802 100644 --- a/assignment-client/src/octree/OctreeServerConsts.h +++ b/assignment-client/src/octree/OctreeServerConsts.h @@ -19,6 +19,6 @@ const int MAX_FILENAME_LENGTH = 1024; const int INTERVALS_PER_SECOND = 60; const int OCTREE_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND; -const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels +const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for sending octree elements #endif // hifi_OctreeServerConsts_h diff --git a/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp b/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp index 0d3c622900..9f2ae72147 100644 --- a/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp +++ b/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp @@ -45,7 +45,7 @@ void OctreeServerDatagramProcessor::readPendingDatagrams() { PacketType packetType = packetTypeForPacket(incomingPacket); if (packetType == PacketTypePing) { - NodeList::getInstance()->processNodeData(senderSockAddr, incomingPacket); + DependencyManager::get()->processNodeData(senderSockAddr, incomingPacket); return; // don't emit } diff --git a/assignment-client/src/voxels/VoxelNodeData.h b/assignment-client/src/voxels/VoxelNodeData.h deleted file mode 100644 index dada32ac3e..0000000000 --- a/assignment-client/src/voxels/VoxelNodeData.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// VoxelNodeData.h -// assignment-client/src/voxels -// -// Created by Stephen Birarda on 3/21/13. -// 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_VoxelNodeData_h -#define hifi_VoxelNodeData_h - -#include - -#include "../octree/OctreeQueryNode.h" - -class VoxelNodeData : public OctreeQueryNode { -public: - VoxelNodeData() : OctreeQueryNode() { } - virtual PacketType getMyPacketType() const { return PacketTypeVoxelData; } -}; - -#endif // hifi_VoxelNodeData_h diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp deleted file mode 100644 index a83e3e99e3..0000000000 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// VoxelServer.cpp -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 9/16/13. -// Copyright 2013 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 - -#include "VoxelServer.h" -#include "VoxelServerConsts.h" -#include "VoxelNodeData.h" - -const char* VOXEL_SERVER_NAME = "Voxel"; -const char* VOXEL_SERVER_LOGGING_TARGET_NAME = "voxel-server"; -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; - -VoxelServer::VoxelServer(const QByteArray& packet) : OctreeServer(packet) { - // nothing special to do here... -} - -VoxelServer::~VoxelServer() { - // nothing special to do here... -} - -OctreeQueryNode* VoxelServer::createOctreeQueryNode() { - return new VoxelNodeData(); -} - -Octree* VoxelServer::createTree() { - return new VoxelTree(true); -} - -bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { - bool shouldSendEnvironments = _sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, OCTREE_SEND_INTERVAL_USECS); - return shouldSendEnvironments; -} - -int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { - - unsigned char* copyAt = _tempOutputBuffer; - - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); - copyAt += numBytesPacketHeader; - int envPacketLength = numBytesPacketHeader; - - // pack in flags - OCTREE_PACKET_FLAGS flags = 0; - OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; - *flagsAt = flags; - copyAt += sizeof(OCTREE_PACKET_FLAGS); - envPacketLength += sizeof(OCTREE_PACKET_FLAGS); - - // pack in sequence number - OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; - *sequenceAt = queryNode->getSequenceNumber(); - copyAt += sizeof(OCTREE_PACKET_SEQUENCE); - envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); - - // pack in timestamp - OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); - OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; - *timeAt = now; - copyAt += sizeof(OCTREE_PACKET_SENT_TIME); - envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); - - int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); - - for (int i = 0; i < environmentsToSend; i++) { - envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); - } - - NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); - queryNode->packetSent(_tempOutputBuffer, envPacketLength); - packetsSent = 1; - - return envPacketLength; -} - - -void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { - // should we send environments? Default is yes, but this command line suppresses sending - readOptionBool(QString("sendEnvironments"), settingsSectionObject, _sendEnvironments); - bool dontSendEnvironments = !_sendEnvironments; - if (dontSendEnvironments) { - qDebug("Sending environments suppressed..."); - } else { - // should we send environments? Default is yes, but this command line suppresses sending - //const char* MINIMAL_ENVIRONMENT = "--minimalEnvironment"; - //_sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT); - - readOptionBool(QString("minimalEnvironment"), settingsSectionObject, _sendMinimalEnvironment); - qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment)); - } - qDebug("Sending environments=%s", debug::valueOf(_sendEnvironments)); - - NodeList::getInstance()->addNodeTypeToInterestSet(NodeType::AnimationServer); -} diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h deleted file mode 100644 index 4d21695f33..0000000000 --- a/assignment-client/src/voxels/VoxelServer.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// VoxelServer.h -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 8/21/13. -// Copyright 2013 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_VoxelServer_h -#define hifi_VoxelServer_h - -#include -#include -#include - -#include -#include - -#include "../octree/OctreeServer.h" - -#include "VoxelServerConsts.h" - -/// Handles assignments of type VoxelServer - sending voxels to various clients. -class VoxelServer : public OctreeServer { -public: - VoxelServer(const QByteArray& packet); - ~VoxelServer(); - - bool wantSendEnvironments() const { return _sendEnvironments; } - bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; } - EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; } - int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); } - - // Subclasses must implement these methods - virtual OctreeQueryNode* createOctreeQueryNode(); - virtual char getMyNodeType() const { return NodeType::VoxelServer; } - virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; } - virtual const char* getMyServerName() const { return VOXEL_SERVER_NAME; } - virtual const char* getMyLoggingServerTargetName() const { return VOXEL_SERVER_LOGGING_TARGET_NAME; } - virtual const char* getMyDefaultPersistFilename() const { return LOCAL_VOXELS_PERSIST_FILE; } - virtual PacketType getMyEditNackType() const { return PacketTypeVoxelEditNack; } - virtual QString getMyDomainSettingsKey() const { return QString("voxel_server_settings"); } - - // subclass may implement these method - virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent); - -protected: - virtual Octree* createTree(); - virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); - -private: - bool _sendEnvironments; - bool _sendMinimalEnvironment; - EnvironmentData _environmentData[3]; - unsigned char _tempOutputBuffer[MAX_PACKET_SIZE]; -}; - -#endif // hifi_VoxelServer_h diff --git a/assignment-client/src/voxels/VoxelServerConsts.h b/assignment-client/src/voxels/VoxelServerConsts.h deleted file mode 100644 index 5764e7d4cf..0000000000 --- a/assignment-client/src/voxels/VoxelServerConsts.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// VoxelServerConsts.h -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 8/21/13. -// Copyright 2013 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_VoxelServerConsts_h -#define hifi_VoxelServerConsts_h - -extern const char* VOXEL_SERVER_NAME; -extern const char* VOXEL_SERVER_LOGGING_TARGET_NAME; -extern const char* LOCAL_VOXELS_PERSIST_FILE; - -const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000; - -#endif // hifi_VoxelServerConsts_h diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake new file mode 100755 index 0000000000..5584afe5e9 --- /dev/null +++ b/cmake/macros/AutoScribeShader.cmake @@ -0,0 +1,83 @@ +# +# AutoScribeShader.cmake +# +# Created by Sam Gateau on 12/17/14. +# 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 +# + +function(AUTOSCRIBE_SHADER SHADER_FILE) + + # Grab include files + foreach(includeFile ${ARGN}) + list(APPEND SHADER_INCLUDE_FILES ${includeFile}) + endforeach() + + #Extract the unique include shader paths + foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES}) + get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH) + list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR}) + endforeach() + list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS) + + # make the scribe include arguments + set(SCRIBE_INCLUDES) + foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS}) + set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/) + endforeach() + + # Define the final name of the generated shader file + get_filename_component(SHADER_TARGET ${SHADER_FILE} NAME_WE) + get_filename_component(SHADER_EXT ${SHADER_FILE} EXT) + if(SHADER_EXT STREQUAL .slv) + set(SHADER_TARGET ${SHADER_TARGET}_vert.h) + elseif(${SHADER_EXT} STREQUAL .slf) + set(SHADER_TARGET ${SHADER_TARGET}_frag.h) + endif() + + # Target dependant Custom rule on the SHADER_FILE + if (APPLE) + set(GLPROFILE MAC_GL) + set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE}) + + add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE}) + else (APPLE) + set(GLPROFILE PC_GL) + set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE}) + + add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE}) + endif() + + #output the generated file name + set(AUTOSCRIBE_SHADER_RETURN ${SHADER_TARGET} PARENT_SCOPE) + + file(GLOB INCLUDE_FILES ${SHADER_TARGET}) + +endfunction() + + +macro(AUTOSCRIBE_SHADER_LIB) + + file(GLOB_RECURSE SHADER_INCLUDE_FILES src/*.slh) + file(GLOB_RECURSE SHADER_SOURCE_FILES src/*.slv src/*.slf) + + #message(${SHADER_INCLUDE_FILES}) + foreach(SHADER_FILE ${SHADER_SOURCE_FILES}) + AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES}) + list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_SHADER_RETURN}) + endforeach() + #message(${AUTOSCRIBE_SHADER_SRC}) + + if (WIN32) + source_group("Shaders" FILES ${SHADER_INCLUDE_FILES}) + source_group("Shaders" FILES ${SHADER_SOURCE_FILES}) + source_group("Shaders" FILES ${AUTOSCRIBE_SHADER_SRC}) + endif() + + list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${SHADER_INCLUDE_FILES}) + list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${SHADER_SOURCE_FILES}) + list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${AUTOSCRIBE_SHADER_SRC}) + +endmacro() diff --git a/cmake/macros/IncludeBullet.cmake b/cmake/macros/IncludeBullet.cmake new file mode 100644 index 0000000000..a238b33660 --- /dev/null +++ b/cmake/macros/IncludeBullet.cmake @@ -0,0 +1,18 @@ +# +# IncludeBullet.cmake +# +# 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 +# + +macro(INCLUDE_BULLET) + find_package(Bullet) + if (BULLET_FOUND) + include_directories("${BULLET_INCLUDE_DIRS}") + if (APPLE OR UNIX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_BULLET_PHYSICS -isystem ${BULLET_INCLUDE_DIRS}") + endif () + endif (BULLET_FOUND) +endmacro(INCLUDE_BULLET) diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/IncludeDependencyIncludes.cmake similarity index 59% rename from cmake/macros/LinkSharedDependencies.cmake rename to cmake/macros/IncludeDependencyIncludes.cmake index 9168c5a921..4474bdc53a 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/IncludeDependencyIncludes.cmake @@ -1,5 +1,5 @@ # -# LinkSharedDependencies.cmake +# IncludeDependencyIncludes.cmake # cmake/macros # # Copyright 2014 High Fidelity, Inc. @@ -9,14 +9,14 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -macro(LINK_SHARED_DEPENDENCIES) +macro(INCLUDE_DEPENDENCY_INCLUDES) if (${TARGET_NAME}_DEPENDENCY_INCLUDES) list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_INCLUDES) # include those in our own target include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES}) - endif () - - # set the property on this target so it can be retreived by targets linking to us - set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") -endmacro(LINK_SHARED_DEPENDENCIES) \ No newline at end of file + + # set the property on this target so it can be retreived by targets linking to us + set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") + endif() +endmacro(INCLUDE_DEPENDENCY_INCLUDES) \ No newline at end of file diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index 646b680f27..ef0c8321c6 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -27,7 +27,10 @@ macro(LINK_HIFI_LIBRARIES) # ask the library what its include dependencies are and link them get_target_property(LINKED_TARGET_DEPENDENCY_INCLUDES ${HIFI_LIBRARY} DEPENDENCY_INCLUDES) - list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES}) + + if(LINKED_TARGET_DEPENDENCY_INCLUDES) + list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES}) + endif() endforeach() endmacro(LINK_HIFI_LIBRARIES) \ No newline at end of file diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index 362a833862..e76e1112e3 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -16,7 +16,7 @@ macro(SETUP_HIFI_LIBRARY) set(LIB_SRCS ${LIB_SRCS}) # create a library and set the property so it can be referenced later - add_library(${TARGET_NAME} ${LIB_SRCS} ${AUTOMTC_SRC}) + add_library(${TARGET_NAME} ${LIB_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC}) set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN}) list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core) diff --git a/cmake/modules/FindFaceplus.cmake b/cmake/modules/FindFaceplus.cmake deleted file mode 100644 index e97fce3edb..0000000000 --- a/cmake/modules/FindFaceplus.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Try to find the Faceplus library -# -# You must provide a FACEPLUS_ROOT_DIR which contains lib and include directories -# -# Once done this will define -# -# FACEPLUS_FOUND - system found Faceplus -# FACEPLUS_INCLUDE_DIRS - the Faceplus include directory -# FACEPLUS_LIBRARIES - Link this to use Faceplus -# -# Created on 4/8/2014 by Andrzej Kapolka -# Copyright (c) 2014 High Fidelity -# - -find_path(FACEPLUS_INCLUDE_DIRS faceplus.h ${FACEPLUS_ROOT_DIR}/include) - -if (WIN32) - find_library(FACEPLUS_LIBRARIES faceplus.lib ${FACEPLUS_ROOT_DIR}/win32/) -endif (WIN32) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Faceplus DEFAULT_MSG FACEPLUS_INCLUDE_DIRS FACEPLUS_LIBRARIES) - -mark_as_advanced(FACEPLUS_INCLUDE_DIRS FACEPLUS_LIBRARIES) \ No newline at end of file diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 99d6dfc003..363f346d09 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -21,17 +21,17 @@ if (WIN32) include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") hifi_library_search_hints("glew") - - find_path(GLEW_INCLUDE_DIRS GL/glew.h PATH_SUFFIXES include HINTS ${GLEW_SEARCH_DIRS}) - find_library(GLEW_LIBRARY_RELEASE glew32s PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) - find_library(GLEW_LIBRARY_DEBUG glew32s PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) + find_path(GLEW_INCLUDE_DIRS GL/glew.h PATH_SUFFIXES include HINTS ${GLEW_SEARCH_DIRS}) + + find_library(GLEW_LIBRARY_RELEASE glew32s PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) + find_library(GLEW_LIBRARY_DEBUG glew32sd PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) include(SelectLibraryConfigurations) select_library_configurations(GLEW) endif () -set(GLEW_LIBRARIES "${GLEW_LIBRARY}") +set(GLEW_LIBRARIES ${GLEW_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES) diff --git a/cmake/modules/FindGLUT.cmake b/cmake/modules/FindGLUT.cmake deleted file mode 100644 index e7bf752aca..0000000000 --- a/cmake/modules/FindGLUT.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# -# FindGLUT.cmake -# -# Try to find GLUT library and include path. -# Once done this will define -# -# GLUT_FOUND -# GLUT_INCLUDE_DIRS -# GLUT_LIBRARIES -# -# Created on 2/6/2014 by Stephen Birarda -# Copyright 2014 High Fidelity, Inc. -# -# Adapted from FindGLUT.cmake available in tlorach's OpenGLText Repository -# https://raw.github.com/tlorach/OpenGLText/master/cmake/FindGLUT.cmake -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") -hifi_library_search_hints("freeglut") - -if (WIN32) - set(GLUT_HINT_DIRS "${FREEGLUT_SEARCH_DIRS} ${OPENGL_INCLUDE_DIR}") - - find_path(GLUT_INCLUDE_DIRS GL/glut.h PATH_SUFFIXES include HINTS ${FREEGLUT_SEARCH_DIRS}) - find_library(GLUT_LIBRARY freeglut PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) -else () - find_path(GLUT_INCLUDE_DIRS GL/glut.h PATH_SUFFIXES include HINTS ${FREEGLUT_SEARCH_DIRS}) - find_library(GLUT_LIBRARY glut PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) -endif () - -include(FindPackageHandleStandardArgs) - -set(GLUT_LIBRARIES "${GLUT_LIBRARY}" "${XMU_LIBRARY}" "${XI_LIBRARY}") - -if (UNIX) - find_library(XI_LIBRARY Xi PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) - find_library(XMU_LIBRARY Xmu PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) - - find_package_handle_standard_args(GLUT DEFAULT_MSG GLUT_INCLUDE_DIRS GLUT_LIBRARIES XI_LIBRARY XMU_LIBRARY) -else () - find_package_handle_standard_args(GLUT DEFAULT_MSG GLUT_INCLUDE_DIRS GLUT_LIBRARIES) -endif () - -mark_as_advanced(GLUT_INCLUDE_DIRS GLUT_LIBRARIES GLUT_LIBRARY XI_LIBRARY XMU_LIBRARY FREEGLUT_SEARCH_DIRS) \ No newline at end of file diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 482c397b14..421a1da2d4 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -52,4 +52,4 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index ae6f116537..e2f751a7f0 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -305,20 +305,66 @@ "settings": [ { "name": "persistFilename", - "label": "Persistant Filename", - "help": "the filename for your entities", + "label": "Entities Filename", + "help": "the path to the file entities are stored in. Make sure the path exists.", "placeholder": "resources/models.svo", "default": "resources/models.svo", "advanced": true }, { "name": "persistInterval", - "label": "Persist Interval", - "help": "Interval between persist checks in msecs.", + "label": "Save Check Interval", + "help": "Milliseconds between checks for saving the current state of entities.", "placeholder": "30000", "default": "30000", "advanced": true }, + { + "name": "backups", + "type": "table", + "label": "Backup Rules", + "help": "In this table you can define a set of rules for how frequently to backup copies of your entites content file.", + "numbered": false, + "default": [ + {"Name":"Half Hourly Rolling","backupInterval":1800,"format":".backup.halfhourly.%N","maxBackupVersions":5}, + {"Name":"Daily Rolling","backupInterval":86400,"format":".backup.daily.%N","maxBackupVersions":7}, + {"Name":"Weekly Rolling","backupInterval":604800,"format":".backup.weekly.%N","maxBackupVersions":4}, + {"Name":"Thirty Day Rolling","backupInterval":2592000,"format":".backup.thirtyday.%N","maxBackupVersions":12} + ], + "columns": [ + { + "name": "Name", + "label": "Name", + "can_set": true, + "placeholder": "Example", + "default": "Example" + }, + { + "name": "format", + "label": "Rule Format", + "can_set": true, + "help": "Format used to create the extension for the backup of your persisted entities. Use a format with %N to get rolling. Or use date formatting like %Y-%m-%d.%H:%M:%S.%z", + "placeholder": ".backup.example.%N", + "default": ".backup.example.%N" + }, + { + "name": "backupInterval", + "label": "Backup Interval in Seconds", + "help": "Interval between backup checks in seconds.", + "placeholder": 1800, + "default": 1800, + "can_set": true + }, + { + "name": "maxBackupVersions", + "label": "Max Rolled Backup Versions", + "help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?", + "placeholder": 5, + "default": 5, + "can_set": true + } + ] + }, { "name": "NoPersist", "type": "checkbox", @@ -326,30 +372,6 @@ "default": false, "advanced": true }, - { - "name": "backupExtensionFormat", - "label": "Backup File Extension Format:", - "help": "Format used to create the extension for the backup of your persisted entities. Use a format with %N to get rolling. Or use date formatting like %Y-%m-%d.%H:%M:%S.%z", - "placeholder": ".backup.%N", - "default": ".backup.%N", - "advanced": true - }, - { - "name": "backupInterval", - "label": "Backup Interval", - "help": "Interval between backup checks in msecs.", - "placeholder": "1800000", - "default": "1800000", - "advanced": true - }, - { - "name": "maxBackupVersions", - "label": "Max Rolled Backup Versions", - "help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?", - "placeholder": "5", - "default": "5", - "advanced": true - }, { "name": "NoBackup", "type": "checkbox", @@ -410,99 +432,5 @@ "advanced": true } ] - }, - - - { - "name": "voxel_server_settings", - "label": "Voxel Server Settings", - "assignment-types": [3], - "settings": [ - { - "name": "persistFilename", - "label": "Persistant Filename", - "help": "the filename for your voxels", - "placeholder": "resources/voxels.svo", - "default": "resources/voxels.svo", - "advanced": true - }, - { - "name": "persistInterval", - "label": "Persist Interval", - "help": "Interval between persist checks in msecs.", - "placeholder": "30000", - "default": "30000", - "advanced": true - }, - { - "name": "NoPersist", - "type": "checkbox", - "help": "Don't persist your voxels to a file.", - "default": false, - "advanced": true - }, - { - "name": "backupExtensionFormat", - "label": "Backup File Extension Format:", - "help": "Format used to create the extension for the backup of your persisted voxels.", - "placeholder": ".backup.%Y-%m-%d.%H:%M:%S.%z", - "default": ".backup.%Y-%m-%d.%H:%M:%S.%z", - "advanced": true - }, - { - "name": "backupInterval", - "label": "Backup Interval", - "help": "Interval between backup checks in msecs.", - "placeholder": "1800000", - "default": "1800000", - "advanced": true - }, - { - "name": "NoBackup", - "type": "checkbox", - "help": "Don't regularly backup your persisted voxels to a backup file.", - "default": false, - "advanced": true - }, - { - "name": "statusHost", - "label": "Status Hostname", - "help": "host name or IP address of the server for accessing the status page", - "placeholder": "", - "default": "", - "advanced": true - }, - { - "name": "statusPort", - "label": "Status Port", - "help": "port of the server for accessing the status page", - "placeholder": "", - "default": "", - "advanced": true - }, - { - "name": "clockSkew", - "label": "Clock Skew", - "help": "Number of msecs to skew the server clock by to test clock skew", - "placeholder": "0", - "default": "0", - "advanced": true - }, - { - "name": "sendEnvironments", - "type": "checkbox", - "help": "send environmental data", - "default": false, - "advanced": true - }, - { - "name": "minimalEnvironment", - "type": "checkbox", - "help": "send minimal environmental data if sending environmental data", - "default": false, - "advanced": true - } - ] - } - + } ] \ No newline at end of file diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 141bd72a26..1e9051d717 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -364,7 +364,7 @@ function makeTableInputs(setting) { _.each(setting.columns, function(col) { html += "\ \ + value='" + (col.default ? col.default : "") + "' data-default='" + (col.default ? col.default : "") + "'>\ " }) @@ -504,7 +504,7 @@ function addTableRow(add_glyphicon) { }) input_clone.find('input').each(function(){ - $(this).val('') + $(this).val($(this).attr('data-default')); }); if (isArray) { @@ -525,9 +525,9 @@ function deleteTableRow(delete_glyphicon) { var table = $(row).closest('table') var isArray = table.data('setting-type') === 'array' + row.empty(); + if (!isArray) { - // this is a hash row, so we empty it but leave the hidden input blank so it is cleared when we save - row.empty() row.html(""); } else { @@ -538,7 +538,6 @@ function deleteTableRow(delete_glyphicon) { row.remove() } else { // this is the last row, we can't remove it completely since we need to post an empty array - row.empty() row.removeClass(Settings.DATA_ROW_CLASS).removeClass(Settings.NEW_ROW_CLASS) row.addClass('empty-array-row') @@ -592,7 +591,7 @@ function updateDataChangedForSiblingRows(row, forceTrue) { var initialPanelSettingJSON = Settings.initialValues[panelParentID][tableShortName] // if they are equal, we don't need data-changed - isTrue = _.isEqual(panelSettingJSON, initialPanelSettingJSON) + isTrue = !_.isEqual(panelSettingJSON, initialPanelSettingJSON) } else { isTrue = true } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 73092b694b..791c7e37b6 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -237,7 +237,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // check for scripts the user wants to persist from their domain-server config populateStaticScriptedAssignmentsFromSettings(); - LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort); + auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); @@ -262,11 +262,11 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { nodeList->setSessionUUID(idValueVariant->toString()); } - connect(nodeList, &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); - connect(nodeList, &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); + connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); + connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); QTimer* silentNodeTimer = new QTimer(this); - connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + connect(silentNodeTimer, SIGNAL(timeout()), nodeList.data(), SLOT(removeSilentNodes())); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS); connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams())); @@ -346,8 +346,7 @@ bool DomainServer::optionallySetupAssignmentPayment() { } void DomainServer::setupAutomaticNetworking() { - - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000; const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; @@ -368,8 +367,10 @@ void DomainServer::setupAutomaticNetworking() { iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); // call our sendHeartbeatToIceServer immediately anytime a local or public socket changes - connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); - connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, + this, &DomainServer::sendHeartbeatToIceServer); + connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged, + this, &DomainServer::sendHeartbeatToIceServer); // attempt to update our public socket now, this will send a heartbeat once we get public socket requestCurrentPublicSocketViaSTUN(); @@ -400,7 +401,8 @@ void DomainServer::setupAutomaticNetworking() { dynamicIPTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS); // send public socket changes to the data server so nodes can find us at our new IP - connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate); + connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged, + this, &DomainServer::performIPAddressUpdate); // attempt to update our sockets now requestCurrentPublicSocketViaSTUN(); @@ -549,7 +551,10 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet(static_cast(defaultedType) + 1)) { - if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) { + if (!excludedTypes.contains(defaultedType) + && defaultedType != Assignment::UNUSED_0 + && defaultedType != Assignment::UNUSED_1 + && defaultedType != Assignment::AgentType) { // type has not been set from a command line or config file config, use the default // by clearing whatever exists and writing a single default assignment with no payload Assignment* newAssignment = new Assignment(Assignment::CreateCommand, (Assignment::Type) defaultedType); @@ -559,7 +564,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSetwriteUnverifiedDatagram(usernameRequestByteArray, senderSockAddr); + DependencyManager::get()->writeUnverifiedDatagram(usernameRequestByteArray, senderSockAddr); return; } @@ -634,7 +639,7 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock } - SharedNodePointer newNode = LimitedNodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType, + SharedNodePointer newNode = DependencyManager::get()->addOrUpdateNode(nodeUUID, nodeType, publicSockAddr, localSockAddr); // when the newNode is created the linked data is also created // if this was a static assignment set the UUID, set the sendingSockAddr @@ -667,7 +672,7 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, QStringList allowedUsers = allowedUsersVariant ? allowedUsersVariant->toStringList() : QStringList(); // we always let in a user who is sending a packet from our local socket or from the localhost address - if (senderSockAddr.getAddress() == LimitedNodeList::getInstance()->getLocalSockAddr().getAddress() + if (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost) { return true; } @@ -840,8 +845,8 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos(); DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); - - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + + auto nodeList = DependencyManager::get(); // if we've established a connection via ICE with this peer, use that socket // otherwise just try to reply back to them on their sending socket (although that may not work) @@ -907,7 +912,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif } void DomainServer::readAvailableDatagrams() { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); HifiSockAddr senderSockAddr; QByteArray receivedPacket; @@ -995,7 +1000,7 @@ void DomainServer::readAvailableDatagrams() { void DomainServer::setupPendingAssignmentCredits() { // enumerate the NodeList to find the assigned nodes - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull() && !nodeData->getWalletUUID().isNull()) { @@ -1109,7 +1114,7 @@ void DomainServer::transactionJSONCallback(const QJsonObject& data) { } void DomainServer::requestCurrentPublicSocketViaSTUN() { - LimitedNodeList::getInstance()->sendSTUNRequest(); + DependencyManager::get()->sendSTUNRequest(); } QJsonObject jsonForDomainSocketUpdate(const HifiSockAddr& socket) { @@ -1131,7 +1136,8 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; - const QUuid& domainID = LimitedNodeList::getInstance()->getSessionUUID(); + auto nodeList = DependencyManager::get(); + const QUuid& domainID = nodeList->getSessionUUID(); // setup the domain object to send to the data server const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address"; @@ -1155,7 +1161,7 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { // add the number of currently connected agent users int numConnectedAuthedUsers = 0; - NodeList::getInstance()->eachNode([&numConnectedAuthedUsers](const SharedNodePointer& node){ + nodeList->eachNode([&numConnectedAuthedUsers](const SharedNodePointer& node){ if (node->getLinkedData() && !static_cast(node->getLinkedData())->getUsername().isEmpty()) { ++numConnectedAuthedUsers; } @@ -1184,11 +1190,11 @@ void DomainServer::performICEUpdates() { } void DomainServer::sendHeartbeatToIceServer() { - LimitedNodeList::getInstance()->sendHeartbeatToIceServer(_iceServerSocket); + DependencyManager::get()->sendHeartbeatToIceServer(_iceServerSocket); } void DomainServer::sendICEPingPackets() { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); QHash::iterator peer = _connectingICEPeers.begin(); @@ -1256,7 +1262,7 @@ void DomainServer::processICEPingReply(const QByteArray& packet, const HifiSockA } void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType requestType = packetTypeForPacket(receivedPacket); @@ -1407,6 +1413,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + auto nodeList = DependencyManager::get(); + // allow sub-handlers to handle requests that do not require authentication if (_settingsManager.handlePublicHTTPRequest(connection, url)) { return true; @@ -1449,7 +1457,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString URI_ID = "/id"; if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == URI_ID) { - QUuid domainID = LimitedNodeList::getInstance()->getSessionUUID(); + QUuid domainID = nodeList->getSessionUUID(); connection->respond(HTTPConnection::StatusCode200, uuidStringWithoutCurlyBraces(domainID).toLocal8Bit()); return true; @@ -1471,7 +1479,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonObject assignedNodesJSON; // enumerate the NodeList to find the assigned nodes - NodeList::getInstance()->eachNode([this, &assignedNodesJSON](const SharedNodePointer& node){ + nodeList->eachNode([this, &assignedNodesJSON](const SharedNodePointer& node){ DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull()) { @@ -1533,7 +1541,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonArray nodesJSONArray; // enumerate the NodeList to find the assigned nodes - LimitedNodeList::getInstance()->eachNode([this, &nodesJSONArray](const SharedNodePointer& node){ + nodeList->eachNode([this, &nodesJSONArray](const SharedNodePointer& node){ // add the node using the UUID as the key nodesJSONArray.append(jsonObjectForNode(node)); }); @@ -1556,7 +1564,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QUuid matchingUUID = QUuid(nodeShowRegex.cap(1)); // see if we have a node that matches this ID - SharedNodePointer matchingNode = LimitedNodeList::getInstance()->nodeWithUUID(matchingUUID); + SharedNodePointer matchingNode = nodeList->nodeWithUUID(matchingUUID); if (matchingNode) { // create a QJsonDocument with the stats QJsonObject QJsonObject statsObject = @@ -1650,14 +1658,14 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url // pull the captured string, if it exists QUuid deleteUUID = QUuid(nodeDeleteRegex.cap(1)); - SharedNodePointer nodeToKill = LimitedNodeList::getInstance()->nodeWithUUID(deleteUUID); + SharedNodePointer nodeToKill = nodeList->nodeWithUUID(deleteUUID); if (nodeToKill) { // start with a 200 response connection->respond(HTTPConnection::StatusCode200); // we have a valid UUID and node - kill the node that has this assignment - QMetaObject::invokeMethod(LimitedNodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID)); + QMetaObject::invokeMethod(nodeList.data(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID)); // successfully processed request return true; @@ -1666,7 +1674,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } else if (allNodesDeleteRegex.indexIn(url.path()) != -1) { qDebug() << "Received request to kill all nodes."; - LimitedNodeList::getInstance()->eraseAllNodes(); + nodeList->eraseAllNodes(); return true; } @@ -1733,6 +1741,9 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u connection->respond(HTTPConnection::StatusCode302, QByteArray(), HTTPConnection::DefaultContentType, cookieHeaders); + delete tokenReply; + delete profileReply; + // we've redirected the user back to our homepage return true; @@ -1983,7 +1994,7 @@ void DomainServer::nodeKilled(SharedNodePointer node) { // cleanup the connection secrets that we set up for this node (on the other nodes) foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) { - SharedNodePointer otherNode = LimitedNodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID); + SharedNodePointer otherNode = DependencyManager::get()->nodeWithUUID(otherNodeSessionUUID); if (otherNode) { reinterpret_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); } @@ -2066,7 +2077,7 @@ void DomainServer::addStaticAssignmentsToQueue() { // add any of the un-matched static assignments to the queue // enumerate the nodes and check if there is one with an attached assignment with matching UUID - if (!NodeList::getInstance()->nodeWithUUID(staticAssignment->data()->getUUID())) { + if (!DependencyManager::get()->nodeWithUUID(staticAssignment->data()->getUUID())) { // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue refreshStaticAssignmentAndAddToQueue(*staticAssignment); } diff --git a/examples/ControlACs.js b/examples/acScripts/ControlACs.js similarity index 96% rename from examples/ControlACs.js rename to examples/acScripts/ControlACs.js index 73a4385c24..0edbde4ad1 100644 --- a/examples/ControlACs.js +++ b/examples/acScripts/ControlACs.js @@ -145,13 +145,9 @@ function sendCommand(id, action) { return; } - Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize, - controlVoxelPosition.y, - controlVoxelPosition.z, - controlVoxelSize, - COLORS[action].red, - COLORS[action].green, - COLORS[action].blue); + // TODO: Fix this to use some mechanism other than voxels + //Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize, controlVoxelPosition.y, controlVoxelPosition.z, + // controlVoxelSize, COLORS[action].red, COLORS[action].green, COLORS[action].blue); } function mousePressEvent(event) { diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index b19d27946a..4e400670e5 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -82,10 +82,9 @@ function getAction(controlVoxel) { if (controlVoxel.red === COLORS[i].red && controlVoxel.green === COLORS[i].green && controlVoxel.blue === COLORS[i].blue) { - Voxels.eraseVoxel(controlVoxelPosition.x, - controlVoxelPosition.y, - controlVoxelPosition.z, - controlVoxelSize); + + // TODO: Fix this to use some mechanism other than voxels + //Voxels.eraseVoxel(controlVoxelPosition.x, controlVoxelPosition.y, controlVoxelPosition.z, controlVoxelSize); return parseInt(i); } } @@ -101,10 +100,9 @@ function update(event) { return; } - var controlVoxel = Voxels.getVoxelAt(controlVoxelPosition.x, - controlVoxelPosition.y, - controlVoxelPosition.z, - controlVoxelSize); + // TODO: Fix this to use some mechanism other than voxels + // Voxels.getVoxelAt(controlVoxelPosition.x, controlVoxelPosition.y, controlVoxelPosition.z, controlVoxelSize); + var controlVoxel = false; var action = getAction(controlVoxel); switch(action) { diff --git a/examples/botProceduralWayPoints.js b/examples/acScripts/botProceduralWayPoints.js similarity index 99% rename from examples/botProceduralWayPoints.js rename to examples/acScripts/botProceduralWayPoints.js index e20714bd27..b7c1fa1fe2 100644 --- a/examples/botProceduralWayPoints.js +++ b/examples/acScripts/botProceduralWayPoints.js @@ -20,7 +20,7 @@ // //For procedural walk animation -Script.include("libraries/globals.js"); +Script.include("../libraries/globals.js"); Script.include(HIFI_PUBLIC_BUCKET + "scripts/proceduralAnimationAPI.js"); var procAnimAPI = new ProcAnimAPI(); diff --git a/examples/bot_procedural.js b/examples/acScripts/bot_procedural.js similarity index 99% rename from examples/bot_procedural.js rename to examples/acScripts/bot_procedural.js index eec3c8906d..8b96ed36c2 100644 --- a/examples/bot_procedural.js +++ b/examples/acScripts/bot_procedural.js @@ -11,8 +11,8 @@ // //For procedural walk animation -Script.include("libraries/globals.js"); -Script.include(HIFI_PUBLIC_BUCKET + "scripts/proceduralAnimationAPI.js"); +Script.include("../libraries/globals.js"); +Script.include("proceduralAnimationAPI.js"); var procAnimAPI = new ProcAnimAPI(); diff --git a/examples/bot_randomExpression.js b/examples/acScripts/bot_randomExpression.js similarity index 98% rename from examples/bot_randomExpression.js rename to examples/acScripts/bot_randomExpression.js index 44d546e763..32bfb24065 100644 --- a/examples/bot_randomExpression.js +++ b/examples/acScripts/bot_randomExpression.js @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../libraries/globals.js"); function getRandomFloat(min, max) { return Math.random() * (max - min) + min; diff --git a/examples/proceduralAnimationAPI.js b/examples/acScripts/proceduralAnimationAPI.js similarity index 100% rename from examples/proceduralAnimationAPI.js rename to examples/acScripts/proceduralAnimationAPI.js diff --git a/examples/addVoxelOnMouseClickExample.js b/examples/addVoxelOnMouseClickExample.js deleted file mode 100644 index 4fa175577c..0000000000 --- a/examples/addVoxelOnMouseClickExample.js +++ /dev/null @@ -1,64 +0,0 @@ -// -// addVoxelOnMouseClickExample.js -// examples -// -// Created by Brad Hefta-Gaub on 2/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Camera and Voxels class to implement -// clicking on a voxel and adding a new voxel on the clicked on face -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -function mousePressEvent(event) { - print("mousePressEvent event.x,y=" + event.x + ", " + event.y); - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - if (intersection.intersects) { - - // Note: due to the current C++ "click on voxel" behavior, these values may be the animated color for the voxel - print("clicked on voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print("clicked on voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print("clicked on face=" + intersection.face); - print("clicked on distance=" + intersection.distance); - - var newVoxel = { - x: intersection.voxel.x, - y: intersection.voxel.y, - z: intersection.voxel.z, - s: intersection.voxel.s, - red: 255, - green: 0, - blue: 255 }; - - if (intersection.face == "MIN_X_FACE") { - newVoxel.x -= newVoxel.s; - } else if (intersection.face == "MAX_X_FACE") { - newVoxel.x += newVoxel.s; - } else if (intersection.face == "MIN_Y_FACE") { - newVoxel.y -= newVoxel.s; - } else if (intersection.face == "MAX_Y_FACE") { - newVoxel.y += newVoxel.s; - } else if (intersection.face == "MIN_Z_FACE") { - newVoxel.z -= newVoxel.s; - } else if (intersection.face == "MAX_Z_FACE") { - newVoxel.z += newVoxel.s; - } - - print("Voxels.setVoxel("+newVoxel.x + ", " - + newVoxel.y + ", " + newVoxel.z + ", " + newVoxel.s + ", " - + newVoxel.red + ", " + newVoxel.green + ", " + newVoxel.blue + ")" ); - - Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); - } -} - -Controller.mousePressEvent.connect(mousePressEvent); - -function scriptEnding() { -} -Script.scriptEnding.connect(scriptEnding); diff --git a/examples/avatarCollision.js b/examples/avatarCollision.js deleted file mode 100644 index ce13daa50d..0000000000 --- a/examples/avatarCollision.js +++ /dev/null @@ -1,72 +0,0 @@ -// -// avatarCollision.js -// examples -// -// Created by Andrew Meadows on 2014-04-09 -// Copyright 2014 High Fidelity, Inc. -// -// Play a sound on collisions with your avatar -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var SOUND_TRIGGER_CLEAR = 1000; // milliseconds -var SOUND_TRIGGER_DELAY = 200; // milliseconds -var soundExpiry = 0; -var DateObj = new Date(); - -var audioOptions = { - volume: 0.5, - position: { x: 0, y: 0, z: 0 } -} - -var hitSounds = new Array(); -hitSounds[0] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit1.raw"); -hitSounds[1] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit2.raw"); -hitSounds[2] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit3.raw"); -hitSounds[3] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit4.raw"); -hitSounds[4] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit5.raw"); -hitSounds[5] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit6.raw"); -hitSounds[6] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit7.raw"); -hitSounds[7] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit8.raw"); -hitSounds[8] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit9.raw"); -hitSounds[9] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit10.raw"); -hitSounds[10] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit11.raw"); -hitSounds[11] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit12.raw"); -hitSounds[12] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit13.raw"); -hitSounds[13] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit14.raw"); -hitSounds[14] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit15.raw"); -hitSounds[15] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit16.raw"); -hitSounds[16] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit17.raw"); -hitSounds[17] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit18.raw"); -hitSounds[18] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit19.raw"); -hitSounds[19] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit20.raw"); -hitSounds[20] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit21.raw"); -hitSounds[21] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit22.raw"); - -function playHitSound(mySessionID, theirSessionID, collision) { - var now = new Date(); - var msec = now.getTime(); - if (msec > soundExpiry) { - // this is a new contact --> play a new sound - var soundIndex = Math.floor((Math.random() * hitSounds.length) % hitSounds.length); - audioOptions.position = collision.contactPoint; - Audio.playSound(hitSounds[soundIndex], audioOptions); - - // bump the expiry - soundExpiry = msec + SOUND_TRIGGER_CLEAR; - - // log the collision info - Uuid.print("my sessionID = ", mySessionID); - Uuid.print(" their sessionID = ", theirSessionID); - Vec3.print(" penetration = ", collision.penetration); - Vec3.print(" contactPoint = ", collision.contactPoint); - } else { - // this is a recurring contact --> continue to delay sound trigger - soundExpiry = msec + SOUND_TRIGGER_DELAY; - } -} -MyAvatar.collisionWithAvatar.connect(playHitSound); diff --git a/examples/avatarLocalLight.js b/examples/avatarLocalLight.js deleted file mode 100644 index b1f31888d8..0000000000 --- a/examples/avatarLocalLight.js +++ /dev/null @@ -1,139 +0,0 @@ -// -// avatarLocalLight.js -// -// Created by Tony Peng on July 2nd, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// Set the local light direction and color on the avatar -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var localLightDirections = [ {x: 1.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 1.0} ]; -var localLightColors = [ {x: 0.4, y:0.335, z: 0.266}, {x: 0.4, y:0.335, z: 0.266} ]; - -var currentSelection = 0; -var currentNumLights = 2; -var maxNumLights = 2; -var currentNumAvatars = 0; -var changeDelta = 0.1; -var lightsDirty = true; - -function keyPressEvent(event) { - - var choice = parseInt(event.text); - - if (event.text == "1") { - currentSelection = 0; - print("light election = " + currentSelection); - } - else if (event.text == "2" ) { - currentSelection = 1; - print("light selection = " + currentSelection); - } - else if (event.text == "3" ) { - currentSelection = 2; - print("light selection = " + currentSelection); - } - else if (event.text == "4" ) { - currentSelection = 3; - print("light selection = " + currentSelection); - } - else if (event.text == "5" ) { - localLightColors[currentSelection].x += changeDelta; - if ( localLightColors[currentSelection].x > 1.0) { - localLightColors[currentSelection].x = 0.0; - } - - lightsDirty = true; - print("CHANGE RED light " + currentSelection + " color (" + localLightColors[currentSelection].x + ", " + localLightColors[currentSelection].y + ", " + localLightColors[currentSelection].z + " )" ); - } - else if (event.text == "6" ) { - localLightColors[currentSelection].y += changeDelta; - if ( localLightColors[currentSelection].y > 1.0) { - localLightColors[currentSelection].y = 0.0; - } - - lightsDirty = true; - print("CHANGE GREEN light " + currentSelection + " color (" + localLightColors[currentSelection].x + ", " + localLightColors[currentSelection].y + ", " + localLightColors[currentSelection].z + " )" ); - } - else if (event.text == "7" ) { - localLightColors[currentSelection].z += changeDelta; - if ( localLightColors[currentSelection].z > 1.0) { - localLightColors[currentSelection].z = 0.0; - } - - lightsDirty = true; - print("CHANGE BLUE light " + currentSelection + " color (" + localLightColors[currentSelection].x + ", " + localLightColors[currentSelection].y + ", " + localLightColors[currentSelection].z + " )" ); - } - else if (event.text == "8" ) { - localLightDirections[currentSelection].x += changeDelta; - if (localLightDirections[currentSelection].x > 1.0) { - localLightDirections[currentSelection].x = -1.0; - } - - lightsDirty = true; - print("PLUS X light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); - } - else if (event.text == "9" ) { - localLightDirections[currentSelection].x -= changeDelta; - if (localLightDirections[currentSelection].x < -1.0) { - localLightDirections[currentSelection].x = 1.0; - } - - lightsDirty = true; - print("MINUS X light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); - } - else if (event.text == "0" ) { - localLightDirections[currentSelection].y += changeDelta; - if (localLightDirections[currentSelection].y > 1.0) { - localLightDirections[currentSelection].y = -1.0; - } - - lightsDirty = true; - print("PLUS Y light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); - } - else if (event.text == "-" ) { - localLightDirections[currentSelection].y -= changeDelta; - if (localLightDirections[currentSelection].y < -1.0) { - localLightDirections[currentSelection].y = 1.0; - } - - lightsDirty = true; - print("MINUS Y light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); - } - else if (event.text == "," ) { - if (currentNumLights + 1 <= maxNumLights) { - ++currentNumLights; - lightsDirty = true; - } - - print("ADD LIGHT, number of lights " + currentNumLights); - } - else if (event.text == "." ) { - if (currentNumLights - 1 >= 0 ) { - --currentNumLights; - lightsDirty = true; - } - - print("REMOVE LIGHT, number of lights " + currentNumLights); - } -} - -function updateLocalLights() -{ - if (lightsDirty) { - var localLights = []; - for (var i = 0; i < currentNumLights; i++) { - localLights.push({ direction: localLightDirections[i], color: localLightColors[i] }); - } - AvatarManager.setLocalLights(localLights); - lightsDirty = false; - } -} - -// main -Script.update.connect(updateLocalLights); -Controller.keyPressEvent.connect(keyPressEvent); - diff --git a/examples/bot.js b/examples/bot.js deleted file mode 100644 index aadd038eb6..0000000000 --- a/examples/bot.js +++ /dev/null @@ -1,233 +0,0 @@ -// -// bot.js -// examples -// -// Created by Stephen Birarda on 2/20/14. -// Modified by Philip on 3/3/14 -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates an NPC avatar. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -function getRandomFloat(min, max) { - return Math.random() * (max - min) + min; -} - -function getRandomInt (min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function printVector(string, vector) { - print(string + " " + vector.x + ", " + vector.y + ", " + vector.z); -} - -var CHANCE_OF_MOVING = 0.005; -var CHANCE_OF_SOUND = 0.005; -var CHANCE_OF_HEAD_TURNING = 0.05; -var CHANCE_OF_BIG_MOVE = 0.1; -var CHANCE_OF_WAVING = 0.009; - -var shouldReceiveVoxels = true; -var VOXEL_FPS = 60.0; -var lastVoxelQueryTime = 0.0; - -var isMoving = false; -var isTurningHead = false; -var isPlayingAudio = false; -var isWaving = false; -var waveFrequency = 0.0; -var waveAmplitude = 0.0; - -var X_MIN = 5.0; -var X_MAX = 15.0; -var Z_MIN = 5.0; -var Z_MAX = 15.0; -var Y_PELVIS = 1.0; -var SPINE_JOINT_NUMBER = 13; -var SHOULDER_JOINT_NUMBER = 17; -var ELBOW_JOINT_NUMBER = 18; -var JOINT_R_HIP = 1; -var JOINT_R_KNEE = 2; - -var MOVE_RANGE_SMALL = 0.5; -var MOVE_RANGE_BIG = Math.max(X_MAX - X_MIN, Z_MAX - Z_MIN) / 2.0; -var TURN_RANGE = 70.0; -var STOP_TOLERANCE = 0.05; -var MOVE_RATE = 0.05; -var TURN_RATE = 0.15; -var PITCH_RATE = 0.20; -var PITCH_RANGE = 30.0; - -var firstPosition = { x: getRandomFloat(X_MIN, X_MAX), y: Y_PELVIS, z: getRandomFloat(Z_MIN, Z_MAX) }; -var targetPosition = { x: 0, y: 0, z: 0 }; -var targetDirection = { x: 0, y: 0, z: 0, w: 0 }; -var currentDirection = { x: 0, y: 0, z: 0, w: 0 }; -var targetHeadPitch = 0.0; - -var walkFrequency = 5.0; -var walkAmplitude = 45.0; - -var cumulativeTime = 0.0; - -var sounds = []; -loadSounds(); - -function clamp(val, min, max){ - return Math.max(min, Math.min(max, val)) -} - -// Play a random sound from a list of conversational audio clips -var AVERAGE_AUDIO_LENGTH = 8000; -function playRandomSound() { - if (!Agent.isPlayingAvatarSound) { - var whichSound = Math.floor((Math.random() * sounds.length) % sounds.length); - Agent.playAvatarSound(sounds[whichSound]); - } -} - -// pick an integer between 1 and 20 for the face model for this bot -botNumber = getRandomInt(1, 100); - -if (botNumber <= 20) { - newFaceFilePrefix = "bot" + botNumber; - newBodyFilePrefix = "defaultAvatar_body" -} else { - if (botNumber <= 40) { - newFaceFilePrefix = "superhero"; - } else if (botNumber <= 60) { - newFaceFilePrefix = "amber"; - } else if (botNumber <= 80) { - newFaceFilePrefix = "ron"; - } else { - newFaceFilePrefix = "angie"; - } - - newBodyFilePrefix = "bot" + botNumber; -} - -// set the face model fst using the bot number -// there is no need to change the body model - we're using the default -Avatar.faceModelURL = HIFI_PUBLIC_BUCKET + "meshes/" + newFaceFilePrefix + ".fst"; -Avatar.skeletonModelURL = HIFI_PUBLIC_BUCKET + "meshes/" + newBodyFilePrefix + ".fst"; -Avatar.billboardURL = HIFI_PUBLIC_BUCKET + "meshes/billboards/bot" + botNumber + ".png"; - -Agent.isAvatar = true; -Agent.isListeningToAudioStream = true; - -// change the avatar's position to the random one -Avatar.position = firstPosition; -printVector("New bot, position = ", Avatar.position); - -function stopWaving() { - isWaving = false; - Avatar.clearJointData(SHOULDER_JOINT_NUMBER); - Avatar.clearJointData(ELBOW_JOINT_NUMBER); - Avatar.clearJointData(SPINE_JOINT_NUMBER); -} - -function keepWalking() { - Avatar.setJointData(JOINT_R_HIP, Quat.fromPitchYawRollDegrees(walkAmplitude * Math.sin(cumulativeTime * walkFrequency), 0.0, 0.0)); - Avatar.setJointData(JOINT_R_KNEE, Quat.fromPitchYawRollDegrees(walkAmplitude * Math.sin(cumulativeTime * walkFrequency), 0.0, 0.0)); -} - -function stopWalking() { - Avatar.clearJointData(JOINT_R_HIP); - Avatar.clearJointData(JOINT_R_KNEE); -} - -function updateBehavior(deltaTime) { - - cumulativeTime += deltaTime; - - // Hack - right now you need to set the avatar position a bit after the avatar is made to make sure it's there. - - if (CHANCE_OF_MOVING == 0.000) { - Avatar.position = firstPosition; - } - - if (shouldReceiveVoxels && ((cumulativeTime - lastVoxelQueryTime) > (1.0 / VOXEL_FPS))) { - VoxelViewer.setPosition(Avatar.position); - VoxelViewer.setOrientation(Avatar.orientation); - VoxelViewer.queryOctree(); - lastVoxelQueryTime = cumulativeTime; - /* - if (Math.random() < (1.0 / VOXEL_FPS)) { - print("Voxels in view = " + VoxelViewer.getOctreeElementsCount()); - }*/ - } - - if (!isWaving && (Math.random() < CHANCE_OF_WAVING)) { - isWaving = true; - waveFrequency = 3.0 + Math.random() * 5.0; - waveAmplitude = 5.0 + Math.random() * 60.0; - Script.setTimeout(stopWaving, 1000 + Math.random() * 2000); - Avatar.setJointData(ELBOW_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 45, 0.0)); // Initially turn the palm outward - } else if (isWaving) { - Avatar.setJointData(SHOULDER_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, 60 + waveAmplitude * Math.sin((cumulativeTime - 0.25) * waveFrequency))); - Avatar.setJointData(ELBOW_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, 25 + waveAmplitude/2.0 * Math.sin(cumulativeTime * 1.2 * waveFrequency))); - Avatar.setJointData(SPINE_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, 60 + waveAmplitude/4.0 * Math.sin(cumulativeTime * waveFrequency))); - - } - - - if (Math.random() < CHANCE_OF_SOUND) { - playRandomSound(); - } - - if (!isTurningHead && (Math.random() < CHANCE_OF_HEAD_TURNING)) { - targetHeadPitch = getRandomFloat(-PITCH_RANGE, PITCH_RANGE); - isTurningHead = true; - } else { - Avatar.headPitch = Avatar.headPitch + (targetHeadPitch - Avatar.headPitch) * PITCH_RATE; - if (Math.abs(Avatar.headPitch - targetHeadPitch) < STOP_TOLERANCE) { - isTurningHead = false; - } - } - if (!isMoving && (Math.random() < CHANCE_OF_MOVING)) { - // Set new target location - targetDirection = Quat.multiply(Avatar.orientation, Quat.angleAxis(getRandomFloat(-TURN_RANGE, TURN_RANGE), { x:0, y:1, z:0 })); - var front = Quat.getFront(targetDirection); - if (Math.random() < CHANCE_OF_BIG_MOVE) { - targetPosition = Vec3.sum(Avatar.position, Vec3.multiply(front, getRandomFloat(0.0, MOVE_RANGE_BIG))); - } else { - targetPosition = Vec3.sum(Avatar.position, Vec3.multiply(front, getRandomFloat(0.0, MOVE_RANGE_SMALL))); - } - targetPosition.x = clamp(targetPosition.x, X_MIN, X_MAX); - targetPosition.z = clamp(targetPosition.z, Z_MIN, Z_MAX); - targetPosition.y = Y_PELVIS; - - isMoving = true; - } else if (isMoving) { - keepWalking(); - Avatar.position = Vec3.sum(Avatar.position, Vec3.multiply(Vec3.subtract(targetPosition, Avatar.position), MOVE_RATE)); - Avatar.orientation = Quat.mix(Avatar.orientation, targetDirection, TURN_RATE); - if (Vec3.length(Vec3.subtract(Avatar.position, targetPosition)) < STOP_TOLERANCE) { - isMoving = false; - stopWalking(); - } - } -} - -Script.update.connect(updateBehavior); - -function loadSounds() { - var sound_filenames = ["AB1.raw", "Anchorman2.raw", "B1.raw", "B1.raw", "Bale1.raw", "Bandcamp.raw", - "Big1.raw", "Big2.raw", "Brian1.raw", "Buster1.raw", "CES1.raw", "CES2.raw", "CES3.raw", "CES4.raw", - "Carrie1.raw", "Carrie3.raw", "Charlotte1.raw", "EN1.raw", "EN2.raw", "EN3.raw", "Eugene1.raw", "Francesco1.raw", - "Italian1.raw", "Japanese1.raw", "Leigh1.raw", "Lucille1.raw", "Lucille2.raw", "MeanGirls.raw", "Murray2.raw", - "Nigel1.raw", "PennyLane.raw", "Pitt1.raw", "Ricardo.raw", "SN.raw", "Sake1.raw", "Samantha1.raw", "Samantha2.raw", - "Spicoli1.raw", "Supernatural.raw", "Swearengen1.raw", "TheDude.raw", "Tony.raw", "Triumph1.raw", "Uma1.raw", - "Walken1.raw", "Walken2.raw", "Z1.raw", "Z2.raw" - ]; - - var SOUND_BASE_URL = HIFI_PUBLIC_BUCKET + "sounds/Cocktail+Party+Snippets/Raws/"; - - for (var i = 0; i < sound_filenames.length; i++) { - sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i])); - } -} diff --git a/examples/clipboardExample.js b/examples/clipboardExample.js deleted file mode 100644 index 0b6371e2b7..0000000000 --- a/examples/clipboardExample.js +++ /dev/null @@ -1,162 +0,0 @@ -// -// clipboardExample.js -// examples -// -// Created by Brad Hefta-Gaub on 1/28/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Clipboard class -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var selectedVoxel = { x: 0, y: 0, z: 0, s: 0 }; -var selectedSize = 4; - -function setupMenus() { - // hook up menus - Menu.menuItemEvent.connect(menuItemEvent); - - // delete the standard application menu item - Menu.removeMenuItem("Edit", "Cut"); - Menu.removeMenuItem("Edit", "Copy"); - Menu.removeMenuItem("Edit", "Paste"); - Menu.removeMenuItem("Edit", "Delete"); - Menu.removeMenuItem("Edit", "Nudge"); - Menu.removeMenuItem("Edit", "Replace from File"); - Menu.removeMenuItem("File", "Export Voxels"); - Menu.removeMenuItem("File", "Import Voxels"); - - // delete the standard application menu item - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Cut", shortcutKey: "CTRL+X", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Copy", shortcutKey: "CTRL+C", afterItem: "Cut" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste", shortcutKey: "CTRL+V", afterItem: "Copy" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Nudge", shortcutKey: "CTRL+N", afterItem: "Paste" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Replace from File", shortcutKey: "CTRL+R", afterItem: "Nudge" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", shortcutKeyEvent: { text: "backspace" }, afterItem: "Nudge" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Voxels", shortcutKey: "CTRL+E", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Voxels", shortcutKey: "CTRL+I", afterItem: "Export Voxels" }); -} - -function menuItemEvent(menuItem) { - var debug = true; - if (debug) { - print("menuItemEvent " + menuItem); - } - - // Note: this sample uses Alt+ as the key codes for these clipboard items - if (menuItem == "Copy") { - print("copying..."); - Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Cut") { - print("cutting..."); - Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Paste") { - print("pasting..."); - Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Delete") { - print("deleting..."); - Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Export Voxels") { - print("export"); - Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Import Voxels") { - print("import"); - Clipboard.importVoxels(); - } - if (menuItem == "Nudge") { - print("nudge"); - Clipboard.nudgeVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s, { x: -1, y: 0, z: 0 }); - } - if (menuItem == "Replace from File") { - var filename = Window.browse("Select file to load replacement", "", "Voxel Files (*.png *.svo *.schematic)"); - if (filename) { - Clipboard.importVoxel(filename, selectedVoxel); - } - } -} - -var selectCube = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0}, - size: selectedSize, - color: { red: 255, green: 255, blue: 0}, - alpha: 1, - solid: false, - visible: false, - lineWidth: 4 - }); - - -function mouseMoveEvent(event) { - - var pickRay = Camera.computePickRay(event.x, event.y); - - var debug = false; - if (debug) { - print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y); - print("called Camera.computePickRay()"); - print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z); - print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z); - } - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - if (debug) { - print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print("intersection face=" + intersection.face); - print("intersection distance=" + intersection.distance); - print("intersection intersection.x/y/z=" + intersection.intersection.x + ", " - + intersection.intersection.y + ", " + intersection.intersection.z); - } - - - - var x = Math.floor(intersection.voxel.x / selectedSize) * selectedSize; - var y = Math.floor(intersection.voxel.y / selectedSize) * selectedSize; - var z = Math.floor(intersection.voxel.z / selectedSize) * selectedSize; - selectedVoxel = { x: x, y: y, z: z, s: selectedSize }; - Overlays.editOverlay(selectCube, { position: selectedVoxel, size: selectedSize, visible: true } ); - } else { - Overlays.editOverlay(selectCube, { visible: false } ); - selectedVoxel = { x: 0, y: 0, z: 0, s: 0 }; - } -} - -Controller.mouseMoveEvent.connect(mouseMoveEvent); - -function wheelEvent(event) { - var debug = false; - if (debug) { - print("wheelEvent"); - print(" event.x,y=" + event.x + ", " + event.y); - print(" event.delta=" + event.delta); - print(" event.orientation=" + event.orientation); - print(" event.isLeftButton=" + event.isLeftButton); - print(" event.isRightButton=" + event.isRightButton); - print(" event.isMiddleButton=" + event.isMiddleButton); - print(" event.isShifted=" + event.isShifted); - print(" event.isControl=" + event.isControl); - print(" event.isMeta=" + event.isMeta); - print(" event.isAlt=" + event.isAlt); - } -} - -Controller.wheelEvent.connect(wheelEvent); - -function scriptEnding() { - Overlays.deleteOverlay(selectCube); -} - -Script.scriptEnding.connect(scriptEnding); - -setupMenus(); \ No newline at end of file diff --git a/examples/gamepad.js b/examples/controllers/gamepad/gamepad.js similarity index 98% rename from examples/gamepad.js rename to examples/controllers/gamepad/gamepad.js index cc275e6267..c28747216d 100644 --- a/examples/gamepad.js +++ b/examples/controllers/gamepad/gamepad.js @@ -75,7 +75,7 @@ var warpSphere = Overlays.addOverlay("sphere", { var WARP_LINE_HEIGHT = 10; var warpLine = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z:0 }, + start: { x: 0, y: 0, z:0 }, end: { x: 0, y: 0, z: 0 }, color: { red: 0, green: 255, blue: 255}, alpha: 1, @@ -116,7 +116,7 @@ function updateWarp() { direction: { x: 0, y: -1, z: 0 } }; - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects && intersection.distance < WARP_PICK_MAX_DISTANCE) { // Warp 1 meter above the object - this is an approximation @@ -131,7 +131,7 @@ function updateWarp() { visible: true, }); Overlays.editOverlay(warpLine, { - position: warpPosition, + start: warpPosition, end: Vec3.sum(warpPosition, { x: 0, y: WARP_LINE_HEIGHT, z: 0 }), visible: true, }); diff --git a/examples/airGuitar.js b/examples/controllers/hydra/airGuitar.js similarity index 97% rename from examples/airGuitar.js rename to examples/controllers/hydra/airGuitar.js index 5a62ee3e7b..6d3d374f3a 100644 --- a/examples/airGuitar.js +++ b/examples/controllers/hydra/airGuitar.js @@ -10,7 +10,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); function length(v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); @@ -73,7 +73,7 @@ var soundPlaying = false; var selectorPressed = false; var position; -MyAvatar.attach(guitarModel, "Hips", {x: -0.0, y: -0.0, z: 0.0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.0); +MyAvatar.attach(guitarModel, "Hips", {x: -0.2, y: 0.0, z: 0.1}, Quat.fromPitchYawRollDegrees(90, 00, 90), 1.0); function checkHands(deltaTime) { for (var palm = 0; palm < 2; palm++) { diff --git a/examples/drumStick.js b/examples/controllers/hydra/drumStick.js similarity index 98% rename from examples/drumStick.js rename to examples/controllers/hydra/drumStick.js index 88ffa36c50..14e1413742 100644 --- a/examples/drumStick.js +++ b/examples/controllers/hydra/drumStick.js @@ -10,7 +10,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); function length(v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); diff --git a/examples/frisbee.js b/examples/controllers/hydra/frisbee.js similarity index 95% rename from examples/frisbee.js rename to examples/controllers/hydra/frisbee.js index cf271f4f04..a9fd74910d 100644 --- a/examples/frisbee.js +++ b/examples/controllers/hydra/frisbee.js @@ -15,8 +15,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); -Script.include("libraries/toolBars.js"); +Script.include("../../libraries/globals.js"); +Script.include("../../libraries/toolBars.js"); const LEFT_PALM = 0; const LEFT_TIP = 1; @@ -192,15 +192,18 @@ function cleanupFrisbees() { } function checkControllerSide(hand) { + // print("cCS"); // If I don't currently have a frisbee in my hand, then try to catch closest one if (!hand.holdingFrisbee && hand.grabButtonPressed()) { var closestEntity = Entities.findClosestEntity(hand.palmPosition(), CATCH_RADIUS); var modelUrl = Entities.getEntityProperties(closestEntity).modelURL; + print("lol2"+closestEntity.isKnownID); if (closestEntity.isKnownID && validFrisbeeURL(Entities.getEntityProperties(closestEntity).modelURL)) { + print("lol"); Entities.editEntity(closestEntity, {modelScale: 1, inHand: true, position: hand.holdPosition(), shouldDie: true}); Entities.deleteEntity(closestEntity); debugPrint(hand.message + " HAND- CAUGHT SOMETHING!!"); - + print("lol"); var properties = { type: "Model", position: hand.holdPosition(), @@ -210,8 +213,8 @@ function checkControllerSide(hand) { dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS }, damping: 0.999, modelURL: modelUrl, - modelScale: FRISBEE_MODEL_SCALE, - modelRotation: hand.holdRotation(), + scale: FRISBEE_MODEL_SCALE, + rotation: hand.holdRotation(), lifetime: FRISBEE_LIFETIME }; @@ -235,10 +238,10 @@ function checkControllerSide(hand) { gravity: { x: 0, y: 0, z: 0}, inHand: true, dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS }, - damping: 0.999, + damping: 0, modelURL: frisbeeURL(), - modelScale: FRISBEE_MODEL_SCALE, - modelRotation: hand.holdRotation(), + scale: FRISBEE_MODEL_SCALE, + rotation: hand.holdRotation(), lifetime: FRISBEE_LIFETIME }; @@ -270,7 +273,7 @@ function checkControllerSide(hand) { inHand: false, lifetime: FRISBEE_LIFETIME, gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0}, - modelRotation: hand.holdRotation() + rotation: hand.holdRotation() }; Entities.editEntity(hand.entity, properties); @@ -304,7 +307,7 @@ function hydraCheck() { var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); - return hydrasConnected; + return true;//hydrasConnected; } function checkController(deltaTime) { @@ -314,6 +317,7 @@ function checkController(deltaTime) { } // this is expected for hydras if (hydraCheck()) { +///print("testrr "); checkControllerSide(leftHand); checkControllerSide(rightHand); } @@ -333,7 +337,7 @@ function controlFrisbees(deltaTime) { killSimulations.push(frisbee); continue; } - Entities.editEntity(simulatedFrisbees[frisbee], {modelRotation: Quat.multiply(properties.modelRotation, Quat.fromPitchYawRollDegrees(0, speed * deltaTime * SPIN_MULTIPLIER, 0))}); + Entities.editEntity(simulatedFrisbees[frisbee], {rotation: Quat.multiply(properties.modelRotation, Quat.fromPitchYawRollDegrees(0, speed * deltaTime * SPIN_MULTIPLIER, 0))}); } for (var i = killSimulations.length - 1; i >= 0; i--) { diff --git a/examples/gun.js b/examples/controllers/hydra/gun.js similarity index 60% rename from examples/gun.js rename to examples/controllers/hydra/gun.js index 2386e61539..b60a70ca36 100644 --- a/examples/gun.js +++ b/examples/controllers/hydra/gun.js @@ -14,7 +14,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); function getRandomFloat(min, max) { return Math.random() * (max - min) + min; @@ -26,14 +26,19 @@ var yawFromMouse = 0; var pitchFromMouse = 0; var isMouseDown = false; -var BULLET_VELOCITY = 5.0; +var BULLET_VELOCITY = 20.0; var MIN_THROWER_DELAY = 1000; var MAX_THROWER_DELAY = 1000; var LEFT_BUTTON_3 = 3; var RELOAD_INTERVAL = 5; +var KICKBACK_ANGLE = 15; +var elbowKickAngle = 0.0; +var rotationBeforeKickback; + var showScore = false; + // Load some sound to use for loading and firing var fireSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw"); var loadSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw"); @@ -48,10 +53,11 @@ var audioOptions = { } var shotsFired = 0; - var shotTime = new Date(); -// initialize our triggers +var activeControllers = 0; + +// initialize our controller triggers var triggerPulled = new Array(); var numberOfTriggers = Controller.getNumberOfTriggers(); for (t = 0; t < numberOfTriggers; t++) { @@ -59,9 +65,11 @@ for (t = 0; t < numberOfTriggers; t++) { } var isLaunchButtonPressed = false; - var score = 0; +var bulletID = false; +var targetID = false; + // Create a reticle image in center of screen var screenSize = Controller.getViewportDimensions(); var reticle = Overlays.addOverlay("image", { @@ -74,6 +82,16 @@ var reticle = Overlays.addOverlay("image", { alpha: 1 }); +var offButton = Overlays.addOverlay("image", { + x: screenSize.x - 48, + y: 96, + width: 32, + height: 32, + imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", + color: { red: 255, green: 255, blue: 255}, + alpha: 1 + }); + if (showScore) { var text = Overlays.addOverlay("text", { x: screenSize.x / 2 - 100, @@ -95,18 +113,20 @@ function printVector(string, vector) { } function shootBullet(position, velocity) { - var BULLET_SIZE = 0.01; - var BULLET_LIFETIME = 20.0; + var BULLET_SIZE = 0.07; + var BULLET_LIFETIME = 10.0; var BULLET_GRAVITY = -0.02; - Entities.addEntity( + bulletID = Entities.addEntity( { type: "Sphere", position: position, dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, - color: { red: 10, green: 10, blue: 10 }, + color: { red: 255, green: 0, blue: 0 }, velocity: velocity, lifetime: BULLET_LIFETIME, - gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, - damping: 0 }); + gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, + ignoreCollisions: false, + collisionsWillMove: true + }); // Play firing sounds audioOptions.position = position; @@ -115,36 +135,45 @@ function shootBullet(position, velocity) { if ((shotsFired % RELOAD_INTERVAL) == 0) { Audio.playSound(loadSound, audioOptions); } + + // Kickback the arm + rotationBeforeKickback = MyAvatar.getJointRotation("LeftForeArm"); + var armRotation = MyAvatar.getJointRotation("LeftForeArm"); + armRotation = Quat.multiply(armRotation, Quat.fromPitchYawRollDegrees(0.0, 0.0, KICKBACK_ANGLE)); + MyAvatar.setJointData("LeftForeArm", armRotation); + elbowKickAngle = KICKBACK_ANGLE; } function shootTarget() { - var TARGET_SIZE = 0.25; - var TARGET_GRAVITY = -0.6; + var TARGET_SIZE = 0.50; + var TARGET_GRAVITY = -0.25; var TARGET_LIFETIME = 300.0; - var TARGET_UP_VELOCITY = 3.0; - var TARGET_FWD_VELOCITY = 5.0; + var TARGET_UP_VELOCITY = 0.5; + var TARGET_FWD_VELOCITY = 1.0; var DISTANCE_TO_LAUNCH_FROM = 3.0; + var ANGLE_RANGE_FOR_LAUNCH = 20.0; var camera = Camera.getPosition(); //printVector("camera", camera); - var targetDirection = Quat.angleAxis(getRandomFloat(-20.0, 20.0), { x:0, y:1, z:0 }); + var targetDirection = Quat.angleAxis(getRandomFloat(-ANGLE_RANGE_FOR_LAUNCH, ANGLE_RANGE_FOR_LAUNCH), { x:0, y:1, z:0 }); targetDirection = Quat.multiply(Camera.getOrientation(), targetDirection); var forwardVector = Quat.getFront(targetDirection); - //printVector("forwardVector", forwardVector); + var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_TO_LAUNCH_FROM)); - //printVector("newPosition", newPosition); + var velocity = Vec3.multiply(forwardVector, TARGET_FWD_VELOCITY); velocity.y += TARGET_UP_VELOCITY; - //printVector("velocity", velocity); - - Entities.addEntity( - { type: "Sphere", + + targetID = Entities.addEntity( + { type: "Box", position: newPosition, dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, color: { red: 0, green: 200, blue: 200 }, + //angularVelocity: { x: 1, y: 0, z: 0 }, velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, lifetime: TARGET_LIFETIME, - damping: 0.99 }); + damping: 0.0001, + collisionsWillMove: true }); // Record start time shotTime = new Date(); @@ -156,38 +185,26 @@ function shootTarget() { -function entityCollisionWithVoxel(entity, voxel, collision) { - var HOLE_SIZE = 0.125; - var entityProperties = Entities.getEntityProperties(entity); - var position = entityProperties.position; - Entities.deleteEntity(entity); - // Make a hole in this voxel - //Vec3.print("voxel penetration", collision.penetration); - //Vec3.print("voxel contactPoint", collision.contactPoint); - Voxels.eraseVoxel(collision.contactPoint.x, collision.contactPoint.y, collision.contactPoint.z, HOLE_SIZE); - audioOptions.position = collision.contactPoint; - Audio.playSound(impactSound, audioOptions); -} - function entityCollisionWithEntity(entity1, entity2, collision) { - score++; - if (showScore) { - Overlays.editOverlay(text, { text: "Score: " + score } ); - } - - // Sort out which entity is which - // Record shot time - var endTime = new Date(); - var msecs = endTime.valueOf() - shotTime.valueOf(); - //print("hit, msecs = " + msecs); - //Vec3.print("penetration = ", collision.penetration); - //Vec3.print("contactPoint = ", collision.contactPoint); - Entities.deleteEntity(entity1); - Entities.deleteEntity(entity2); - // play the sound near the camera so the shooter can hear it - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(targetHitSound, audioOptions); + if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) && + ((entity2.id == bulletID.id) || (entity2.id == targetID.id))) { + score++; + if (showScore) { + Overlays.editOverlay(text, { text: "Score: " + score } ); + } + + // We will delete the bullet and target in 1/2 sec, but for now we can see them bounce! + Script.setTimeout(deleteBulletAndTarget, 500); + + // Turn the target and the bullet white + Entities.editEntity(entity1, { color: { red: 255, green: 255, blue: 255 }}); + Entities.editEntity(entity2, { color: { red: 255, green: 255, blue: 255 }}); + + // play the sound near the camera so the shooter can hear it + audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); + Audio.playSound(targetHitSound, audioOptions); + } } function keyPressEvent(event) { @@ -199,32 +216,94 @@ function keyPressEvent(event) { shootFromMouse(); } else if (event.text == "r") { playLoadSound(); + } else if (event.text == "s") { + // Hit this key to dump a posture from hydra to log + Quat.print("arm = ", MyAvatar.getJointRotation("LeftArm")); + Quat.print("forearm = ", MyAvatar.getJointRotation("LeftForeArm")); + Quat.print("hand = ", MyAvatar.getJointRotation("LeftHand")); + } } function playLoadSound() { audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); Audio.playSound(loadSound, audioOptions); + // Raise arm to firing posture + takeFiringPose(); } -//MyAvatar.attach(gunModel, "RightHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); -MyAvatar.attach(gunModel, "LeftHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); +function clearPose() { + MyAvatar.clearJointData("LeftForeArm"); + MyAvatar.clearJointData("LeftArm"); + MyAvatar.clearJointData("LeftHand"); +} + +function deleteBulletAndTarget() { + Entities.deleteEntity(bulletID); + Entities.deleteEntity(targetID); + bulletID = false; + targetID = false; +} + +function takeFiringPose() { + clearPose(); + if (Controller.getNumberOfSpatialControls() == 0) { + MyAvatar.setJointData("LeftForeArm", {x: -0.251919, y: -0.0415449, z: 0.499487, w: 0.827843}); + MyAvatar.setJointData("LeftArm", { x: 0.470196, y: -0.132559, z: 0.494033, w: 0.719219}); + MyAvatar.setJointData("LeftHand", { x: -0.0104815, y: -0.110551, z: -0.352111, w: 0.929333}); + } +} + +//MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(-0, -160, -79), 0.20); +MyAvatar.attach(gunModel, "LeftHand", {x:-0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(0, 0, 79), 0.20); // Give a bit of time to load before playing sound Script.setTimeout(playLoadSound, 2000); function update(deltaTime) { + if (bulletID && !bulletID.isKnownID) { + print("Trying to identify bullet"); + bulletID = Entities.identifyEntity(bulletID); + } + if (targetID && !targetID.isKnownID) { + targetID = Entities.identifyEntity(targetID); + } // Check for mouseLook movement, update rotation // rotate body yaw for yaw received from mouse var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMouse, z: 0 } )); - MyAvatar.orientation = newOrientation; + //MyAvatar.orientation = newOrientation; yawFromMouse = 0; // apply pitch from mouse var newPitch = MyAvatar.headPitch + pitchFromMouse; - MyAvatar.headPitch = newPitch; + //MyAvatar.headPitch = newPitch; pitchFromMouse = 0; + + if (activeControllers == 0) { + if (Controller.getNumberOfSpatialControls() > 0) { + activeControllers = Controller.getNumberOfSpatialControls(); + clearPose(); + } + } + + var KICKBACK_DECAY_RATE = 0.125; + if (elbowKickAngle > 0.0) { + if (elbowKickAngle > 0.5) { + var newAngle = elbowKickAngle * KICKBACK_DECAY_RATE; + elbowKickAngle -= newAngle; + var armRotation = MyAvatar.getJointRotation("LeftForeArm"); + armRotation = Quat.multiply(armRotation, Quat.fromPitchYawRollDegrees(0.0, 0.0, -newAngle)); + MyAvatar.setJointData("LeftForeArm", armRotation); + } else { + MyAvatar.setJointData("LeftForeArm", rotationBeforeKickback); + if (Controller.getNumberOfSpatialControls() > 0) { + clearPose(); + } + elbowKickAngle = 0.0; + } + } + // Check hydra controller for launch button press if (!isLaunchButtonPressed && Controller.isButtonPressed(LEFT_BUTTON_3)) { isLaunchButtonPressed = true; @@ -235,15 +314,13 @@ function update(deltaTime) { } - // Check hydra controller for trigger press + // check for trigger press - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + var numberOfTriggers = 2; + var controllersPerTrigger = 2; - // this is expected for hydras if (numberOfTriggers == 2 && controllersPerTrigger == 2) { - for (var t = 0; t < numberOfTriggers; t++) { + for (var t = 0; t < 2; t++) { var shootABullet = false; var triggerValue = Controller.getTriggerValue(t); if (triggerPulled[t]) { @@ -252,14 +329,13 @@ function update(deltaTime) { triggerPulled[t] = false; // unpulled } } else { - // must pull to at least 0.9 - if (triggerValue > 0.9) { + // must pull to at least + if (triggerValue > 0.5) { triggerPulled[t] = true; // pulled shootABullet = true; } } - if (shootABullet) { var palmController = t * controllersPerTrigger; var palmPosition = Controller.getSpatialControlPosition(palmController); @@ -276,12 +352,8 @@ function update(deltaTime) { var position = { x: fingerTipPosition.x + palmToFingerTipVector.x/2, y: fingerTipPosition.y + palmToFingerTipVector.y/2, z: fingerTipPosition.z + palmToFingerTipVector.z/2}; - - var linearVelocity = 25; - - var velocity = { x: palmToFingerTipVector.x * linearVelocity, - y: palmToFingerTipVector.y * linearVelocity, - z: palmToFingerTipVector.z * linearVelocity }; + + var velocity = Vec3.multiply(BULLET_VELOCITY, Vec3.normalize(palmToFingerTipVector)); shootBullet(position, velocity); } @@ -293,8 +365,12 @@ function mousePressEvent(event) { isMouseDown = true; lastX = event.x; lastY = event.y; - //audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - //Audio.playSound(loadSound, audioOptions); + + if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === offButton) { + Script.stop(); + } else { + shootFromMouse(); + } } function shootFromMouse() { @@ -325,11 +401,12 @@ function mouseMoveEvent(event) { function scriptEnding() { Overlays.deleteOverlay(reticle); + Overlays.deleteOverlay(offButton); Overlays.deleteOverlay(text); MyAvatar.detachOne(gunModel); + clearPose(); } -Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Script.scriptEnding.connect(scriptEnding); Script.update.connect(update); diff --git a/examples/controllers/hydra/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js new file mode 100644 index 0000000000..4d0b873fd2 --- /dev/null +++ b/examples/controllers/hydra/hydraGrab.js @@ -0,0 +1,742 @@ +// +// hydraGrab.js +// examples +// +// Created by Clément Brisset on 4/24/14. +// Copyright 2014 High Fidelity, Inc. +// +// This script allows you to edit models either with the razor hydras or with your mouse +// +// Using the hydras : +// grab models with the triggers, you can then move the models around or scale them with both hands. +// You can switch mode using the bumpers so that you can move models around more easily. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +Script.include("libraries/entityPropertyDialogBox.js"); +var entityPropertyDialogBox = EntityPropertyDialogBox; + +var LASER_WIDTH = 4; +var LASER_COLOR = { red: 255, green: 0, blue: 0 }; +var LASER_LENGTH_FACTOR = 500; + +var MIN_ANGULAR_SIZE = 2; +var MAX_ANGULAR_SIZE = 45; +var allowLargeModels = false; +var allowSmallModels = false; +var wantEntityGlow = false; + +var LEFT = 0; +var RIGHT = 1; + +var jointList = MyAvatar.getJointNames(); + +var mode = 0; + +function controller(wichSide) { + this.side = wichSide; + this.palm = 2 * wichSide; + this.tip = 2 * wichSide + 1; + this.trigger = wichSide; + this.bumper = 6 * wichSide + 5; + + this.oldPalmPosition = Controller.getSpatialControlPosition(this.palm); + this.palmPosition = Controller.getSpatialControlPosition(this.palm); + + this.oldTipPosition = Controller.getSpatialControlPosition(this.tip); + this.tipPosition = Controller.getSpatialControlPosition(this.tip); + + this.oldUp = Controller.getSpatialControlNormal(this.palm); + this.up = this.oldUp; + + this.oldFront = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); + this.front = this.oldFront; + + this.oldRight = Vec3.cross(this.front, this.up); + this.right = this.oldRight; + + this.oldRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); + this.rotation = this.oldRotation; + + this.triggerValue = Controller.getTriggerValue(this.trigger); + this.bumperValue = Controller.isButtonPressed(this.bumper); + + this.pressed = false; // is trigger pressed + this.pressing = false; // is trigger being pressed (is pressed now but wasn't previously) + + this.grabbing = false; + this.entityID = { isKnownID: false }; + this.modelURL = ""; + this.oldModelRotation; + this.oldModelPosition; + this.oldModelHalfDiagonal; + + this.positionAtGrab; + this.rotationAtGrab; + this.modelPositionAtGrab; + this.rotationAtGrab; + this.jointsIntersectingFromStart = []; + + this.laser = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: LASER_COLOR, + alpha: 1, + visible: false, + lineWidth: LASER_WIDTH, + anchor: "MyAvatar" + }); + + this.guideScale = 0.02; + this.ball = Overlays.addOverlay("sphere", { + position: { x: 0, y: 0, z: 0 }, + size: this.guideScale, + solid: true, + color: { red: 0, green: 255, blue: 0 }, + alpha: 1, + visible: false, + anchor: "MyAvatar" + }); + this.leftRight = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 0, blue: 255 }, + alpha: 1, + visible: false, + lineWidth: LASER_WIDTH, + anchor: "MyAvatar" + }); + this.topDown = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 0, blue: 255 }, + alpha: 1, + visible: false, + lineWidth: LASER_WIDTH, + anchor: "MyAvatar" + }); + + + + this.grab = function (entityID, properties) { + print("Grabbing " + entityID.id); + this.grabbing = true; + this.entityID = entityID; + this.modelURL = properties.modelURL; + + this.oldModelPosition = properties.position; + this.oldModelRotation = properties.rotation; + this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + this.positionAtGrab = this.palmPosition; + this.rotationAtGrab = this.rotation; + this.modelPositionAtGrab = properties.position; + this.rotationAtGrab = properties.rotation; + this.jointsIntersectingFromStart = []; + for (var i = 0; i < jointList.length; i++) { + var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); + if (distance < this.oldModelHalfDiagonal) { + this.jointsIntersectingFromStart.push(i); + } + } + this.showLaser(false); + } + + this.release = function () { + if (this.grabbing) { + jointList = MyAvatar.getJointNames(); + + var closestJointIndex = -1; + var closestJointDistance = 10; + for (var i = 0; i < jointList.length; i++) { + var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); + if (distance < closestJointDistance) { + closestJointDistance = distance; + closestJointIndex = i; + } + } + + if (closestJointIndex != -1) { + print("closestJoint: " + jointList[closestJointIndex]); + print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelHalfDiagonal + ")"); + } + + if (closestJointDistance < this.oldModelHalfDiagonal) { + + if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1 || + (leftController.grabbing && rightController.grabbing && + leftController.entityID.id == rightController.entityID.id)) { + // Do nothing + } else { + print("Attaching to " + jointList[closestJointIndex]); + var jointPosition = MyAvatar.getJointPosition(jointList[closestJointIndex]); + var jointRotation = MyAvatar.getJointCombinedRotation(jointList[closestJointIndex]); + + var attachmentOffset = Vec3.subtract(this.oldModelPosition, jointPosition); + attachmentOffset = Vec3.multiplyQbyV(Quat.inverse(jointRotation), attachmentOffset); + var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation); + + MyAvatar.attach(this.modelURL, jointList[closestJointIndex], + attachmentOffset, attachmentRotation, 2.0 * this.oldModelHalfDiagonal, + true, false); + Entities.deleteEntity(this.entityID); + } + } + } + + this.grabbing = false; + this.entityID.isKnownID = false; + this.jointsIntersectingFromStart = []; + this.showLaser(true); + } + + this.checkTrigger = function () { + if (this.triggerValue > 0.9) { + if (this.pressed) { + this.pressing = false; + } else { + this.pressing = true; + } + this.pressed = true; + } else { + this.pressing = false; + this.pressed = false; + } + } + + this.checkEntity = function (properties) { + // P P - Model + // /| A - Palm + // / | d B - unit vector toward tip + // / | X - base of the perpendicular line + // A---X----->B d - distance fom axis + // x x - distance from A + // + // |X-A| = (P-A).B + // X == A + ((P-A).B)B + // d = |P-X| + + var A = this.palmPosition; + var B = this.front; + var P = properties.position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var y = Vec3.dot(Vec3.subtract(P, A), this.up); + var z = Vec3.dot(Vec3.subtract(P, A), this.right); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) + && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (0 < x && sizeOK) { + return { valid: true, x: x, y: y, z: z }; + } + return { valid: false }; + } + + this.glowedIntersectingModel = { isKnownID: false }; + this.moveLaser = function () { + // the overlays here are anchored to the avatar, which means they are specified in the avatar's local frame + + var inverseRotation = Quat.inverse(MyAvatar.orientation); + var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position)); + var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition)); + var distance = Vec3.length(direction); + direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance); + var endPosition = Vec3.sum(startPosition, direction); + + Overlays.editOverlay(this.laser, { + start: startPosition, + end: endPosition + }); + + + Overlays.editOverlay(this.ball, { + position: endPosition + }); + Overlays.editOverlay(this.leftRight, { + start: Vec3.sum(endPosition, Vec3.multiply(this.right, 2 * this.guideScale)), + end: Vec3.sum(endPosition, Vec3.multiply(this.right, -2 * this.guideScale)) + }); + Overlays.editOverlay(this.topDown, { + start: Vec3.sum(endPosition, Vec3.multiply(this.up, 2 * this.guideScale)), + end: Vec3.sum(endPosition, Vec3.multiply(this.up, -2 * this.guideScale)) + }); + this.showLaser(!this.grabbing || mode == 0); + + if (this.glowedIntersectingModel.isKnownID) { + Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.0 }); + this.glowedIntersectingModel.isKnownID = false; + } + if (!this.grabbing) { + var intersection = Entities.findRayIntersection({ + origin: this.palmPosition, + direction: this.front + }); + + var halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) + && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + if (intersection.accurate && intersection.entityID.isKnownID && sizeOK) { + this.glowedIntersectingModel = intersection.entityID; + + if (wantEntityGlow) { + Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 }); + } + } + } + } + + this.showLaser = function (show) { + Overlays.editOverlay(this.laser, { visible: show }); + Overlays.editOverlay(this.ball, { visible: show }); + Overlays.editOverlay(this.leftRight, { visible: show }); + Overlays.editOverlay(this.topDown, { visible: show }); + } + this.moveEntity = function () { + if (this.grabbing) { + if (!this.entityID.isKnownID) { + print("Unknown grabbed ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); + this.entityID = Entities.findRayIntersection({ + origin: this.palmPosition, + direction: this.front + }).entityID; + print("Identified ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); + } + var newPosition; + var newRotation; + + switch (mode) { + case 0: + newPosition = Vec3.sum(this.palmPosition, + Vec3.multiply(this.front, this.x)); + newPosition = Vec3.sum(newPosition, + Vec3.multiply(this.up, this.y)); + newPosition = Vec3.sum(newPosition, + Vec3.multiply(this.right, this.z)); + + + newRotation = Quat.multiply(this.rotation, + Quat.inverse(this.oldRotation)); + newRotation = Quat.multiply(newRotation, + this.oldModelRotation); + break; + case 1: + var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); + var d = Vec3.dot(forward, MyAvatar.position); + + var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; + var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; + var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); + + if (factor2 < 0) { + factor2 = 0; + } + if (factor1 <= 0) { + factor1 = 1; + factor2 = 1; + } + + newPosition = Vec3.sum(this.modelPositionAtGrab, + Vec3.multiply(vector, + factor2 / factor1)); + + newRotation = Quat.multiply(this.rotation, + Quat.inverse(this.rotationAtGrab)); + newRotation = Quat.multiply(newRotation, + this.rotationAtGrab); + break; + } + Entities.editEntity(this.entityID, { + position: newPosition, + rotation: newRotation + }); + this.oldModelRotation = newRotation; + this.oldModelPosition = newPosition; + + var indicesToRemove = []; + for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { + var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); + if (distance >= this.oldModelHalfDiagonal) { + indicesToRemove.push(this.jointsIntersectingFromStart[i]); + } + + } + for (var i = 0; i < indicesToRemove.length; ++i) { + this.jointsIntersectingFromStart.splice(this.jointsIntersectingFromStart.indexOf(indicesToRemove[i], 1)); + } + } + } + + this.update = function () { + this.oldPalmPosition = this.palmPosition; + this.oldTipPosition = this.tipPosition; + this.palmPosition = Controller.getSpatialControlPosition(this.palm); + this.tipPosition = Controller.getSpatialControlPosition(this.tip); + + this.oldUp = this.up; + this.up = Vec3.normalize(Controller.getSpatialControlNormal(this.palm)); + + this.oldFront = this.front; + this.front = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); + + this.oldRight = this.right; + this.right = Vec3.normalize(Vec3.cross(this.front, this.up)); + + this.oldRotation = this.rotation; + this.rotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); + + this.triggerValue = Controller.getTriggerValue(this.trigger); + + var bumperValue = Controller.isButtonPressed(this.bumper); + if (bumperValue && !this.bumperValue) { + if (mode == 0) { + mode = 1; + Overlays.editOverlay(leftController.laser, { color: { red: 0, green: 0, blue: 255 } }); + Overlays.editOverlay(rightController.laser, { color: { red: 0, green: 0, blue: 255 } }); + } else { + mode = 0; + Overlays.editOverlay(leftController.laser, { color: { red: 255, green: 0, blue: 0 } }); + Overlays.editOverlay(rightController.laser, { color: { red: 255, green: 0, blue: 0 } }); + } + } + this.bumperValue = bumperValue; + + + this.checkTrigger(); + + this.moveLaser(); + + if (!this.pressed && this.grabbing) { + // release if trigger not pressed anymore. + this.release(); + } + + if (this.pressing) { + // Checking for attachments intersecting + var attachments = MyAvatar.getAttachmentData(); + var attachmentIndex = -1; + var attachmentX = LASER_LENGTH_FACTOR; + + var newModel; + var newProperties; + + for (var i = 0; i < attachments.length; ++i) { + var position = Vec3.sum(MyAvatar.getJointPosition(attachments[i].jointName), + Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[i].jointName), attachments[i].translation)); + var scale = attachments[i].scale; + + var A = this.palmPosition; + var B = this.front; + var P = position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + + if (d < scale / 2.0 && 0 < x && x < attachmentX) { + attachmentIndex = i; + attachmentX = d; + } + } + + if (attachmentIndex != -1) { + print("Detaching: " + attachments[attachmentIndex].modelURL); + MyAvatar.detachOne(attachments[attachmentIndex].modelURL, attachments[attachmentIndex].jointName); + + newProperties = { + type: "Model", + position: Vec3.sum(MyAvatar.getJointPosition(attachments[attachmentIndex].jointName), + Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].translation)), + rotation: Quat.multiply(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), + attachments[attachmentIndex].rotation), + + // TODO: how do we know the correct dimensions for detachment??? + dimensions: { x: attachments[attachmentIndex].scale / 2.0, + y: attachments[attachmentIndex].scale / 2.0, + z: attachments[attachmentIndex].scale / 2.0 }, + + modelURL: attachments[attachmentIndex].modelURL + }; + + newModel = Entities.addEntity(newProperties); + + + } else { + // There is none so ... + // Checking model tree + Vec3.print("Looking at: ", this.palmPosition); + var pickRay = { origin: this.palmPosition, + direction: Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)) }; + var foundIntersection = Entities.findRayIntersection(pickRay); + + if(!foundIntersection.accurate) { + print("No accurate intersection"); + return; + } + newModel = foundIntersection.entityID; + if (!newModel.isKnownID) { + var identify = Entities.identifyEntity(newModel); + if (!identify.isKnownID) { + print("Unknown ID " + identify.id + " (update loop " + newModel.id + ")"); + return; + } + newModel = identify; + } + newProperties = Entities.getEntityProperties(newModel); + } + print("foundEntity.modelURL=" + newProperties.modelURL); + var check = this.checkEntity(newProperties); + if (!check.valid) { + return; + } + + this.grab(newModel, newProperties); + + this.x = check.x; + this.y = check.y; + this.z = check.z; + return; + } + } + + this.cleanup = function () { + Overlays.deleteOverlay(this.laser); + Overlays.deleteOverlay(this.ball); + Overlays.deleteOverlay(this.leftRight); + Overlays.deleteOverlay(this.topDown); + } +} + +var leftController = new controller(LEFT); +var rightController = new controller(RIGHT); + +function moveEntities() { + if (leftController.grabbing && rightController.grabbing && rightController.entityID.id == leftController.entityID.id) { + var newPosition = leftController.oldModelPosition; + var rotation = leftController.oldModelRotation; + var ratio = 1; + + + switch (mode) { + case 0: + var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x)); + var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x)); + + var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5); + var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint)); + + + var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x)); + var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x)); + + var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5); + var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint)); + + + ratio = length / oldLength; + newPosition = Vec3.sum(middle, + Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio)); + break; + case 1: + var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); + var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); + + var cos_theta = Vec3.dot(u, v); + if (cos_theta > 1) { + cos_theta = 1; + } + var angle = Math.acos(cos_theta) / Math.PI * 180; + if (angle < 0.1) { + return; + + } + var w = Vec3.normalize(Vec3.cross(u, v)); + + rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); + + + leftController.positionAtGrab = leftController.palmPosition; + leftController.rotationAtGrab = leftController.rotation; + leftController.modelPositionAtGrab = leftController.oldModelPosition; + leftController.rotationAtGrab = rotation; + rightController.positionAtGrab = rightController.palmPosition; + rightController.rotationAtGrab = rightController.rotation; + rightController.modelPositionAtGrab = rightController.oldModelPosition; + rightController.rotationAtGrab = rotation; + break; + } + Entities.editEntity(leftController.entityID, { + position: newPosition, + rotation: rotation, + // TODO: how do we know the correct dimensions for detachment??? + //radius: leftController.oldModelHalfDiagonal * ratio + dimensions: { x: leftController.oldModelHalfDiagonal * ratio, + y: leftController.oldModelHalfDiagonal * ratio, + z: leftController.oldModelHalfDiagonal * ratio } + + + }); + leftController.oldModelPosition = newPosition; + leftController.oldModelRotation = rotation; + leftController.oldModelHalfDiagonal *= ratio; + + rightController.oldModelPosition = newPosition; + rightController.oldModelRotation = rotation; + rightController.oldModelHalfDiagonal *= ratio; + return; + } + leftController.moveEntity(); + rightController.moveEntity(); +} + +var hydraConnected = false; +function checkController(deltaTime) { + var numberOfButtons = Controller.getNumberOfButtons(); + var numberOfTriggers = Controller.getNumberOfTriggers(); + var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); + var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + + // this is expected for hydras + if (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2) { + if (!hydraConnected) { + hydraConnected = true; + } + + leftController.update(); + rightController.update(); + moveEntities(); + } else { + if (hydraConnected) { + hydraConnected = false; + + leftController.showLaser(false); + rightController.showLaser(false); + } + } +} + +var glowedEntityID = { id: -1, isKnownID: false }; + +// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already +// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that +// added it. +var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); +function setupModelMenus() { + print("setupModelMenus()"); + // adj our menuitems + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Edit Properties...", + shortcutKeyEvent: { text: "`" }, afterItem: "Models" }); + if (!Menu.menuItemExists("Edit", "Delete")) { + print("no delete... adding ours"); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", + shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" }); + modelMenuAddedDelete = true; + } else { + print("delete exists... don't add ours"); + } + + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", + afterItem: "Paste Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", + afterItem: "Allow Selecting of Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", + afterItem: "Allow Selecting of Small Models", isCheckable: true }); + + Entities.setLightsArePickable(false); +} + +function cleanupModelMenus() { + Menu.removeMenuItem("Edit", "Edit Properties..."); + if (modelMenuAddedDelete) { + // delete our menuitems + Menu.removeMenuItem("Edit", "Delete"); + } + + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); + +} + +function scriptEnding() { + leftController.cleanup(); + rightController.cleanup(); + cleanupModelMenus(); + Entities.setLightsArePickable(originalLightsArePickable); +} +Script.scriptEnding.connect(scriptEnding); + +// register the call back so it fires before each data send +Script.update.connect(checkController); + +setupModelMenus(); + +var editModelID = -1; +function showPropertiesForm(editModelID) { + entityPropertyDialogBox.openDialog(editModelID); +} + +Menu.menuItemEvent.connect(function (menuItem) { + print("menuItemEvent() in JS... menuItem=" + menuItem); + if (menuItem == "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem == "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem == "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); + } else if (menuItem == "Delete") { + if (leftController.grabbing) { + print(" Delete Entity.... leftController.entityID="+ leftController.entityID); + Entities.deleteEntity(leftController.entityID); + leftController.grabbing = false; + if (glowedEntityID.id == leftController.entityID.id) { + glowedEntityID = { id: -1, isKnownID: false }; + } + } else if (rightController.grabbing) { + print(" Delete Entity.... rightController.entityID="+ rightController.entityID); + Entities.deleteEntity(rightController.entityID); + rightController.grabbing = false; + if (glowedEntityID.id == rightController.entityID.id) { + glowedEntityID = { id: -1, isKnownID: false }; + } + } else { + print(" Delete Entity.... not holding..."); + } + } else if (menuItem == "Edit Properties...") { + editModelID = -1; + if (leftController.grabbing) { + print(" Edit Properties.... leftController.entityID="+ leftController.entityID); + editModelID = leftController.entityID; + } else if (rightController.grabbing) { + print(" Edit Properties.... rightController.entityID="+ rightController.entityID); + editModelID = rightController.entityID; + } else { + print(" Edit Properties.... not holding..."); + } + if (editModelID != -1) { + print(" Edit Properties.... about to edit properties..."); + showPropertiesForm(editModelID); + } + } +}); + +Controller.keyReleaseEvent.connect(function (event) { + // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items + if (event.text == "`") { + handeMenuEvent("Edit Properties..."); + } + if (event.text == "BACKSPACE") { + handeMenuEvent("Delete"); + } +}); + diff --git a/examples/hydraMove.js b/examples/controllers/hydra/hydraMove.js similarity index 100% rename from examples/hydraMove.js rename to examples/controllers/hydra/hydraMove.js diff --git a/examples/controllers/hydra/laserPointer.js b/examples/controllers/hydra/laserPointer.js new file mode 100644 index 0000000000..156e9ba298 --- /dev/null +++ b/examples/controllers/hydra/laserPointer.js @@ -0,0 +1,93 @@ +// +// laserPointer.js +// examples +// +// Created by Clément Brisset on 7/18/14. +// Copyright 2014 High Fidelity, Inc. +// +// If using Hydra controllers, pulling the triggers makes laser pointers emanate from the respective hands. +// If using a Leap Motion or similar to control your avatar's hands and fingers, pointing with your index fingers makes +// laser pointers emanate from the respective index fingers. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var laserPointer = (function () { + + var NUM_FINGERs = 4, // Excluding thumb + fingers = [ + [ "LeftHandIndex", "LeftHandMiddle", "LeftHandRing", "LeftHandPinky" ], + [ "RightHandIndex", "RightHandMiddle", "RightHandRing", "RightHandPinky" ] + ]; + + function isHandPointing(hand) { + var MINIMUM_TRIGGER_PULL = 0.9; + return Controller.getTriggerValue(hand) > MINIMUM_TRIGGER_PULL; + } + + function isFingerPointing(hand) { + // Index finger is pointing if final two bones of middle, ring, and pinky fingers are > 90 degrees w.r.t. index finger + + var pointing, + indexDirection, + otherDirection, + f; + + pointing = true; + + indexDirection = Vec3.subtract( + MyAvatar.getJointPosition(fingers[hand][0] + "4"), + MyAvatar.getJointPosition(fingers[hand][0] + "2") + ); + + for (f = 1; f < NUM_FINGERs; f += 1) { + otherDirection = Vec3.subtract( + MyAvatar.getJointPosition(fingers[hand][f] + "4"), + MyAvatar.getJointPosition(fingers[hand][f] + "2") + ); + pointing = pointing && Vec3.dot(indexDirection, otherDirection) < 0; + } + + return pointing; + } + + function update() { + var LEFT_HAND = 0, + RIGHT_HAND = 1, + LEFT_HAND_POINTING_FLAG = 1, + RIGHT_HAND_POINTING_FLAG = 2, + FINGER_POINTING_FLAG = 4, + handState; + + handState = 0; + + if (isHandPointing(LEFT_HAND)) { + handState += LEFT_HAND_POINTING_FLAG; + } + if (isHandPointing(RIGHT_HAND)) { + handState += RIGHT_HAND_POINTING_FLAG; + } + + if (handState === 0) { + if (isFingerPointing(LEFT_HAND)) { + handState += LEFT_HAND_POINTING_FLAG; + } + if (isFingerPointing(RIGHT_HAND)) { + handState += RIGHT_HAND_POINTING_FLAG; + } + if (handState !== 0) { + handState += FINGER_POINTING_FLAG; + } + } + + MyAvatar.setHandState(handState); + } + + return { + update: update + }; + +}()); + +Script.update.connect(laserPointer.update); diff --git a/examples/squeezeHands.js b/examples/controllers/hydra/squeezeHands.js similarity index 98% rename from examples/squeezeHands.js rename to examples/controllers/hydra/squeezeHands.js index 21da7f9c25..84e5aefb51 100644 --- a/examples/squeezeHands.js +++ b/examples/controllers/hydra/squeezeHands.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); var rightHandAnimation = HIFI_PUBLIC_BUCKET + "animations/RightHandAnimPhilip.fbx"; var leftHandAnimation = HIFI_PUBLIC_BUCKET + "animations/LeftHandAnimPhilip.fbx"; diff --git a/examples/toyball.js b/examples/controllers/hydra/toyball.js similarity index 96% rename from examples/toyball.js rename to examples/controllers/hydra/toyball.js index e39ca9c8b4..4dc65703b7 100644 --- a/examples/toyball.js +++ b/examples/controllers/hydra/toyball.js @@ -15,7 +15,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); // maybe we should make these constants... var LEFT_PALM = 0; @@ -29,7 +29,7 @@ var RIGHT_BUTTON_FWD = 11; var RIGHT_BUTTON_3 = 9; var BALL_RADIUS = 0.08; -var GRAVITY_STRENGTH = 0.5; +var GRAVITY_STRENGTH = 1.0; var HELD_COLOR = { red: 240, green: 0, blue: 0 }; var THROWN_COLOR = { red: 128, green: 0, blue: 0 }; @@ -136,8 +136,8 @@ function checkControllerSide(whichSide) { velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, inHand: true, - radius: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, - damping: 0.999, + dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, + damping: 0.00001, color: HELD_COLOR, lifetime: 600 // 10 seconds - same as default, not needed but here as an example @@ -185,6 +185,7 @@ function checkControllerSide(whichSide) { velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING, y: tipVelocity.y * THROWN_VELOCITY_SCALING, z: tipVelocity.z * THROWN_VELOCITY_SCALING } , + collisionsWillMove: true, inHand: false, color: THROWN_COLOR, lifetime: 10, diff --git a/examples/controllers/leap/laserPointer.js b/examples/controllers/leap/laserPointer.js new file mode 100644 index 0000000000..156e9ba298 --- /dev/null +++ b/examples/controllers/leap/laserPointer.js @@ -0,0 +1,93 @@ +// +// laserPointer.js +// examples +// +// Created by Clément Brisset on 7/18/14. +// Copyright 2014 High Fidelity, Inc. +// +// If using Hydra controllers, pulling the triggers makes laser pointers emanate from the respective hands. +// If using a Leap Motion or similar to control your avatar's hands and fingers, pointing with your index fingers makes +// laser pointers emanate from the respective index fingers. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var laserPointer = (function () { + + var NUM_FINGERs = 4, // Excluding thumb + fingers = [ + [ "LeftHandIndex", "LeftHandMiddle", "LeftHandRing", "LeftHandPinky" ], + [ "RightHandIndex", "RightHandMiddle", "RightHandRing", "RightHandPinky" ] + ]; + + function isHandPointing(hand) { + var MINIMUM_TRIGGER_PULL = 0.9; + return Controller.getTriggerValue(hand) > MINIMUM_TRIGGER_PULL; + } + + function isFingerPointing(hand) { + // Index finger is pointing if final two bones of middle, ring, and pinky fingers are > 90 degrees w.r.t. index finger + + var pointing, + indexDirection, + otherDirection, + f; + + pointing = true; + + indexDirection = Vec3.subtract( + MyAvatar.getJointPosition(fingers[hand][0] + "4"), + MyAvatar.getJointPosition(fingers[hand][0] + "2") + ); + + for (f = 1; f < NUM_FINGERs; f += 1) { + otherDirection = Vec3.subtract( + MyAvatar.getJointPosition(fingers[hand][f] + "4"), + MyAvatar.getJointPosition(fingers[hand][f] + "2") + ); + pointing = pointing && Vec3.dot(indexDirection, otherDirection) < 0; + } + + return pointing; + } + + function update() { + var LEFT_HAND = 0, + RIGHT_HAND = 1, + LEFT_HAND_POINTING_FLAG = 1, + RIGHT_HAND_POINTING_FLAG = 2, + FINGER_POINTING_FLAG = 4, + handState; + + handState = 0; + + if (isHandPointing(LEFT_HAND)) { + handState += LEFT_HAND_POINTING_FLAG; + } + if (isHandPointing(RIGHT_HAND)) { + handState += RIGHT_HAND_POINTING_FLAG; + } + + if (handState === 0) { + if (isFingerPointing(LEFT_HAND)) { + handState += LEFT_HAND_POINTING_FLAG; + } + if (isFingerPointing(RIGHT_HAND)) { + handState += RIGHT_HAND_POINTING_FLAG; + } + if (handState !== 0) { + handState += FINGER_POINTING_FLAG; + } + } + + MyAvatar.setHandState(handState); + } + + return { + update: update + }; + +}()); + +Script.update.connect(laserPointer.update); diff --git a/examples/leapHands.js b/examples/controllers/leap/leapHands.js similarity index 100% rename from examples/leapHands.js rename to examples/controllers/leap/leapHands.js diff --git a/examples/leapOfFaith.js b/examples/controllers/leap/leapOfFaith.js similarity index 100% rename from examples/leapOfFaith.js rename to examples/controllers/leap/leapOfFaith.js diff --git a/examples/virtualKeyboard.js b/examples/controllers/oculus/virtualKeyboard.js similarity index 99% rename from examples/virtualKeyboard.js rename to examples/controllers/oculus/virtualKeyboard.js index ce793c6ea0..dc3c2eb3cc 100644 --- a/examples/virtualKeyboard.js +++ b/examples/controllers/oculus/virtualKeyboard.js @@ -15,7 +15,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); const KBD_UPPERCASE_DEFAULT = 0; const KBD_LOWERCASE_DEFAULT = 1; diff --git a/examples/count.js b/examples/count.js deleted file mode 100644 index 2a8699ac55..0000000000 --- a/examples/count.js +++ /dev/null @@ -1,30 +0,0 @@ -// -// count.js -// examples -// -// Created by Brad Hefta-Gaub on 12/31/13. -// Copyright 2013 High Fidelity, Inc. -// -// This is an example script that runs in a loop and displays a counter to the log -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -// - -var count = 0; - -function displayCount(deltaTime) { - print("count =" + count + " deltaTime=" + deltaTime); - count++; -} - -function scriptEnding() { - print("SCRIPT ENDNG!!!\n"); -} - -// register the call back so it fires before each data send -Script.update.connect(displayCount); - -// register our scriptEnding callback -Script.scriptEnding.connect(scriptEnding); diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index d39fce0186..cdb8e76c65 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -15,3 +15,4 @@ Script.load("hydraMove.js"); Script.load("headMove.js"); Script.load("inspect.js"); Script.load("lobby.js"); +Script.load("notifications.js"); diff --git a/examples/editEntities.js b/examples/editEntities.js index 0b5c089c07..172089ed62 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -42,7 +42,15 @@ gridTool = GridTool({ horizontalGrid: grid }); Script.include("libraries/entityList.js"); var entityListTool = EntityListTool(); -selectionManager.addEventListener(selectionDisplay.updateHandles); +var hasShownPropertiesTool = false; + +selectionManager.addEventListener(function() { + selectionDisplay.updateHandles(); + if (selectionManager.hasSelection() && !hasShownPropertiesTool) { + propertiesTool.setVisible(true); + hasShownPropertiesTool = true; + } +}); var windowDimensions = Controller.getViewportDimensions(); var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; @@ -77,7 +85,6 @@ var modelURLs = [ HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush1.fbx", HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush6.fbx", - HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-large-purple.svo", HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed.fbx", HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed2.fbx", HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed4.fbx", @@ -192,8 +199,7 @@ var toolBar = (function () { }); newTextButton = toolBar.addTool({ - //imageURL: toolIconUrl + "add-text.svg", - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/add-text.svg", // temporarily + imageURL: toolIconUrl + "add-text.svg", subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, width: toolWidth, height: toolHeight, @@ -225,10 +231,9 @@ var toolBar = (function () { selectionManager.clearSelections(); cameraManager.disable(); } else { + hasShownPropertiesTool = false; cameraManager.enable(); - entityListTool.setVisible(true); gridTool.setVisible(true); - propertiesTool.setVisible(true); grid.setEnabled(true); } } @@ -494,8 +499,10 @@ var mouseHasMovedSincePress = false; function mousePressEvent(event) { mouseHasMovedSincePress = false; + mouseCapturedByTool = false; - if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { + if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event) || gridTool.mousePressEvent(event)) { + mouseCapturedByTool = true; return; } if (isActive) { @@ -519,6 +526,7 @@ function mousePressEvent(event) { } var highlightedEntityID = { isKnownID: false }; +var mouseCapturedByTool = false; function mouseMoveEvent(event) { mouseHasMovedSincePress = true; @@ -563,6 +571,9 @@ function mouseReleaseEvent(event) { if (isActive && selectionManager.hasSelection()) { tooltip.show(false); } + if (mouseCapturedByTool) { + return; + } cameraManager.mouseReleaseEvent(event); @@ -651,8 +662,6 @@ function setupModelMenus() { print("setupModelMenus()"); // adj our menuitems Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Edit Properties...", - shortcutKeyEvent: { text: "`" }, afterItem: "Models" }); if (!Menu.menuItemExists("Edit", "Delete")) { print("no delete... adding ours"); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", @@ -663,7 +672,7 @@ function setupModelMenus() { } Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Model List..." }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Paste Models", isCheckable: true, isChecked: true }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", @@ -685,7 +694,6 @@ setupModelMenus(); // do this when first running our script. function cleanupModelMenus() { Menu.removeSeparator("Edit", "Models"); - Menu.removeMenuItem("Edit", "Edit Properties..."); if (modelMenuAddedDelete) { // delete our menuitems Menu.removeMenuItem("Edit", "Delete"); @@ -787,22 +795,6 @@ function handeMenuEvent(menuItem) { MyAvatar.position = selectedModel.properties.position; } } - } else if (menuItem == "Edit Properties...") { - // good place to put the properties dialog - - editModelID = -1; - if (selectionManager.selections.length == 1) { - print(" Edit Properties.... selectedEntityID="+ selectedEntityID); - editModelID = selectionManager.selections[0]; - } else { - print(" Edit Properties.... not holding..."); - } - if (editModelID != -1) { - print(" Edit Properties.... about to edit properties..."); - entityPropertyDialogBox.openDialog(editModelID); - selectionManager._update(); - } - } else if (menuItem == "Paste Models") { modelImporter.paste(); } else if (menuItem == "Export Models") { @@ -830,9 +822,6 @@ Controller.keyPressEvent.connect(function(event) { Controller.keyReleaseEvent.connect(function (event) { // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items - if (event.text == "`") { - handeMenuEvent("Edit Properties..."); - } if (event.text == "BACKSPACE" || event.text == "DELETE") { handeMenuEvent("Delete"); } else if (event.text == "TAB") { @@ -1066,6 +1055,19 @@ PropertiesTool = function(opts) { pushCommandForSelections(); selectionManager._update(); } + } else if (data.action == "rescaleDimensions") { + var multiplier = data.percentage / 100; + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + Entities.editEntity(selectionManager.selections[i], { + dimensions: Vec3.multiply(multiplier, properties.dimensions), + }); + } + pushCommandForSelections(); + selectionManager._update(); + } } } }); diff --git a/examples/editModels.js b/examples/editModels.js deleted file mode 100644 index e0ade3b6a3..0000000000 --- a/examples/editModels.js +++ /dev/null @@ -1,3042 +0,0 @@ -// -// editEntities.js -// examples -// -// Created by Clément Brisset on 4/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit models either with the razor hydras or with your mouse -// -// If using the hydras : -// grab grab models with the triggers, you can then move the models around or scale them with both hands. -// You can switch mode using the bumpers so that you can move models around more easily. -// -// If using the mouse : -// - left click lets you move the model in the plane facing you. -// If pressing shift, it will move on the horizontal plane it's in. -// - right click lets you rotate the model. z and x give access to more axes of rotation while shift provides finer control. -// - left + right click lets you scale the model. -// - you can press r while holding the model to reset its rotation -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); -Script.include("libraries/toolBars.js"); - -Script.include("libraries/entityPropertyDialogBox.js"); -var entityPropertyDialogBox = EntityPropertyDialogBox; - -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; -var toolHeight = 50; -var toolWidth = 50; - -var LASER_WIDTH = 4; -var LASER_COLOR = { red: 255, green: 0, blue: 0 }; -var LASER_LENGTH_FACTOR = 500; - -var MIN_ANGULAR_SIZE = 2; -var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = false; -var allowSmallModels = false; -var wantEntityGlow = false; - -var LEFT = 0; -var RIGHT = 1; - -var SPAWN_DISTANCE = 1; -var DEFAULT_DIMENSION = 0.20; -var DEFAULT_TEXT_DIMENSION_X = 1.0; -var DEFAULT_TEXT_DIMENSION_Y = 1.0; -var DEFAULT_TEXT_DIMENSION_Z = 0.01; - -var modelURLs = [ - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush1.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush6.fbx", - HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-large-purple.svo", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed2.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed4.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed7.fbx" - ]; - -var jointList = MyAvatar.getJointNames(); - -var mode = 0; -var isActive = false; - - -if (typeof String.prototype.fileName !== "function") { - String.prototype.fileName = function () { - return this.replace(/^(.*[\/\\])*/, ""); - }; -} - -if (typeof String.prototype.fileBase !== "function") { - String.prototype.fileBase = function () { - var filename = this.fileName(); - return filename.slice(0, filename.indexOf(".")); - }; -} - -if (typeof String.prototype.fileType !== "function") { - String.prototype.fileType = function () { - return this.slice(this.lastIndexOf(".") + 1); - }; -} - -if (typeof String.prototype.path !== "function") { - String.prototype.path = function () { - return this.replace(/[\\\/][^\\\/]*$/, ""); - }; -} - -if (typeof String.prototype.regExpEscape !== "function") { - String.prototype.regExpEscape = function () { - return this.replace(/([$\^.+*?|\\\/{}()\[\]])/g, '\\$1'); - }; -} - -if (typeof String.prototype.toArrayBuffer !== "function") { - String.prototype.toArrayBuffer = function () { - var length, - buffer, - view, - charCode, - charCodes, - i; - - charCodes = []; - - length = this.length; - for (i = 0; i < length; i += 1) { - charCode = this.charCodeAt(i); - if (charCode <= 255) { - charCodes.push(charCode); - } else { - charCodes.push(charCode / 256); - charCodes.push(charCode % 256); - } - } - - length = charCodes.length; - buffer = new ArrayBuffer(length); - view = new Uint8Array(buffer); - for (i = 0; i < length; i += 1) { - view[i] = charCodes[i]; - } - - return buffer; - }; -} - -if (typeof DataView.prototype.indexOf !== "function") { - DataView.prototype.indexOf = function (searchString, position) { - var searchLength = searchString.length, - byteArrayLength = this.byteLength, - maxSearchIndex = byteArrayLength - searchLength, - searchCharCodes = [], - found, - i, - j; - - searchCharCodes[searchLength] = 0; - for (j = 0; j < searchLength; j += 1) { - searchCharCodes[j] = searchString.charCodeAt(j); - } - - i = position; - found = false; - while (i < maxSearchIndex && !found) { - j = 0; - while (j < searchLength && this.getUint8(i + j) === searchCharCodes[j]) { - j += 1; - } - found = (j === searchLength); - i += 1; - } - - return found ? i - 1 : -1; - }; -} - -if (typeof DataView.prototype.string !== "function") { - DataView.prototype.string = function (start, length) { - var charCodes = [], - end, - i; - - if (start === undefined) { - start = 0; - } - if (length === undefined) { - length = this.length; - } - - end = start + length; - for (i = start; i < end; i += 1) { - charCodes.push(this.getUint8(i)); - } - - return String.fromCharCode.apply(String, charCodes); - }; -} - -var progressDialog = (function () { - var that = {}, - progressBackground, - progressMessage, - cancelButton, - displayed = false, - backgroundWidth = 300, - backgroundHeight = 100, - messageHeight = 32, - cancelWidth = 70, - cancelHeight = 32, - textColor = { red: 255, green: 255, blue: 255 }, - textBackground = { red: 52, green: 52, blue: 52 }, - backgroundUrl = toolIconUrl + "progress-background.svg", - windowDimensions; - - progressBackground = Overlays.addOverlay("image", { - width: backgroundWidth, - height: backgroundHeight, - imageURL: backgroundUrl, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - progressMessage = Overlays.addOverlay("text", { - width: backgroundWidth - 40, - height: messageHeight, - text: "", - textColor: textColor, - backgroundColor: textBackground, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - cancelButton = Overlays.addOverlay("text", { - width: cancelWidth, - height: cancelHeight, - text: "Cancel", - textColor: textColor, - backgroundColor: textBackground, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - function move() { - var progressX, - progressY; - - if (displayed) { - - if (windowDimensions.x === Window.innerWidth && windowDimensions.y === Window.innerHeight) { - return; - } - windowDimensions.x = Window.innerWidth; - windowDimensions.y = Window.innerHeight; - - progressX = (windowDimensions.x - backgroundWidth) / 2; // Center. - progressY = windowDimensions.y / 2 - backgroundHeight; // A little up from center. - - Overlays.editOverlay(progressBackground, { x: progressX, y: progressY }); - Overlays.editOverlay(progressMessage, { x: progressX + 20, y: progressY + 15 }); - Overlays.editOverlay(cancelButton, { - x: progressX + backgroundWidth - cancelWidth - 20, - y: progressY + backgroundHeight - cancelHeight - 15 - }); - } - } - that.move = move; - - that.onCancel = undefined; - - function open(message) { - if (!displayed) { - windowDimensions = { x: 0, y : 0 }; - displayed = true; - move(); - Overlays.editOverlay(progressBackground, { visible: true }); - Overlays.editOverlay(progressMessage, { visible: true, text: message }); - Overlays.editOverlay(cancelButton, { visible: true }); - } else { - throw new Error("open() called on progressDialog when already open"); - } - } - that.open = open; - - function isOpen() { - return displayed; - } - that.isOpen = isOpen; - - function update(message) { - if (displayed) { - Overlays.editOverlay(progressMessage, { text: message }); - } else { - throw new Error("update() called on progressDialog when not open"); - } - } - that.update = update; - - function close() { - if (displayed) { - Overlays.editOverlay(cancelButton, { visible: false }); - Overlays.editOverlay(progressMessage, { visible: false }); - Overlays.editOverlay(progressBackground, { visible: false }); - displayed = false; - } else { - throw new Error("close() called on progressDialog when not open"); - } - } - that.close = close; - - function mousePressEvent(event) { - if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === cancelButton) { - if (typeof this.onCancel === "function") { - close(); - this.onCancel(); - } - return true; - } - return false; - } - that.mousePressEvent = mousePressEvent; - - function cleanup() { - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(progressMessage); - Overlays.deleteOverlay(progressBackground); - } - that.cleanup = cleanup; - - return that; -}()); - -var httpMultiPart = (function () { - var that = {}, - parts, - byteLength, - boundaryString, - crlf; - - function clear() { - boundaryString = "--boundary_" + String(Uuid.generate()).slice(1, 36) + "="; - parts = []; - byteLength = 0; - crlf = ""; - } - that.clear = clear; - - function boundary() { - return boundaryString.slice(2); - } - that.boundary = boundary; - - function length() { - return byteLength; - } - that.length = length; - - function add(object) { - // - name, string - // - name, buffer - var buffer, - string, - stringBuffer, - compressedBuffer; - - if (object.name === undefined) { - - throw new Error("Item to add to HttpMultiPart must have a name"); - - } else if (object.string !== undefined) { - //--= - //Content-Disposition: form-data; name="model_name" - // - // - - string = crlf + boundaryString + "\r\n" - + "Content-Disposition: form-data; name=\"" + object.name + "\"\r\n" - + "\r\n" - + object.string; - buffer = string.toArrayBuffer(); - - } else if (object.buffer !== undefined) { - //--= - //Content-Disposition: form-data; name="fbx"; filename="" - //Content-Type: application/octet-stream - // - // - - string = crlf + boundaryString + "\r\n" - + "Content-Disposition: form-data; name=\"" + object.name - + "\"; filename=\"" + object.buffer.filename + "\"\r\n" - + "Content-Type: application/octet-stream\r\n" - + "\r\n"; - stringBuffer = string.toArrayBuffer(); - - compressedBuffer = object.buffer.buffer.compress(); - buffer = new Uint8Array(stringBuffer.byteLength + compressedBuffer.byteLength); - buffer.set(new Uint8Array(stringBuffer)); - buffer.set(new Uint8Array(compressedBuffer), stringBuffer.byteLength); - - } else { - - throw new Error("Item to add to HttpMultiPart not recognized"); - } - - byteLength += buffer.byteLength; - parts.push(buffer); - - crlf = "\r\n"; - - return true; - } - that.add = add; - - function response() { - var buffer, - index, - str, - i; - - str = crlf + boundaryString + "--\r\n"; - buffer = str.toArrayBuffer(); - byteLength += buffer.byteLength; - parts.push(buffer); - - buffer = new Uint8Array(byteLength); - index = 0; - for (i = 0; i < parts.length; i += 1) { - buffer.set(new Uint8Array(parts[i]), index); - index += parts[i].byteLength; - } - - return buffer; - } - that.response = response; - - clear(); - - return that; -}()); - -var modelUploader = (function () { - var that = {}, - modelFile, - modelName, - modelURL, - modelCallback, - isProcessing, - fstBuffer, - fbxBuffer, - //svoBuffer, - mapping, - geometry, - API_URL = "https://data.highfidelity.io/api/v1/models", - MODEL_URL = "http://public.highfidelity.io/models/content", - NAME_FIELD = "name", - SCALE_FIELD = "scale", - FILENAME_FIELD = "filename", - TEXDIR_FIELD = "texdir", - MAX_TEXTURE_SIZE = 1024; - - function info(message) { - if (progressDialog.isOpen()) { - progressDialog.update(message); - } else { - progressDialog.open(message); - } - print(message); - } - - function error(message) { - if (progressDialog.isOpen()) { - progressDialog.close(); - } - print(message); - Window.alert(message); - } - - function randomChar(length) { - var characters = "0123457689abcdefghijklmnopqrstuvwxyz", - string = "", - i; - - for (i = 0; i < length; i += 1) { - string += characters[Math.floor(Math.random() * 36)]; - } - - return string; - } - - function resetDataObjects() { - fstBuffer = null; - fbxBuffer = null; - //svoBuffer = null; - mapping = {}; - geometry = {}; - geometry.textures = []; - geometry.embedded = []; - } - - function readFile(filename) { - var url = "file:///" + filename, - req = new XMLHttpRequest(); - - req.open("GET", url, false); - req.responseType = "arraybuffer"; - req.send(); - if (req.status !== 200) { - error("Could not read file: " + filename + " : " + req.statusText); - return null; - } - - return { - filename: filename.fileName(), - buffer: req.response - }; - } - - function readMapping(buffer) { - var dv = new DataView(buffer.buffer), - lines, - line, - tokens, - i, - name, - value, - remainder, - existing; - - mapping = {}; // { name : value | name : { value : [remainder] } } - lines = dv.string(0, dv.byteLength).split(/\r\n|\r|\n/); - for (i = 0; i < lines.length; i += 1) { - line = lines[i].trim(); - if (line.length > 0 && line[0] !== "#") { - tokens = line.split(/\s*=\s*/); - if (tokens.length > 1) { - name = tokens[0]; - value = tokens[1]; - if (tokens.length > 2) { - remainder = tokens.slice(2, tokens.length).join(" = "); - } else { - remainder = null; - } - if (tokens.length === 2 && mapping[name] === undefined) { - mapping[name] = value; - } else { - if (mapping[name] === undefined) { - mapping[name] = {}; - - } else if (typeof mapping[name] !== "object") { - existing = mapping[name]; - mapping[name] = { existing : null }; - } - - if (mapping[name][value] === undefined) { - mapping[name][value] = []; - } - mapping[name][value].push(remainder); - } - } - } - } - } - - function writeMapping(buffer) { - var name, - value, - remainder, - i, - string = ""; - - for (name in mapping) { - if (mapping.hasOwnProperty(name)) { - if (typeof mapping[name] === "object") { - for (value in mapping[name]) { - if (mapping[name].hasOwnProperty(value)) { - remainder = mapping[name][value]; - if (remainder === null) { - string += (name + " = " + value + "\n"); - } else { - for (i = 0; i < remainder.length; i += 1) { - string += (name + " = " + value + " = " + remainder[i] + "\n"); - } - } - } - } - } else { - string += (name + " = " + mapping[name] + "\n"); - } - } - } - - buffer.buffer = string.toArrayBuffer(); - } - - function readGeometry(fbxBuffer) { - var textures, - view, - index, - EOF, - previousNodeFilename; - - // Reference: - // http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/ - - textures = {}; - view = new DataView(fbxBuffer.buffer); - EOF = false; - - function parseBinaryFBX() { - var endOffset, - numProperties, - propertyListLength, - nameLength, - name, - filename; - - endOffset = view.getUint32(index, true); - numProperties = view.getUint32(index + 4, true); - propertyListLength = view.getUint32(index + 8, true); - nameLength = view.getUint8(index + 12); - index += 13; - - if (endOffset === 0) { - return; - } - if (endOffset < index || endOffset > view.byteLength) { - EOF = true; - return; - } - - name = view.string(index, nameLength).toLowerCase(); - index += nameLength; - - if (name === "content" && previousNodeFilename !== "") { - // Blender 2.71 exporter "embeds" external textures as empty binary blobs so ignore these - if (propertyListLength > 5) { - geometry.embedded.push(previousNodeFilename); - } - } - - if (name === "relativefilename") { - filename = view.string(index + 5, view.getUint32(index + 1, true)).fileName(); - if (!textures.hasOwnProperty(filename)) { - textures[filename] = ""; - geometry.textures.push(filename); - } - previousNodeFilename = filename; - } else { - previousNodeFilename = ""; - } - - index += (propertyListLength); - - while (index < endOffset && !EOF) { - parseBinaryFBX(); - } - } - - function readTextFBX() { - var line, - view, - viewLength, - charCode, - charCodes, - numCharCodes, - filename, - relativeFilename = "", - MAX_CHAR_CODES = 250; - - view = new Uint8Array(fbxBuffer.buffer); - viewLength = view.byteLength; - charCodes = []; - numCharCodes = 0; - - for (index = 0; index < viewLength; index += 1) { - charCode = view[index]; - if (charCode !== 9 && charCode !== 32) { - if (charCode === 10) { // EOL. Can ignore EOF. - line = String.fromCharCode.apply(String, charCodes).toLowerCase(); - // For embedded textures, "Content:" line immediately follows "RelativeFilename:" line. - if (line.slice(0, 8) === "content:" && relativeFilename !== "") { - geometry.embedded.push(relativeFilename); - } - if (line.slice(0, 17) === "relativefilename:") { - filename = line.slice(line.indexOf("\""), line.lastIndexOf("\"") - line.length).fileName(); - if (!textures.hasOwnProperty(filename)) { - textures[filename] = ""; - geometry.textures.push(filename); - } - relativeFilename = filename; - } else { - relativeFilename = ""; - } - charCodes = []; - numCharCodes = 0; - } else { - if (numCharCodes < MAX_CHAR_CODES) { // Only interested in start of line - charCodes.push(charCode); - numCharCodes += 1; - } - } - } - } - } - - if (view.string(0, 18) === "Kaydara FBX Binary") { - previousNodeFilename = ""; - - index = 27; - while (index < view.byteLength - 39 && !EOF) { - parseBinaryFBX(); - } - - } else { - - readTextFBX(); - - } - } - - function readModel() { - var fbxFilename, - //svoFilename, - fileType; - - info("Reading model file"); - print("Model file: " + modelFile); - - if (modelFile.toLowerCase().fileType() === "fst") { - fstBuffer = readFile(modelFile); - if (fstBuffer === null) { - return false; - } - readMapping(fstBuffer); - fileType = mapping[FILENAME_FIELD].toLowerCase().fileType(); - if (mapping.hasOwnProperty(FILENAME_FIELD)) { - if (fileType === "fbx") { - fbxFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD]; - //} else if (fileType === "svo") { - // svoFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD]; - } else { - error("Unrecognized model type in FST file!"); - return false; - } - } else { - error("Model file name not found in FST file!"); - return false; - } - } else { - fstBuffer = { - filename: "Interface." + randomChar(6), // Simulate avatar model uploading behaviour - buffer: null - }; - - if (modelFile.toLowerCase().fileType() === "fbx") { - fbxFilename = modelFile; - mapping[FILENAME_FIELD] = modelFile.fileName(); - - //} else if (modelFile.toLowerCase().fileType() === "svo") { - // svoFilename = modelFile; - // mapping[FILENAME_FIELD] = modelFile.fileName(); - - } else { - error("Unrecognized file type: " + modelFile); - return false; - } - } - - if (!isProcessing) { return false; } - - if (fbxFilename) { - fbxBuffer = readFile(fbxFilename); - if (fbxBuffer === null) { - return false; - } - - if (!isProcessing) { return false; } - - readGeometry(fbxBuffer); - } - - //if (svoFilename) { - // svoBuffer = readFile(svoFilename); - // if (svoBuffer === null) { - // return false; - // } - //} - - // Add any missing basic mappings - if (!mapping.hasOwnProperty(NAME_FIELD)) { - mapping[NAME_FIELD] = modelFile.fileName().fileBase(); - } - if (!mapping.hasOwnProperty(TEXDIR_FIELD)) { - mapping[TEXDIR_FIELD] = "."; - } - if (!mapping.hasOwnProperty(SCALE_FIELD)) { - mapping[SCALE_FIELD] = 1.0; - } - - return true; - } - - function setProperties() { - var form = [], - directory, - displayAs, - validateAs; - - progressDialog.close(); - print("Setting model properties"); - - form.push({ label: "Name:", value: mapping[NAME_FIELD] }); - - directory = modelFile.path() + "/" + mapping[TEXDIR_FIELD]; - displayAs = new RegExp("^" + modelFile.path().regExpEscape() + "[\\\\\\\/](.*)"); - validateAs = new RegExp("^" + modelFile.path().regExpEscape() + "([\\\\\\\/].*)?"); - - form.push({ - label: "Texture directory:", - directory: modelFile.path() + "/" + mapping[TEXDIR_FIELD], - title: "Choose Texture Directory", - displayAs: displayAs, - validateAs: validateAs, - errorMessage: "Texture directory must be subdirectory of the model directory." - }); - - form.push({ button: "Cancel" }); - - if (!Window.form("Set Model Properties", form)) { - print("User cancelled uploading model"); - return false; - } - - mapping[NAME_FIELD] = form[0].value; - mapping[TEXDIR_FIELD] = form[1].directory.slice(modelFile.path().length + 1); - if (mapping[TEXDIR_FIELD] === "") { - mapping[TEXDIR_FIELD] = "."; - } - - writeMapping(fstBuffer); - - return true; - } - - function createHttpMessage(callback) { - var multiparts = [], - lodCount, - lodFile, - lodBuffer, - textureBuffer, - textureSourceFormat, - textureTargetFormat, - embeddedTextures, - i; - - info("Preparing to send model"); - - // Model name - if (mapping.hasOwnProperty(NAME_FIELD)) { - multiparts.push({ - name : "model_name", - string : mapping[NAME_FIELD] - }); - } else { - error("Model name is missing"); - httpMultiPart.clear(); - return; - } - - // FST file - if (fstBuffer) { - multiparts.push({ - name : "fst", - buffer: fstBuffer - }); - } - - // FBX file - if (fbxBuffer) { - multiparts.push({ - name : "fbx", - buffer: fbxBuffer - }); - } - - // SVO file - //if (svoBuffer) { - // multiparts.push({ - // name : "svo", - // buffer: svoBuffer - // }); - //} - - // LOD files - lodCount = 0; - for (lodFile in mapping.lod) { - if (mapping.lod.hasOwnProperty(lodFile)) { - lodBuffer = readFile(modelFile.path() + "\/" + lodFile); - if (lodBuffer === null) { - return; - } - multiparts.push({ - name: "lod" + lodCount, - buffer: lodBuffer - }); - lodCount += 1; - } - if (!isProcessing) { return; } - } - - // Textures - embeddedTextures = "|" + geometry.embedded.join("|") + "|"; - for (i = 0; i < geometry.textures.length; i += 1) { - if (embeddedTextures.indexOf("|" + geometry.textures[i].fileName() + "|") === -1) { - textureBuffer = readFile(modelFile.path() + "\/" - + (mapping[TEXDIR_FIELD] !== "." ? mapping[TEXDIR_FIELD] + "\/" : "") - + geometry.textures[i]); - if (textureBuffer === null) { - return; - } - - textureSourceFormat = geometry.textures[i].fileType().toLowerCase(); - textureTargetFormat = (textureSourceFormat === "jpg" ? "jpg" : "png"); - textureBuffer.buffer = - textureBuffer.buffer.recodeImage(textureSourceFormat, textureTargetFormat, MAX_TEXTURE_SIZE); - textureBuffer.filename = textureBuffer.filename.slice(0, -textureSourceFormat.length) + textureTargetFormat; - - multiparts.push({ - name: "texture" + i, - buffer: textureBuffer - }); - } - - if (!isProcessing) { return; } - } - - // Model category - multiparts.push({ - name : "model_category", - string : "content" - }); - - // Create HTTP message - httpMultiPart.clear(); - Script.setTimeout(function addMultipart() { - var multipart = multiparts.shift(); - httpMultiPart.add(multipart); - - if (!isProcessing) { return; } - - if (multiparts.length > 0) { - Script.setTimeout(addMultipart, 25); - } else { - callback(); - } - }, 25); - } - - function sendToHighFidelity() { - var req, - uploadedChecks, - HTTP_GET_TIMEOUT = 60, // 1 minute - HTTP_SEND_TIMEOUT = 900, // 15 minutes - UPLOADED_CHECKS = 30, - CHECK_UPLOADED_TIMEOUT = 1, // 1 second - handleCheckUploadedResponses, - handleUploadModelResponses, - handleRequestUploadResponses; - - function uploadTimedOut() { - error("Model upload failed: Internet request timed out!"); - } - - function debugResponse() { - print("req.errorCode = " + req.errorCode); - print("req.readyState = " + req.readyState); - print("req.status = " + req.status); - print("req.statusText = " + req.statusText); - print("req.responseType = " + req.responseType); - print("req.responseText = " + req.responseText); - print("req.response = " + req.response); - print("req.getAllResponseHeaders() = " + req.getAllResponseHeaders()); - } - - function checkUploaded() { - if (!isProcessing) { return; } - - info("Checking uploaded model"); - - req = new XMLHttpRequest(); - req.open("HEAD", modelURL, true); - req.timeout = HTTP_GET_TIMEOUT * 1000; - req.onreadystatechange = handleCheckUploadedResponses; - req.ontimeout = uploadTimedOut; - req.send(); - } - - handleCheckUploadedResponses = function () { - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - // Note: Unlike avatar models, for content models we don't need to refresh texture cache. - print("Model uploaded: " + modelURL); - progressDialog.close(); - if (Window.confirm("Your model has been uploaded as: " + modelURL + "\nDo you want to rez it?")) { - modelCallback(modelURL); - } - } else if (req.status === 404) { - if (uploadedChecks > 0) { - uploadedChecks -= 1; - Script.setTimeout(checkUploaded, CHECK_UPLOADED_TIMEOUT * 1000); - } else { - print("Error: " + req.status + " " + req.statusText); - error("We could not verify that your model was successfully uploaded but it may have been at: " - + modelURL); - } - } else { - print("Error: " + req.status + " " + req.statusText); - error("There was a problem with your upload, please try again later."); - } - } - }; - - function uploadModel(method) { - var url; - - if (!isProcessing) { return; } - - req = new XMLHttpRequest(); - if (method === "PUT") { - url = API_URL + "\/" + modelName; - req.open("PUT", url, true); //print("PUT " + url); - } else { - url = API_URL; - req.open("POST", url, true); //print("POST " + url); - } - req.setRequestHeader("Content-Type", "multipart/form-data; boundary=\"" + httpMultiPart.boundary() + "\""); - req.timeout = HTTP_SEND_TIMEOUT * 1000; - req.onreadystatechange = handleUploadModelResponses; - req.ontimeout = uploadTimedOut; - req.send(httpMultiPart.response().buffer); - } - - handleUploadModelResponses = function () { - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - uploadedChecks = UPLOADED_CHECKS; - checkUploaded(); - } else { - print("Error: " + req.status + " " + req.statusText); - error("There was a problem with your upload, please try again later."); - } - } - }; - - function requestUpload() { - var url; - - if (!isProcessing) { return; } - - url = API_URL + "\/" + modelName; // XMLHttpRequest automatically handles authorization of API requests. - req = new XMLHttpRequest(); - req.open("GET", url, true); //print("GET " + url); - req.responseType = "json"; - req.timeout = HTTP_GET_TIMEOUT * 1000; - req.onreadystatechange = handleRequestUploadResponses; - req.ontimeout = uploadTimedOut; - req.send(); - } - - handleRequestUploadResponses = function () { - var response; - - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - if (req.responseType === "json") { - response = JSON.parse(req.responseText); - if (response.status === "success") { - if (response.exists === false) { - uploadModel("POST"); - } else if (response.can_update === true) { - uploadModel("PUT"); - } else { - error("This model file already exists and is owned by someone else!"); - } - return; - } - } - } else { - print("Error: " + req.status + " " + req.statusText); - } - error("Model upload failed! Something went wrong at the data server."); - } - }; - - info("Sending model to High Fidelity"); - - requestUpload(); - } - - that.upload = function (file, callback) { - - modelFile = file; - modelCallback = callback; - - isProcessing = true; - - progressDialog.onCancel = function () { - print("User cancelled uploading model"); - isProcessing = false; - }; - - resetDataObjects(); - - if (readModel()) { - if (setProperties()) { - modelName = mapping[NAME_FIELD]; - modelURL = MODEL_URL + "\/" + mapping[NAME_FIELD] + ".fst"; // All models are uploaded as an FST - - createHttpMessage(sendToHighFidelity); - } - } - - resetDataObjects(); - }; - - return that; -}()); - -var toolBar = (function () { - var that = {}, - toolBar, - activeButton, - newModelButton, - newCubeButton, - newSphereButton, - newTextButton, - browseModelsButton, - loadURLMenuItem, - loadFileMenuItem, - menuItemWidth, - menuItemOffset, - menuItemHeight, - menuItemMargin = 5, - menuTextColor = { red: 255, green: 255, blue: 255 }, - menuBackgroundColor = { red: 18, green: 66, blue: 66 }; - - function initialize() { - toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); - - activeButton = toolBar.addTool({ - imageURL: toolIconUrl + "models-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - newModelButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - browseModelsButton = toolBar.addTool({ - imageURL: toolIconUrl + "list-icon.svg", - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - menuItemOffset = toolBar.height / 3 + 2; - menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2; - - loadURLMenuItem = Overlays.addOverlay("text", { - height: menuItemHeight, - backgroundColor: menuBackgroundColor, - topMargin: menuItemMargin, - text: "Model URL", - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - loadFileMenuItem = Overlays.addOverlay("text", { - height: menuItemHeight, - backgroundColor: menuBackgroundColor, - topMargin: menuItemMargin, - text: "Model File", - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - menuItemWidth = Math.max(Overlays.textSize(loadURLMenuItem, "Model URL").width, - Overlays.textSize(loadFileMenuItem, "Model File").width) + 20; - Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); - Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); - - newCubeButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-cube.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - newSphereButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-sphere.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - newTextButton = toolBar.addTool({ - //imageURL: toolIconUrl + "add-text.svg", - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/add-text.svg", // temporarily - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - } - - function toggleNewModelButton(active) { - if (active === undefined) { - active = !toolBar.toolSelected(newModelButton); - } - toolBar.selectTool(newModelButton, active); - - Overlays.editOverlay(loadURLMenuItem, { visible: active }); - Overlays.editOverlay(loadFileMenuItem, { visible: active }); - } - - var RESIZE_INTERVAL = 50; - var RESIZE_TIMEOUT = 20000; - var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; - function addModel(url) { - var position; - - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - var entityId = Entities.addEntity({ - type: "Model", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - modelURL: url - }); - print("Model added: " + url); - - var checkCount = 0; - function resize() { - var entityProperties = Entities.getEntityProperties(entityId); - var naturalDimensions = entityProperties.naturalDimensions; - - checkCount++; - - if (naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) { - if (checkCount < RESIZE_MAX_CHECKS) { - Script.setTimeout(resize, RESIZE_INTERVAL); - } else { - print("Resize failed: timed out waiting for model (" + url + ") to load"); - } - } else { - entityProperties.dimensions = naturalDimensions; - Entities.editEntity(entityId, entityProperties); - } - } - - Script.setTimeout(resize, RESIZE_INTERVAL); - - } else { - print("Can't add model: Model would be out of bounds."); - } - } - - that.move = function () { - var newViewPort, - toolsX, - toolsY; - - newViewPort = Controller.getViewportDimensions(); - - if (toolBar === undefined) { - initialize(); - - } else if (windowDimensions.x === newViewPort.x && - windowDimensions.y === newViewPort.y) { - return; - } - - windowDimensions = newViewPort; - toolsX = windowDimensions.x - 8 - toolBar.width; - toolsY = (windowDimensions.y - toolBar.height) / 2; - - toolBar.move(toolsX, toolsY); - - Overlays.editOverlay(loadURLMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset }); - Overlays.editOverlay(loadFileMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset + menuItemHeight }); - }; - - that.mousePressEvent = function (event) { - var clickedOverlay, - url, - file; - - clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (activeButton === toolBar.clicked(clickedOverlay)) { - isActive = !isActive; - return true; - } - - if (newModelButton === toolBar.clicked(clickedOverlay)) { - toggleNewModelButton(); - return true; - } - - if (clickedOverlay === loadURLMenuItem) { - toggleNewModelButton(false); - url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]); - if (url !== null && url !== "") { - addModel(url); - } - return true; - } - - if (clickedOverlay === loadFileMenuItem) { - toggleNewModelButton(false); - - file = Window.browse("Select your model file ...", - Settings.getValue("LastModelUploadLocation").path(), - "Model files (*.fst *.fbx)"); - //"Model files (*.fst *.fbx *.svo)"); - if (file !== null) { - Settings.setValue("LastModelUploadLocation", file); - modelUploader.upload(file, addModel); - } - return true; - } - - if (browseModelsButton === toolBar.clicked(clickedOverlay)) { - toggleNewModelButton(false); - url = Window.s3Browse(".*(fbx|FBX)"); - if (url !== null && url !== "") { - addModel(url); - } - return true; - } - - if (newCubeButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Box", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - color: { red: 255, green: 0, blue: 0 } - - }); - } else { - print("Can't create box: Box would be out of bounds."); - } - return true; - } - - if (newSphereButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Sphere", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - color: { red: 255, green: 0, blue: 0 } - }); - } else { - print("Can't create box: Box would be out of bounds."); - } - return true; - } - - - if (newTextButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Text", - position: position, - dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z }, - backgroundColor: { red: 0, green: 0, blue: 0 }, - textColor: { red: 255, green: 255, blue: 255 }, - text: "some text", - lineHight: "0.1" - }); - } else { - print("Can't create box: Text would be out of bounds."); - } - return true; - } - - return false; - }; - - that.cleanup = function () { - toolBar.cleanup(); - Overlays.deleteOverlay(loadURLMenuItem); - Overlays.deleteOverlay(loadFileMenuItem); - }; - - return that; -}()); - - -var exportMenu = null; - -var ExportMenu = function (opts) { - var self = this; - - var windowDimensions = Controller.getViewportDimensions(); - var pos = { x: windowDimensions.x / 2, y: windowDimensions.y - 100 }; - - this._onClose = opts.onClose || function () { }; - this._position = { x: 0.0, y: 0.0, z: 0.0 }; - this._scale = 1.0; - - var minScale = 1; - var maxScale = 32768; - var titleWidth = 120; - var locationWidth = 100; - var scaleWidth = 144; - var exportWidth = 100; - var cancelWidth = 100; - var margin = 4; - var height = 30; - var outerHeight = height + (2 * margin); - var buttonColor = { red: 128, green: 128, blue: 128 }; - - var SCALE_MINUS = scaleWidth * 40.0 / 100.0; - var SCALE_PLUS = scaleWidth * 63.0 / 100.0; - - var fullWidth = locationWidth + scaleWidth + exportWidth + cancelWidth + (2 * margin); - var offset = fullWidth / 2; - pos.x -= offset; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y - height, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - text: "Export Models" - }); - - var locationButton = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - width: locationWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "0, 0, 0", - }); - var scaleOverlay = Overlays.addOverlay("image", { - x: pos.x + margin + locationWidth, - y: pos.y + margin, - width: scaleWidth, - height: height, - subImage: { x: 0, y: 3, width: 144, height: height }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - }); - var scaleViewWidth = 40; - var scaleView = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + SCALE_MINUS, - y: pos.y + margin, - width: scaleViewWidth, - height: height, - alpha: 0.0, - backgroundAlpha: 0.0, - color: { red: 255, green: 255, blue: 255 }, - text: "1" - }); - var exportButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth, - y: pos.y + margin, - width: exportWidth, - height: height, - color: { red: 0, green: 255, blue: 255 }, - text: "Export" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth + exportWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "Cancel" - }); - - var voxelPreview = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: this._scale, - color: { red: 255, green: 255, blue: 0 }, - alpha: 1, - solid: false, - visible: true, - lineWidth: 4 - }); - - this.parsePosition = function (str) { - var parts = str.split(','); - if (parts.length == 3) { - var x = parseFloat(parts[0]); - var y = parseFloat(parts[1]); - var z = parseFloat(parts[2]); - if (isFinite(x) && isFinite(y) && isFinite(z)) { - return { x: x, y: y, z: z }; - } - } - return null; - }; - - this.showPositionPrompt = function () { - var positionStr = self._position.x + ", " + self._position.y + ", " + self._position.z; - while (1) { - positionStr = Window.prompt("Position to export form:", positionStr); - if (positionStr == null) { - break; - } - var position = self.parsePosition(positionStr); - if (position != null) { - self.setPosition(position.x, position.y, position.z); - break; - } - Window.alert("The position you entered was invalid."); - } - }; - - this.setScale = function (scale) { - self._scale = Math.min(maxScale, Math.max(minScale, scale)); - Overlays.editOverlay(scaleView, { text: self._scale }); - Overlays.editOverlay(voxelPreview, { size: self._scale }); - } - - this.decreaseScale = function () { - self.setScale(self._scale /= 2); - } - - this.increaseScale = function () { - self.setScale(self._scale *= 2); - } - - this.exportEntities = function() { - var x = self._position.x; - var y = self._position.y; - var z = self._position.z; - var s = self._scale; - var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo"; - filename = Window.save("Select where to save", filename, "*.svo") - if (filename) { - var success = Clipboard.exportEntities(filename, x, y, z, s); - if (!success) { - Window.alert("Export failed: no models found in selected area."); - } - } - self.close(); - }; - - this.getPosition = function () { - return self._position; - }; - - this.setPosition = function (x, y, z) { - self._position = { x: x, y: y, z: z }; - var positionStr = x + ", " + y + ", " + z; - Overlays.editOverlay(locationButton, { text: positionStr }); - Overlays.editOverlay(voxelPreview, { position: self._position }); - - }; - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == locationButton) { - self.showPositionPrompt(); - } else if (clickedOverlay == exportButton) { - self.exportEntities(); - } else if (clickedOverlay == cancelButton) { - self.close(); - } else if (clickedOverlay == scaleOverlay) { - var x = event.x - pos.x - margin - locationWidth; - print(x); - if (x < SCALE_MINUS) { - self.decreaseScale(); - } else if (x > SCALE_PLUS) { - self.increaseScale(); - } - } - }; - - this.close = function () { - this.cleanup(); - this._onClose(); - }; - - this.cleanup = function () { - Overlays.deleteOverlay(background); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(locationButton); - Overlays.deleteOverlay(exportButton); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(voxelPreview); - Overlays.deleteOverlay(scaleOverlay); - Overlays.deleteOverlay(scaleView); - }; - - print("CONNECTING!"); - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); -}; - - - -var ModelImporter = function (opts) { - var self = this; - - var height = 30; - var margin = 4; - var outerHeight = height + (2 * margin); - var titleWidth = 120; - var cancelWidth = 100; - var fullWidth = titleWidth + cancelWidth + (2 * margin); - - var localModels = Overlays.addOverlay("localmodels", { - position: { x: 1, y: 1, z: 1 }, - scale: 1, - visible: false - }); - var importScale = 1; - var importBoundaries = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: 1, - color: { red: 128, blue: 128, green: 128 }, - lineWidth: 4, - solid: false, - visible: false - }); - - var pos = { x: windowDimensions.x / 2 - (fullWidth / 2), y: windowDimensions.y - 100 }; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - visible: false, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Import Models" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + titleWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Close" - }); - this._importing = false; - - this.setImportVisible = function (visible) { - Overlays.editOverlay(importBoundaries, { visible: visible }); - Overlays.editOverlay(localModels, { visible: visible }); - Overlays.editOverlay(cancelButton, { visible: visible }); - Overlays.editOverlay(titleText, { visible: visible }); - Overlays.editOverlay(background, { visible: visible }); - }; - - var importPosition = { x: 0, y: 0, z: 0 }; - this.moveImport = function (position) { - importPosition = position; - Overlays.editOverlay(localModels, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - Overlays.editOverlay(importBoundaries, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - } - - this.mouseMoveEvent = function (event) { - if (self._importing) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - - var distance = 2;// * self._scale; - - if (false) {//intersection.intersects) { - var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection)); - if (intersectionDistance < distance) { - distance = intersectionDistance * 0.99; - } - - } - - var targetPosition = { - x: pickRay.origin.x + (pickRay.direction.x * distance), - y: pickRay.origin.y + (pickRay.direction.y * distance), - z: pickRay.origin.z + (pickRay.direction.z * distance) - }; - - if (targetPosition.x < 0) targetPosition.x = 0; - if (targetPosition.y < 0) targetPosition.y = 0; - if (targetPosition.z < 0) targetPosition.z = 0; - - var nudgeFactor = 1; - var newPosition = { - x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor, - y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor, - z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor - } - - self.moveImport(newPosition); - } - } - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == cancelButton) { - self._importing = false; - self.setImportVisible(false); - } - }; - - // Would prefer to use {4} for the coords, but it would only capture the last digit. - var fileRegex = /__(.+)__(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)__/; - this.doImport = function () { - if (!self._importing) { - var filename = Window.browse("Select models to import", "", "*.svo") - if (filename) { - parts = fileRegex.exec(filename); - if (parts == null) { - Window.alert("The file you selected does not contain source domain or location information"); - } else { - var hostname = parts[1]; - var x = parts[2]; - var y = parts[3]; - var z = parts[4]; - var s = parts[5]; - importScale = s; - if (hostname != location.hostname) { - if (!Window.confirm(("These models were not originally exported from this domain. Continue?"))) { - return; - } - } else { - if (Window.confirm(("Would you like to import back to the source location?"))) { - var success = Clipboard.importEntities(filename); - if (success) { - Clipboard.pasteEntities(x, y, z, 1); - } else { - Window.alert("There was an error importing the entity file."); - } - return; - } - } - } - var success = Clipboard.importEntities(filename); - if (success) { - self._importing = true; - self.setImportVisible(true); - Overlays.editOverlay(importBoundaries, { size: s }); - } else { - Window.alert("There was an error importing the entity file."); - } - } - } - } - - this.paste = function () { - if (self._importing) { - // self._importing = false; - // self.setImportVisible(false); - Clipboard.pasteEntities(importPosition.x, importPosition.y, importPosition.z, 1); - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(localModels); - Overlays.deleteOverlay(importBoundaries); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(background); - } - - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); - Controller.mouseMoveEvent.connect(this.mouseMoveEvent); -}; - -var modelImporter = new ModelImporter(); - - -function isLocked(properties) { - // special case to lock the ground plane model in hq. - if (location.hostname == "hq.highfidelity.io" && - properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { - return true; - } - return false; -} - - -function controller(wichSide) { - this.side = wichSide; - this.palm = 2 * wichSide; - this.tip = 2 * wichSide + 1; - this.trigger = wichSide; - this.bumper = 6 * wichSide + 5; - - this.oldPalmPosition = Controller.getSpatialControlPosition(this.palm); - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - - this.oldTipPosition = Controller.getSpatialControlPosition(this.tip); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - - this.oldUp = Controller.getSpatialControlNormal(this.palm); - this.up = this.oldUp; - - this.oldFront = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - this.front = this.oldFront; - - this.oldRight = Vec3.cross(this.front, this.up); - this.right = this.oldRight; - - this.oldRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - this.rotation = this.oldRotation; - - this.triggerValue = Controller.getTriggerValue(this.trigger); - this.bumperValue = Controller.isButtonPressed(this.bumper); - - this.pressed = false; // is trigger pressed - this.pressing = false; // is trigger being pressed (is pressed now but wasn't previously) - - this.grabbing = false; - this.entityID = { isKnownID: false }; - this.modelURL = ""; - this.oldModelRotation; - this.oldModelPosition; - this.oldModelHalfDiagonal; - - this.positionAtGrab; - this.rotationAtGrab; - this.modelPositionAtGrab; - this.rotationAtGrab; - this.jointsIntersectingFromStart = []; - - this.laser = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: LASER_COLOR, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - - this.guideScale = 0.02; - this.ball = Overlays.addOverlay("sphere", { - position: { x: 0, y: 0, z: 0 }, - size: this.guideScale, - solid: true, - color: { red: 0, green: 255, blue: 0 }, - alpha: 1, - visible: false, - anchor: "MyAvatar" - }); - this.leftRight = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: { red: 0, green: 0, blue: 255 }, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - this.topDown = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: { red: 0, green: 0, blue: 255 }, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - - - - this.grab = function (entityID, properties) { - if (isLocked(properties)) { - print("Model locked " + entityID.id); - } else { - print("Grabbing " + entityID.id); - this.grabbing = true; - this.entityID = entityID; - this.modelURL = properties.modelURL; - - this.oldModelPosition = properties.position; - this.oldModelRotation = properties.rotation; - this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - this.positionAtGrab = this.palmPosition; - this.rotationAtGrab = this.rotation; - this.modelPositionAtGrab = properties.position; - this.rotationAtGrab = properties.rotation; - this.jointsIntersectingFromStart = []; - for (var i = 0; i < jointList.length; i++) { - var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < this.oldModelHalfDiagonal) { - this.jointsIntersectingFromStart.push(i); - } - } - this.showLaser(false); - } - } - - this.release = function () { - if (this.grabbing) { - jointList = MyAvatar.getJointNames(); - - var closestJointIndex = -1; - var closestJointDistance = 10; - for (var i = 0; i < jointList.length; i++) { - var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < closestJointDistance) { - closestJointDistance = distance; - closestJointIndex = i; - } - } - - if (closestJointIndex != -1) { - print("closestJoint: " + jointList[closestJointIndex]); - print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelHalfDiagonal + ")"); - } - - if (closestJointDistance < this.oldModelHalfDiagonal) { - - if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1 || - (leftController.grabbing && rightController.grabbing && - leftController.entityID.id == rightController.entityID.id)) { - // Do nothing - } else { - print("Attaching to " + jointList[closestJointIndex]); - var jointPosition = MyAvatar.getJointPosition(jointList[closestJointIndex]); - var jointRotation = MyAvatar.getJointCombinedRotation(jointList[closestJointIndex]); - - var attachmentOffset = Vec3.subtract(this.oldModelPosition, jointPosition); - attachmentOffset = Vec3.multiplyQbyV(Quat.inverse(jointRotation), attachmentOffset); - var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation); - - MyAvatar.attach(this.modelURL, jointList[closestJointIndex], - attachmentOffset, attachmentRotation, 2.0 * this.oldModelHalfDiagonal, - true, false); - Entities.deleteEntity(this.entityID); - } - } - } - - this.grabbing = false; - this.entityID.isKnownID = false; - this.jointsIntersectingFromStart = []; - this.showLaser(true); - } - - this.checkTrigger = function () { - if (this.triggerValue > 0.9) { - if (this.pressed) { - this.pressing = false; - } else { - this.pressing = true; - } - this.pressed = true; - } else { - this.pressing = false; - this.pressed = false; - } - } - - this.checkEntity = function (properties) { - // special case to lock the ground plane model in hq. - if (isLocked(properties)) { - return { valid: false }; - } - - - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = this.palmPosition; - var B = this.front; - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var y = Vec3.dot(Vec3.subtract(P, A), this.up); - var z = Vec3.dot(Vec3.subtract(P, A), this.right); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - return { valid: true, x: x, y: y, z: z }; - } - return { valid: false }; - } - - this.glowedIntersectingModel = { isKnownID: false }; - this.moveLaser = function () { - // the overlays here are anchored to the avatar, which means they are specified in the avatar's local frame - - var inverseRotation = Quat.inverse(MyAvatar.orientation); - var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position)); - var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition)); - var distance = Vec3.length(direction); - direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance); - var endPosition = Vec3.sum(startPosition, direction); - - Overlays.editOverlay(this.laser, { - position: startPosition, - end: endPosition - }); - - - Overlays.editOverlay(this.ball, { - position: endPosition - }); - Overlays.editOverlay(this.leftRight, { - position: Vec3.sum(endPosition, Vec3.multiply(this.right, 2 * this.guideScale)), - end: Vec3.sum(endPosition, Vec3.multiply(this.right, -2 * this.guideScale)) - }); - Overlays.editOverlay(this.topDown, { position: Vec3.sum(endPosition, Vec3.multiply(this.up, 2 * this.guideScale)), - end: Vec3.sum(endPosition, Vec3.multiply(this.up, -2 * this.guideScale)) - }); - this.showLaser(!this.grabbing || mode == 0); - - if (this.glowedIntersectingModel.isKnownID) { - Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.0 }); - this.glowedIntersectingModel.isKnownID = false; - } - if (!this.grabbing) { - var intersection = Entities.findRayIntersection({ - origin: this.palmPosition, - direction: this.front - }); - - var halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - if (intersection.accurate && intersection.entityID.isKnownID && sizeOK) { - this.glowedIntersectingModel = intersection.entityID; - - if (wantEntityGlow) { - Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 }); - } - } - } - } - - this.showLaser = function (show) { - Overlays.editOverlay(this.laser, { visible: show }); - Overlays.editOverlay(this.ball, { visible: show }); - Overlays.editOverlay(this.leftRight, { visible: show }); - Overlays.editOverlay(this.topDown, { visible: show }); - } - this.moveEntity = function () { - if (this.grabbing) { - if (!this.entityID.isKnownID) { - print("Unknown grabbed ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); - this.entityID = Entities.findRayIntersection({ - origin: this.palmPosition, - direction: this.front - }).entityID; - print("Identified ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); - } - var newPosition; - var newRotation; - - switch (mode) { - case 0: - newPosition = Vec3.sum(this.palmPosition, - Vec3.multiply(this.front, this.x)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.up, this.y)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.right, this.z)); - - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.oldRotation)); - newRotation = Quat.multiply(newRotation, - this.oldModelRotation); - break; - case 1: - var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); - var d = Vec3.dot(forward, MyAvatar.position); - - var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; - var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; - var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); - - if (factor2 < 0) { - factor2 = 0; - } - if (factor1 <= 0) { - factor1 = 1; - factor2 = 1; - } - - newPosition = Vec3.sum(this.modelPositionAtGrab, - Vec3.multiply(vector, - factor2 / factor1)); - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.rotationAtGrab)); - newRotation = Quat.multiply(newRotation, - this.rotationAtGrab); - break; - } - Entities.editEntity(this.entityID, { - position: newPosition, - rotation: newRotation - }); - this.oldModelRotation = newRotation; - this.oldModelPosition = newPosition; - - var indicesToRemove = []; - for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { - var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); - if (distance >= this.oldModelHalfDiagonal) { - indicesToRemove.push(this.jointsIntersectingFromStart[i]); - } - - } - for (var i = 0; i < indicesToRemove.length; ++i) { - this.jointsIntersectingFromStart.splice(this.jointsIntersectingFromStart.indexOf(indicesToRemove[i], 1)); - } - } - } - - this.update = function () { - this.oldPalmPosition = this.palmPosition; - this.oldTipPosition = this.tipPosition; - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - - this.oldUp = this.up; - this.up = Vec3.normalize(Controller.getSpatialControlNormal(this.palm)); - - this.oldFront = this.front; - this.front = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - - this.oldRight = this.right; - this.right = Vec3.normalize(Vec3.cross(this.front, this.up)); - - this.oldRotation = this.rotation; - this.rotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - - this.triggerValue = Controller.getTriggerValue(this.trigger); - - var bumperValue = Controller.isButtonPressed(this.bumper); - if (bumperValue && !this.bumperValue) { - if (mode == 0) { - mode = 1; - Overlays.editOverlay(leftController.laser, { color: { red: 0, green: 0, blue: 255 } }); - Overlays.editOverlay(rightController.laser, { color: { red: 0, green: 0, blue: 255 } }); - } else { - mode = 0; - Overlays.editOverlay(leftController.laser, { color: { red: 255, green: 0, blue: 0 } }); - Overlays.editOverlay(rightController.laser, { color: { red: 255, green: 0, blue: 0 } }); - } - } - this.bumperValue = bumperValue; - - - this.checkTrigger(); - - this.moveLaser(); - - if (!this.pressed && this.grabbing) { - // release if trigger not pressed anymore. - this.release(); - } - - if (this.pressing) { - // Checking for attachments intersecting - var attachments = MyAvatar.getAttachmentData(); - var attachmentIndex = -1; - var attachmentX = LASER_LENGTH_FACTOR; - - var newModel; - var newProperties; - - for (var i = 0; i < attachments.length; ++i) { - var position = Vec3.sum(MyAvatar.getJointPosition(attachments[i].jointName), - Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[i].jointName), attachments[i].translation)); - var scale = attachments[i].scale; - - var A = this.palmPosition; - var B = this.front; - var P = position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - - if (d < scale / 2.0 && 0 < x && x < attachmentX) { - attachmentIndex = i; - attachmentX = d; - } - } - - if (attachmentIndex != -1) { - print("Detaching: " + attachments[attachmentIndex].modelURL); - MyAvatar.detachOne(attachments[attachmentIndex].modelURL, attachments[attachmentIndex].jointName); - - newProperties = { - type: "Model", - position: Vec3.sum(MyAvatar.getJointPosition(attachments[attachmentIndex].jointName), - Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].translation)), - rotation: Quat.multiply(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), - attachments[attachmentIndex].rotation), - - // TODO: how do we know the correct dimensions for detachment??? - dimensions: { x: attachments[attachmentIndex].scale / 2.0, - y: attachments[attachmentIndex].scale / 2.0, - z: attachments[attachmentIndex].scale / 2.0 }, - - modelURL: attachments[attachmentIndex].modelURL - }; - - newModel = Entities.addEntity(newProperties); - - - } else { - // There is none so ... - // Checking model tree - Vec3.print("Looking at: ", this.palmPosition); - var pickRay = { origin: this.palmPosition, - direction: Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)) }; - var foundIntersection = Entities.findRayIntersection(pickRay); - - if(!foundIntersection.accurate) { - print("No accurate intersection"); - return; - } - newModel = foundIntersection.entityID; - if (!newModel.isKnownID) { - var identify = Entities.identifyEntity(newModel); - if (!identify.isKnownID) { - print("Unknown ID " + identify.id + " (update loop " + newModel.id + ")"); - return; - } - newModel = identify; - } - newProperties = Entities.getEntityProperties(newModel); - } - print("foundEntity.modelURL=" + newProperties.modelURL); - if (isLocked(newProperties)) { - print("Model locked " + newProperties.id); - } else { - var check = this.checkEntity(newProperties); - if (!check.valid) { - return; - } - - this.grab(newModel, newProperties); - - this.x = check.x; - this.y = check.y; - this.z = check.z; - return; - } - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(this.laser); - Overlays.deleteOverlay(this.ball); - Overlays.deleteOverlay(this.leftRight); - Overlays.deleteOverlay(this.topDown); - } -} - -var leftController = new controller(LEFT); -var rightController = new controller(RIGHT); - -function moveEntities() { - if (leftController.grabbing && rightController.grabbing && rightController.entityID.id == leftController.entityID.id) { - var newPosition = leftController.oldModelPosition; - var rotation = leftController.oldModelRotation; - var ratio = 1; - - - switch (mode) { - case 0: - var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x)); - var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x)); - - var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5); - var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint)); - - - var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x)); - var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x)); - - var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5); - var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint)); - - - ratio = length / oldLength; - newPosition = Vec3.sum(middle, - Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio)); - break; - case 1: - var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); - var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); - - var cos_theta = Vec3.dot(u, v); - if (cos_theta > 1) { - cos_theta = 1; - } - var angle = Math.acos(cos_theta) / Math.PI * 180; - if (angle < 0.1) { - return; - - } - var w = Vec3.normalize(Vec3.cross(u, v)); - - rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); - - - leftController.positionAtGrab = leftController.palmPosition; - leftController.rotationAtGrab = leftController.rotation; - leftController.modelPositionAtGrab = leftController.oldModelPosition; - leftController.rotationAtGrab = rotation; - rightController.positionAtGrab = rightController.palmPosition; - rightController.rotationAtGrab = rightController.rotation; - rightController.modelPositionAtGrab = rightController.oldModelPosition; - rightController.rotationAtGrab = rotation; - break; - } - Entities.editEntity(leftController.entityID, { - position: newPosition, - rotation: rotation, - // TODO: how do we know the correct dimensions for detachment??? - //radius: leftController.oldModelHalfDiagonal * ratio - dimensions: { x: leftController.oldModelHalfDiagonal * ratio, - y: leftController.oldModelHalfDiagonal * ratio, - z: leftController.oldModelHalfDiagonal * ratio } - - - }); - leftController.oldModelPosition = newPosition; - leftController.oldModelRotation = rotation; - leftController.oldModelHalfDiagonal *= ratio; - - rightController.oldModelPosition = newPosition; - rightController.oldModelRotation = rotation; - rightController.oldModelHalfDiagonal *= ratio; - return; - } - leftController.moveEntity(); - rightController.moveEntity(); -} - -var hydraConnected = false; -function checkController(deltaTime) { - var numberOfButtons = Controller.getNumberOfButtons(); - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - - if (!isActive) { - // So that we hide the lasers bellow and keep updating the overlays position - numberOfButtons = 0; - } - - // this is expected for hydras - if (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2) { - if (!hydraConnected) { - hydraConnected = true; - } - - leftController.update(); - rightController.update(); - moveEntities(); - } else { - if (hydraConnected) { - hydraConnected = false; - - leftController.showLaser(false); - rightController.showLaser(false); - } - } - toolBar.move(); - progressDialog.move(); -} - -var entitySelected = false; -var selectedEntityID; -var selectedEntityProperties; -var mouseLastPosition; -var orientation; -var intersection; - - -var SCALE_FACTOR = 200.0; - -function rayPlaneIntersection(pickRay, point, normal) { - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / Vec3.dot(pickRay.direction, normal); - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function Tooltip() { - this.x = 285; - this.y = 115; - this.width = 500; - this.height = 300; // 145; - this.margin = 5; - this.decimals = 3; - - this.textOverlay = Overlays.addOverlay("text", { - x: this.x, - y: this.y, - width: this.width, - height: this.height, - margin: this.margin, - text: "", - color: { red: 228, green: 228, blue: 228 }, - alpha: 0.8, - backgroundAlpha: 0.8, - visible: false - }); - this.show = function (doShow) { - Overlays.editOverlay(this.textOverlay, { visible: doShow }); - } - this.updateText = function(properties) { - var angles = Quat.safeEulerAngles(properties.rotation); - var text = "Entity Properties:\n" - text += "type: " + properties.type + "\n" - text += "X: " + properties.position.x.toFixed(this.decimals) + "\n" - text += "Y: " + properties.position.y.toFixed(this.decimals) + "\n" - text += "Z: " + properties.position.z.toFixed(this.decimals) + "\n" - text += "Pitch: " + angles.x.toFixed(this.decimals) + "\n" - text += "Yaw: " + angles.y.toFixed(this.decimals) + "\n" - text += "Roll: " + angles.z.toFixed(this.decimals) + "\n" - text += "Dimensions: " + properties.dimensions.x.toFixed(this.decimals) + ", " - + properties.dimensions.y.toFixed(this.decimals) + ", " - + properties.dimensions.z.toFixed(this.decimals) + "\n"; - - text += "Natural Dimensions: " + properties.naturalDimensions.x.toFixed(this.decimals) + ", " - + properties.naturalDimensions.y.toFixed(this.decimals) + ", " - + properties.naturalDimensions.z.toFixed(this.decimals) + "\n"; - - text += "ID: " + properties.id + "\n" - if (properties.type == "Model") { - text += "Model URL: " + properties.modelURL + "\n" - text += "Animation URL: " + properties.animationURL + "\n" - text += "Animation is playing: " + properties.animationIsPlaying + "\n" - if (properties.sittingPoints && properties.sittingPoints.length > 0) { - text += properties.sittingPoints.length + " Sitting points: " - for (var i = 0; i < properties.sittingPoints.length; ++i) { - text += properties.sittingPoints[i].name + " " - } - } else { - text += "No sitting points" + "\n" - } - } - if (properties.lifetime > -1) { - text += "Lifetime: " + properties.lifetime + "\n" - } - text += "Age: " + properties.ageAsText + "\n" - text += "Mass: " + properties.mass + "\n" - text += "Script: " + properties.script + "\n" - - - Overlays.editOverlay(this.textOverlay, { text: text }); - } - - this.cleanup = function () { - Overlays.deleteOverlay(this.textOverlay); - } -} -var tooltip = new Tooltip(); - -function mousePressEvent(event) { - if (event.isAlt) { - return; - } - - mouseLastPosition = { x: event.x, y: event.y }; - entitySelected = false; - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } else { - // If we aren't active and didn't click on an overlay: quit - if (!isActive) { - return; - } - - var pickRay = Camera.computePickRay(event.x, event.y); - Vec3.print("[Mouse] Looking at: ", pickRay.origin); - var foundIntersection = Entities.findRayIntersection(pickRay, true); // we want precision picking here - - if(!foundIntersection.accurate) { - return; - } - var foundEntity = foundIntersection.entityID; - - if (!foundEntity.isKnownID) { - var identify = Entities.identifyEntity(foundEntity); - if (!identify.isKnownID) { - print("Unknown ID " + identify.id + " (update loop " + foundEntity.id + ")"); - return; - } - foundEntity = identify; - } - - var properties = Entities.getEntityProperties(foundEntity); - if (isLocked(properties)) { - print("Model locked " + properties.id); - } else { - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal); - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - entitySelected = true; - selectedEntityID = foundEntity; - selectedEntityProperties = properties; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); - } - } - } - if (entitySelected) { - selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; - selectedEntityProperties.oldPosition = { - x: selectedEntityProperties.position.x, - y: selectedEntityProperties.position.y, - z: selectedEntityProperties.position.z, - }; - selectedEntityProperties.oldRotation = { - x: selectedEntityProperties.rotation.x, - y: selectedEntityProperties.rotation.y, - z: selectedEntityProperties.rotation.z, - w: selectedEntityProperties.rotation.w, - }; - selectedEntityProperties.glowLevel = 0.0; - - print("Clicked on " + selectedEntityID.id + " " + entitySelected); - tooltip.updateText(selectedEntityProperties); - tooltip.show(true); - } -} - -var glowedEntityID = { id: -1, isKnownID: false }; -var oldModifier = 0; -var modifier = 0; -var wasShifted = false; -function mouseMoveEvent(event) { - if (event.isAlt || !isActive) { - return; - } - - var pickRay = Camera.computePickRay(event.x, event.y); - if (!entitySelected) { - var entityIntersection = Entities.findRayIntersection(pickRay); - if (entityIntersection.accurate) { - if(glowedEntityID.isKnownID && glowedEntityID.id != entityIntersection.entityID.id) { - Entities.editEntity(glowedEntityID, { glowLevel: 0.0 }); - glowedEntityID.id = -1; - glowedEntityID.isKnownID = false; - } - - var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), - entityIntersection.properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (entityIntersection.entityID.isKnownID && sizeOK) { - if (wantEntityGlow) { - Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 }); - } - glowedEntityID = entityIntersection.entityID; - } - - } - return; - } - - if (event.isLeftButton) { - if (event.isRightButton) { - modifier = 1; // Scale - } else { - modifier = 2; // Translate - } - } else if (event.isRightButton) { - modifier = 3; // rotate - } else { - modifier = 0; - } - pickRay = Camera.computePickRay(event.x, event.y); - if (wasShifted != event.isShifted || modifier != oldModifier) { - selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; - - selectedEntityProperties.oldPosition = { - x: selectedEntityProperties.position.x, - y: selectedEntityProperties.position.y, - z: selectedEntityProperties.position.z, - }; - selectedEntityProperties.oldRotation = { - x: selectedEntityProperties.rotation.x, - y: selectedEntityProperties.rotation.y, - z: selectedEntityProperties.rotation.z, - w: selectedEntityProperties.rotation.w, - }; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, - selectedEntityProperties.oldPosition, - Quat.getFront(orientation)); - - mouseLastPosition = { x: event.x, y: event.y }; - wasShifted = event.isShifted; - oldModifier = modifier; - return; - } - - - switch (modifier) { - case 0: - return; - case 1: - // Let's Scale - selectedEntityProperties.dimensions = Vec3.multiply(selectedEntityProperties.dimensions, - (1.0 + (mouseLastPosition.y - event.y) / SCALE_FACTOR)); - - var halfDiagonal = Vec3.length(selectedEntityProperties.dimensions) / 2.0; - - if (halfDiagonal < 0.01) { - print("Scale too small ... bailling."); - return; - } - break; - - case 2: - // Let's translate - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityProperties.oldPosition, - Quat.getFront(orientation)); - var vector = Vec3.subtract(newIntersection, intersection) - if (event.isShifted) { - var i = Vec3.dot(vector, Quat.getRight(orientation)); - var j = Vec3.dot(vector, Quat.getUp(orientation)); - vector = Vec3.sum(Vec3.multiply(Quat.getRight(orientation), i), - Vec3.multiply(Quat.getFront(orientation), j)); - } - selectedEntityProperties.position = Vec3.sum(selectedEntityProperties.oldPosition, vector); - break; - case 3: - // Let's rotate - if (somethingChanged) { - selectedEntityProperties.oldRotation.x = selectedEntityProperties.rotation.x; - selectedEntityProperties.oldRotation.y = selectedEntityProperties.rotation.y; - selectedEntityProperties.oldRotation.z = selectedEntityProperties.rotation.z; - selectedEntityProperties.oldRotation.w = selectedEntityProperties.rotation.w; - mouseLastPosition.x = event.x; - mouseLastPosition.y = event.y; - somethingChanged = false; - } - - - var pixelPerDegrees = windowDimensions.y / (1 * 360); // the entire height of the window allow you to make 2 full rotations - - //compute delta in pixel - var cameraForward = Quat.getFront(Camera.getOrientation()); - var rotationAxis = (!zIsPressed && xIsPressed) ? { x: 1, y: 0, z: 0 } : - (!zIsPressed && !xIsPressed) ? { x: 0, y: 1, z: 0 } : - { x: 0, y: 0, z: 1 }; - rotationAxis = Vec3.multiplyQbyV(selectedEntityProperties.rotation, rotationAxis); - var orthogonalAxis = Vec3.cross(cameraForward, rotationAxis); - var mouseDelta = { x: event.x - mouseLastPosition - .x, y: mouseLastPosition.y - event.y, z: 0 }; - var transformedMouseDelta = Vec3.multiplyQbyV(Camera.getOrientation(), mouseDelta); - var delta = Math.floor(Vec3.dot(transformedMouseDelta, Vec3.normalize(orthogonalAxis)) / pixelPerDegrees); - - var STEP = 15; - if (!event.isShifted) { - delta = Math.round(delta / STEP) * STEP; - } - - var rotation = Quat.fromVec3Degrees({ - x: (!zIsPressed && xIsPressed) ? delta : 0, // x is pressed - y: (!zIsPressed && !xIsPressed) ? delta : 0, // neither is pressed - z: (zIsPressed && !xIsPressed) ? delta : 0 // z is pressed - }); - rotation = Quat.multiply(selectedEntityProperties.oldRotation, rotation); - - selectedEntityProperties.rotation.x = rotation.x; - selectedEntityProperties.rotation.y = rotation.y; - selectedEntityProperties.rotation.z = rotation.z; - selectedEntityProperties.rotation.w = rotation.w; - break; - } - - Entities.editEntity(selectedEntityID, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); -} - - -function mouseReleaseEvent(event) { - if (event.isAlt || !isActive) { - return; - } - if (entitySelected) { - tooltip.show(false); - } - - entitySelected = false; - - glowedEntityID.id = -1; - glowedEntityID.isKnownID = false; -} - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var modelMenuAddedDelete = false; -var originalLightsArePickable = Entities.getLightsArePickable(); -function setupModelMenus() { - print("setupModelMenus()"); - // adj our menuitems - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Edit Properties...", - shortcutKeyEvent: { text: "`" }, afterItem: "Models" }); - if (!Menu.menuItemExists("Edit", "Delete")) { - print("no delete... adding ours"); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", - shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" }); - modelMenuAddedDelete = true; - } else { - print("delete exists... don't add ours"); - } - - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", - afterItem: "Paste Models", isCheckable: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", - afterItem: "Allow Selecting of Large Models", isCheckable: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", - afterItem: "Allow Selecting of Small Models", isCheckable: true }); - - Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); - - Entities.setLightsArePickable(false); - -} - -function cleanupModelMenus() { - Menu.removeSeparator("Edit", "Models"); - Menu.removeMenuItem("Edit", "Edit Properties..."); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Model List..."); - Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - - Menu.removeSeparator("File", "Models"); - Menu.removeMenuItem("File", "Export Models"); - Menu.removeMenuItem("File", "Import Models"); -} - -function scriptEnding() { - leftController.cleanup(); - rightController.cleanup(); - progressDialog.cleanup(); - toolBar.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - modelImporter.cleanup(); - if (exportMenu) { - exportMenu.close(); - } - Entities.setLightsArePickable(originalLightsArePickable); -} -Script.scriptEnding.connect(scriptEnding); - -// register the call back so it fires before each data send -Script.update.connect(checkController); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -setupModelMenus(); - -var propertiesForEditedEntity; -var editEntityFormArray; -var editModelID = -1; -var dimensionX; -var dimensionY; -var dimensionZ; -var rescalePercentage; - -function showPropertiesForm(editModelID) { - entityPropertyDialogBox.openDialog(editModelID); -} - -function handeMenuEvent(menuItem) { - print("menuItemEvent() in JS... menuItem=" + menuItem); - if (menuItem == "Allow Selecting of Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); - } else if (menuItem == "Allow Selecting of Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); - } else if (menuItem == "Allow Selecting of Lights") { - Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); - } else if (menuItem == "Delete") { - if (leftController.grabbing) { - print(" Delete Entity.... leftController.entityID="+ leftController.entityID); - Entities.deleteEntity(leftController.entityID); - leftController.grabbing = false; - if (glowedEntityID.id == leftController.entityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else if (rightController.grabbing) { - print(" Delete Entity.... rightController.entityID="+ rightController.entityID); - Entities.deleteEntity(rightController.entityID); - rightController.grabbing = false; - if (glowedEntityID.id == rightController.entityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else if (entitySelected) { - print(" Delete Entity.... selectedEntityID="+ selectedEntityID); - Entities.deleteEntity(selectedEntityID); - entitySelected = false; - if (glowedEntityID.id == selectedEntityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else { - print(" Delete Entity.... not holding..."); - } - } else if (menuItem == "Model List...") { - var models = new Array(); - models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE); - for (var i = 0; i < models.length; i++) { - models[i].properties = Entities.getEntityProperties(models[i]); - models[i].toString = function() { - var modelname; - if (this.properties.type == "Model") { - modelname = decodeURIComponent( - this.properties.modelURL.indexOf("/") != -1 ? - this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) : - this.properties.modelURL); - } else { - modelname = this.properties.id; - } - return "[" + this.properties.type + "] " + modelname; - }; - } - var form = [{label: "Model: ", options: models}]; - form.push({label: "Action: ", options: ["Properties", "Delete", "Teleport"]}); - form.push({ button: "Cancel" }); - if (Window.form("Model List", form)) { - var selectedModel = form[0].value; - if (form[1].value == "Properties") { - editModelID = selectedModel; - showPropertiesForm(editModelID); - } else if (form[1].value == "Delete") { - Entities.deleteEntity(selectedModel); - } else if (form[1].value == "Teleport") { - MyAvatar.position = selectedModel.properties.position; - } - } - } else if (menuItem == "Edit Properties...") { - editModelID = -1; - if (leftController.grabbing) { - print(" Edit Properties.... leftController.entityID="+ leftController.entityID); - editModelID = leftController.entityID; - } else if (rightController.grabbing) { - print(" Edit Properties.... rightController.entityID="+ rightController.entityID); - editModelID = rightController.entityID; - } else if (entitySelected) { - print(" Edit Properties.... selectedEntityID="+ selectedEntityID); - editModelID = selectedEntityID; - } else { - print(" Edit Properties.... not holding..."); - } - if (editModelID != -1) { - print(" Edit Properties.... about to edit properties..."); - showPropertiesForm(editModelID); - } - } else if (menuItem == "Paste Models") { - modelImporter.paste(); - } else if (menuItem == "Export Models") { - if (!exportMenu) { - exportMenu = new ExportMenu({ - onClose: function () { - exportMenu = null; - } - }); - } - } else if (menuItem == "Import Models") { - modelImporter.doImport(); - } - tooltip.show(false); -} -Menu.menuItemEvent.connect(handeMenuEvent); - - - -// handling of inspect.js concurrence -var zIsPressed = false; -var xIsPressed = false; -var somethingChanged = false; -Controller.keyPressEvent.connect(function (event) { - if ((event.text == "z" || event.text == "Z") && !zIsPressed) { - zIsPressed = true; - somethingChanged = true; - } - if ((event.text == "x" || event.text == "X") && !xIsPressed) { - xIsPressed = true; - somethingChanged = true; - } - - // resets model orientation when holding with mouse - if (event.text == "r" && entitySelected) { - selectedEntityProperties.rotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 }); - Entities.editEntity(selectedEntityID, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - somethingChanged = true; - } -}); - -Controller.keyReleaseEvent.connect(function (event) { - if (event.text == "z" || event.text == "Z") { - zIsPressed = false; - somethingChanged = true; - } - if (event.text == "x" || event.text == "X") { - xIsPressed = false; - somethingChanged = true; - } - // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items - if (event.text == "`") { - handeMenuEvent("Edit Properties..."); - } - if (event.text == "BACKSPACE") { - handeMenuEvent("Delete"); - } -}); - diff --git a/examples/editVoxels.js b/examples/editVoxels.js deleted file mode 100644 index ff096973a3..0000000000 --- a/examples/editVoxels.js +++ /dev/null @@ -1,1518 +0,0 @@ -// -// editVoxels.js -// examples -// -// Created by Philip Rosedale on February 8, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// Captures mouse clicks and edits voxels accordingly. -// -// click = create a new voxel on this face, same color as old (default color picker state) -// right click or control + click = delete this voxel -// shift + click = recolor this voxel -// 1 - 8 = pick new color from palette -// 9 = create a new voxel in front of the camera -// -// Click and drag to create more new voxels in the same direction -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var editToolsOn = true; // starts out off - -var windowDimensions = Controller.getViewportDimensions(); -var WORLD_SCALE = Voxels.getTreeScale(); - -var NEW_VOXEL_SIZE = 1.0; -var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0; -var PIXELS_PER_EXTRUDE_VOXEL = 16; -var WHEEL_PIXELS_PER_SCALE_CHANGE = 100; -var MAX_VOXEL_SCALE_POWER = 4; -var MIN_VOXEL_SCALE_POWER = -8; -var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); -var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); -var WHITE_COLOR = { red: 255, green: 255, blue: 255 }; - -var MAX_PASTE_VOXEL_SCALE = 256; -var MIN_PASTE_VOXEL_SCALE = .256; - -var zFightingSizeAdjustRatio = 0.004; // used to adjust preview voxels to prevent z fighting -var previewLineWidth = 1.5; - -var inspectJsIsRunning = false; -var isAdding = false; -var isExtruding = false; -var extrudeDirection = { x: 0, y: 0, z: 0 }; -var extrudeScale = 0.0; -var lastVoxelPosition = { x: 0, y: 0, z: 0 }; -var lastVoxelColor = { red: 0, green: 0, blue: 0 }; -var lastVoxelScale = 0; -var dragStart = { x: 0, y: 0 }; -var wheelPixelsMoved = 0; - -// Create a table of the different colors you can choose -var colors = new Array(); -colors[0] = { red: 120, green: 181, blue: 126 }; -colors[1] = { red: 75, green: 155, blue: 103 }; -colors[2] = { red: 56, green: 132, blue: 86 }; -colors[3] = { red: 83, green: 211, blue: 83 }; -colors[4] = { red: 236, green: 174, blue: 0 }; -colors[5] = { red: 234, green: 133, blue: 0 }; -colors[6] = { red: 211, green: 115, blue: 0 }; -colors[7] = { red: 48, green: 116, blue: 119 }; -colors[8] = { red: 36, green: 64, blue: 64 }; -var numColors = 9; -var whichColor = 0; // Starting color is 'Copy' mode - -// Create sounds for for every script actions that require one -// start with audio slightly above the avatar -var audioOptions = { - position: Vec3.sum(MyAvatar.position, { x: 0, y: 1, z: 0 } ), - volume: 1.0 -}; - -function SoundArray() { - this.audioOptions = audioOptions - this.sounds = new Array(); - this.addSound = function (soundURL) { - this.sounds[this.sounds.length] = SoundCache.getSound(soundURL); - } - this.play = function (index) { - if (0 <= index && index < this.sounds.length) { - Audio.playSound(this.sounds[index], this.audioOptions); - } else { - print("[ERROR] editVoxels.js:randSound.play() : Index " + index + " out of range."); - } - } - this.playRandom = function () { - if (this.sounds.length > 0) { - rand = Math.floor(Math.random() * this.sounds.length); - Audio.playSound(this.sounds[rand], this.audioOptions); - } else { - print("[ERROR] editVoxels.js:randSound.playRandom() : Array is empty."); - } - } -} - -var addVoxelSound = new SoundArray(); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+1.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+2.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+3.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+4.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+5.raw"); -addVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Add/VA+6.raw"); - -var delVoxelSound = new SoundArray(); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+A1.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+A2.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+A3.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+B1.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+B2.raw"); -delVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Del/VD+B3.raw"); - -var resizeVoxelSound = new SoundArray(); -resizeVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Size/V+Size+Minus.raw"); -resizeVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Voxel+Size/V+Size+Plus.raw"); -var voxelSizeMinus = 0; -var voxelSizePlus = 1; - -var swatchesSound = new SoundArray(); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+1.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+2.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+3.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+4.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+5.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+6.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+7.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+8.raw"); -swatchesSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Swatches/Swatch+9.raw"); - -var undoSound = new SoundArray(); -undoSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Undo/Undo+1.raw"); -undoSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Undo/Undo+2.raw"); -undoSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Undo/Undo+3.raw"); - -var scriptInitSound = new SoundArray(); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+A.raw"); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+B.raw"); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+C.raw"); -scriptInitSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Script+Init/Script+Init+D.raw"); - -var modeSwitchSound = new SoundArray(); -modeSwitchSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Mode+Switch/Mode+1.raw"); -modeSwitchSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Mode+Switch/Mode+2.raw"); -modeSwitchSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Mode+Switch/Mode+3.raw"); - -var initialVoxelSound = new SoundArray(); -initialVoxelSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Initial+Voxel/Initial+V.raw"); - -var colorInheritSound = new SoundArray(); -colorInheritSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Color+Inherit/Inherit+A.raw"); -colorInheritSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Color+Inherit/Inherit+B.raw"); -colorInheritSound.addSound(HIFI_PUBLIC_BUCKET + "sounds/Voxel+Editing/Color+Inherit/Inherit+C.raw"); - -// previewAsVoxel - by default, we will preview adds/deletes/recolors as just 4 lines on the intersecting face. But if you -// the preview to show a full voxel then set this to true and the voxel will be displayed for voxel editing -var previewAsVoxel = false; - -var voxelPreview = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0}, - size: 1, - color: { red: 255, green: 0, blue: 0}, - alpha: 1, - solid: false, - visible: false, - lineWidth: 4 - }); - -var linePreviewTop = []; -var linePreviewBottom = []; -var linePreviewLeft = []; -var linePreviewRight = []; - -// Currend cursor index -var currentCursor = 0; - -function addLineOverlay() { - return Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); -} - -//Cursor line previews for up to three cursors -linePreviewTop[0] = addLineOverlay(); -linePreviewTop[1] = addLineOverlay(); -linePreviewTop[2] = addLineOverlay(); - -linePreviewBottom[0] = addLineOverlay(); -linePreviewBottom[1] = addLineOverlay(); -linePreviewBottom[2] = addLineOverlay(); - -linePreviewLeft[0] = addLineOverlay(); -linePreviewLeft[1] = addLineOverlay(); -linePreviewLeft[2] = addLineOverlay(); - -linePreviewRight[0] = addLineOverlay(); -linePreviewRight[1] = addLineOverlay(); -linePreviewRight[2] = addLineOverlay(); - -// these will be used below -var scaleSelectorWidth = 144; -var scaleSelectorHeight = 37; - -// These will be our "overlay IDs" -var swatches = new Array(); -var swatchExtraPadding = 5; -var swatchHeight = 37; -var swatchWidth = 27; -var swatchesWidth = swatchWidth * numColors + numColors + swatchExtraPadding * 2; -var swatchesX = (windowDimensions.x - (swatchesWidth + scaleSelectorWidth)) / 2; -var swatchesY = windowDimensions.y - swatchHeight + 1; - -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - -// create the overlays, position them in a row, set their colors, and for the selected one, use a different source image -// location so that it displays the "selected" marker -for (s = 0; s < numColors; s++) { - - var extraWidth = 0; - - if (s == 0) { - extraWidth = swatchExtraPadding; - } - - var imageFromX = swatchExtraPadding - extraWidth + s * swatchWidth; - var imageFromY = swatchHeight + 1; - - var swatchX = swatchExtraPadding - extraWidth + swatchesX + ((swatchWidth - 1) * s); - - if (s == (numColors - 1)) { - extraWidth = swatchExtraPadding; - } - - swatches[s] = Overlays.addOverlay("image", { - x: swatchX, - y: swatchesY, - width: swatchWidth + extraWidth, - height: swatchHeight, - subImage: { x: imageFromX, y: imageFromY, width: swatchWidth + extraWidth, height: swatchHeight }, - imageURL: toolIconUrl + "swatches.svg", - color: colors[s], - alpha: 1, - visible: editToolsOn - }); -} - - -// These will be our tool palette overlays -var numberOfTools = 3; -var toolHeight = 50; -var toolWidth = 50; -var toolVerticalSpacing = 4; -var toolsHeight = toolHeight * numberOfTools + toolVerticalSpacing * (numberOfTools - 1); -var toolsX = 8; -var toolsY = (windowDimensions.y - toolsHeight) / 2; - -var voxelToolAt = 0; -var recolorToolAt = 1; -var eyedropperToolAt = 2; - -var pasteModeColor = { red: 132, green: 61, blue: 255 }; - -var voxelTool = Overlays.addOverlay("image", { - x: 0, y: 0, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-tool.svg", - visible: editToolsOn, - alpha: 0.9 - }); - -var recolorTool = Overlays.addOverlay("image", { - x: 0, y: 0, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "paint-tool.svg", - visible: editToolsOn, - alpha: 0.9 - }); - -var eyedropperTool = Overlays.addOverlay("image", { - x: 0, y: 0, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "eyedropper-tool.svg", - visible: editToolsOn, - alpha: 0.9 - }); - - -var copyScale = true; -function ScaleSelector() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - this.width = scaleSelectorWidth; - this.height = scaleSelectorHeight; - - this.displayPower = false; - this.scale = 1.0; - this.power = 0; - - this.FIRST_PART = this.width * 40.0 / 100.0; - this.SECOND_PART = this.width * 37.0 / 100.0; - - this.buttonsOverlay = Overlays.addOverlay("image", { - x: this.x, y: this.y, - width: this.width, height: this.height, - //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - visible: editToolsOn - }); - this.textOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - topMargin: 13, - text: this.scale.toString(), - backgroundAlpha: 0.0, - visible: editToolsOn - }); - this.powerOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - leftMargin: 28, - text: this.power.toString(), - backgroundAlpha: 0.0, - visible: false - }); - this.setScale = function(scale) { - if (scale > MAX_VOXEL_SCALE) { - scale = MAX_VOXEL_SCALE; - } - if (scale < MIN_VOXEL_SCALE) { - scale = MIN_VOXEL_SCALE; - } - - this.scale = scale; - this.power = Math.floor(Math.log(scale) / Math.log(2)); - rescaleImport(); - this.update(); - } - - this.show = function(doShow) { - Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); - Overlays.editOverlay(this.textOverlay, {visible: doShow}); - Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); - } - - this.move = function() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - - Overlays.editOverlay(this.buttonsOverlay, { - x: this.x, y: this.y, - }); - Overlays.editOverlay(this.textOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - Overlays.editOverlay(this.powerOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - } - - - this.switchDisplay = function() { - this.displayPower = !this.displayPower; - - if (this.displayPower) { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 18, - text: "2" - }); - Overlays.editOverlay(this.powerOverlay, { - text: this.power.toString(), - visible: editToolsOn - }); - } else { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 13, - text: this.scale.toString() - }); - Overlays.editOverlay(this.powerOverlay, { - visible: false - }); - } - } - - this.update = function() { - if (this.displayPower) { - Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); - } else { - Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); - } - } - - this.incrementScale = function() { - copyScale = false; - if (this.power < MAX_VOXEL_SCALE_POWER) { - ++this.power; - this.scale *= 2.0; - this.update(); - rescaleImport(); - resizeVoxelSound.play(voxelSizePlus); - } - } - - this.decrementScale = function() { - copyScale = false; - if (MIN_VOXEL_SCALE_POWER < this.power) { - --this.power; - this.scale /= 2.0; - this.update(); - rescaleImport(); - resizeVoxelSound.play(voxelSizePlus); - } - } - - this.clicked = function(x, y) { - if (this.x < x && x < this.x + this.width && - this.y < y && y < this.y + this.height) { - - if (x < this.x + this.FIRST_PART) { - this.decrementScale(); - } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { - this.switchDisplay(); - } else { - this.incrementScale(); - } - return true; - } - return false; - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.buttonsOverlay); - Overlays.deleteOverlay(this.textOverlay); - Overlays.deleteOverlay(this.powerOverlay); - } - -} -var scaleSelector = new ScaleSelector(); - - -///////////////////////////////////// IMPORT MODULE /////////////////////////////// -// Move the following code to a separate file when include will be available. -var importTree; -var importPreview; -var importBoundaries; -var xImportGuide; -var yImportGuide; -var zImportGuide; -var isImporting; -var importPosition; -var importDistance; - -function initImport() { - importPreview = Overlays.addOverlay("localvoxels", { - name: "import", - position: { x: 0, y: 0, z: 0}, - scale: 1, - visible: false - }); - importBoundaries = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: 1, - color: { red: 128, blue: 128, green: 128 }, - lineWIdth: 4, - solid: false, - visible: false - }); - - xImportGuide = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 255, green: 0, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - yImportGuide = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - zImportGuide = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - - - isImporting = false; - importPosition = { x: 0, y: 0, z: 0 }; -} - -function importVoxels() { - isImporting = Clipboard.importVoxels(); - return isImporting; -} - -function moveImport(position) { - importPosition = position; - Overlays.editOverlay(importPreview, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - Overlays.editOverlay(importBoundaries, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - - - Overlays.editOverlay(xImportGuide, { - position: { x: importPosition.x, y: 0, z: importPosition.z }, - end: { x: importPosition.x + scaleSelector.scale, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(yImportGuide, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z }, - end: { x: importPosition.x, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(zImportGuide, { - position: { x: importPosition.x, y: 0, z: importPosition.z }, - end: { x: importPosition.x, y: 0, z: importPosition.z + scaleSelector.scale } - }); - rescaleImport(); -} - -function rescaleImport() { - if (0 < scaleSelector.scale) { - Overlays.editOverlay(importPreview, { - scale: scaleSelector.scale - }); - Overlays.editOverlay(importBoundaries, { - size: scaleSelector.scale - }); - - Overlays.editOverlay(xImportGuide, { - end: { x: importPosition.x + scaleSelector.scale, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(yImportGuide, { - end: { x: importPosition.x, y: 0, z: importPosition.z } - }); - Overlays.editOverlay(zImportGuide, { - end: { x: importPosition.x, y: 0, z: importPosition.z + scaleSelector.scale } - }); - } -} - -function showImport(doShow) { - Overlays.editOverlay(importPreview, { - visible: doShow - }); - Overlays.editOverlay(importBoundaries, { - visible: doShow - }); - - Overlays.editOverlay(xImportGuide, { - visible: doShow - }); - Overlays.editOverlay(yImportGuide, { - visible: doShow - }); - Overlays.editOverlay(zImportGuide, { - visible: doShow - }); -} - -function placeImport() { - if (isImporting) { - Clipboard.pasteVoxel(importPosition.x, importPosition.y, importPosition.z, scaleSelector.scale); - isImporting = false; - } -} - -function cancelImport() { - if (isImporting) { - isImporting = false; - showImport(false); - } -} - -function cleanupImport() { - Overlays.deleteOverlay(importPreview); - Overlays.deleteOverlay(importBoundaries); - Overlays.deleteOverlay(xImportGuide); - Overlays.deleteOverlay(yImportGuide); - Overlays.deleteOverlay(zImportGuide); - isImporting = false; - importPostion = { x: 0, y: 0, z: 0 }; -} -/////////////////////////////////// END IMPORT MODULE ///////////////////////////// -initImport(); - -if (editToolsOn) { - moveTools(); -} - -function setAudioPosition() { - var position = MyAvatar.position; - var forwardVector = Quat.getFront(MyAvatar.orientation); - audioOptions.position = Vec3.sum(position, forwardVector); -} - -function getNewPasteVoxel(pickRay) { - - var voxelSize = scaleSelector.scale; - var origin = { x: pickRay.direction.x, y: pickRay.direction.y, z: pickRay.direction.z }; - - origin.x += pickRay.origin.x; - origin.y += pickRay.origin.y; - origin.z += pickRay.origin.z; - - origin.x -= voxelSize / 2; - origin.y -= voxelSize / 2; - origin.z += voxelSize / 2; - - return {origin: origin, voxelSize: voxelSize}; -} - -function getNewVoxelPosition() { - var camera = Camera.getPosition(); - var forwardVector = Quat.getFront(MyAvatar.orientation); - var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, NEW_VOXEL_DISTANCE_FROM_CAMERA)); - return newPosition; -} - -var trackLastMouseX = 0; -var trackLastMouseY = 0; -var trackAsDelete = false; -var trackAsRecolor = false; -var trackAsEyedropper = false; - -var voxelToolSelected = false; -var recolorToolSelected = false; -var eyedropperToolSelected = false; -var pasteMode = false; - - -function calculateVoxelFromIntersection(intersection, operation) { - //print("calculateVoxelFromIntersection() operation="+operation); - var resultVoxel; - - var wantDebug = false; - if (wantDebug) { - print(">>>>> calculateVoxelFromIntersection().... intersection voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print(" intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print(" intersection face=" + intersection.face); - print(" intersection distance=" + intersection.distance); - print(" intersection intersection.x/y/z=" + intersection.intersection.x + ", " - + intersection.intersection.y + ", " + intersection.intersection.z); - } - - var voxelSize = scaleSelector.scale; - var x; - var y; - var z; - - // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest - // ancestor voxel of our target size that contains our intersected voxel. - if (voxelSize > intersection.voxel.s) { - if (wantDebug) { - print("voxelSize > intersection.voxel.s.... choose the larger voxel that encompasses the one selected"); - } - x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; - y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; - z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; - } else { - // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. - // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result - // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting - // voxel this still works and results in returning the intersecting voxel which is what we want - var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); - if (wantDebug) { - print("adjustToCenter=" + adjustToCenter.x + "," + adjustToCenter.y + "," + adjustToCenter.z); - } - var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); - x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; - y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; - z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; - } - resultVoxel = { x: x, y: y, z: z, s: voxelSize }; - highlightAt = { x: x, y: y, z: z, s: voxelSize }; - - // we only do the "add to the face we're pointing at" adjustment, if the operation is an add - // operation, and the target voxel size is equal to or smaller than the intersecting voxel. - var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); - if (wantDebug) { - print("wantAddAdjust="+wantAddAdjust); - } - - var zFightingSizeAdjust = zFightingSizeAdjustRatio * intersection.distance; - - // now we also want to calculate the "edge square" for the face for this voxel - if (intersection.face == "MIN_X_FACE") { - - highlightAt.x = x - zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x -= voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z + voxelSize }; - - } else if (intersection.face == "MAX_X_FACE") { - - highlightAt.x = x + voxelSize + zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z + voxelSize }; - - } else if (intersection.face == "MIN_Y_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y - zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y -= voxelSize; - } - - resultVoxel.topRight = {x: highlightAt.x , y: highlightAt.y, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x , y: highlightAt.y, z: highlightAt.z + voxelSize }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize , y: highlightAt.y, z: highlightAt.z + voxelSize }; - - } else if (intersection.face == "MAX_Y_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y + voxelSize + zFightingSizeAdjust; - highlightAt.z = z + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z + voxelSize}; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z + voxelSize}; - - } else if (intersection.face == "MIN_Z_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z - zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z -= voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize, y: highlightAt.y + voxelSize, z: highlightAt.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - highlightAt.x = x + zFightingSizeAdjust; - highlightAt.y = y + zFightingSizeAdjust; - highlightAt.z = z + voxelSize + zFightingSizeAdjust; - voxelSize -= 2 * zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z += resultVoxel.s; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x + voxelSize, y: highlightAt.y, z: highlightAt.z}; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x + voxelSize, y: highlightAt.y + voxelSize, z: highlightAt.z}; - - } - - return resultVoxel; -} - -function showPreviewVoxel() { - var voxelColor; - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - var intersection = Voxels.findRayIntersection(pickRay); - - voxelColor = { red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue }; - - var guidePosition; - if (trackAsRecolor || recolorToolSelected || trackAsEyedropper || eyedropperToolSelected) { - Overlays.editOverlay(voxelPreview, { visible: true }); - } else if (voxelToolSelected && !isExtruding) { - Overlays.editOverlay(voxelPreview, { visible: true }); - } else if (isExtruding) { - Overlays.editOverlay(voxelPreview, { visible: false }); - } -} - -function showPreviewLines() { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - - if (pasteMode) { // free voxel pasting - - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewLeft, { visible: false }); - - var pasteVoxel = getNewPasteVoxel(pickRay); - - // X axis - Overlays.editOverlay(linePreviewBottom[currentCursor], { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x + pasteVoxel.voxelSize, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z }, - visible: true - }); - - // Y axis - Overlays.editOverlay(linePreviewRight[currentCursor], { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y + pasteVoxel.voxelSize, z: pasteVoxel.origin.z }, - visible: true - }); - - // Z axis - Overlays.editOverlay(linePreviewTop[currentCursor], { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z - pasteVoxel.voxelSize }, - visible: true - }); - - return; - } - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - resultVoxel = calculateVoxelFromIntersection(intersection,""); - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewTop[currentCursor], { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight[currentCursor], { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); - colors[0] = {red: intersection.voxel.red, green: intersection.voxel.green , blue: intersection.voxel.blue }; - - if (copyScale) { - scaleSelector.setScale(intersection.voxel.s); - } - moveTools(); - } else if (intersection.accurate) { - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewTop[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewRight[currentCursor], { visible: false }); - } -} - -function showPreviewGuides() { - if (editToolsOn && !isImporting && (voxelToolSelected || recolorToolSelected || eyedropperToolSelected)) { - if (previewAsVoxel) { - showPreviewVoxel(); - - // make sure alternative is hidden - Overlays.editOverlay(linePreviewTop[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewRight[currentCursor], { visible: false }); - } else { - showPreviewLines(); - } - } else { - // make sure all previews are off - Overlays.editOverlay(voxelPreview, { visible: false }); - Overlays.editOverlay(linePreviewTop[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewBottom[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewLeft[currentCursor], { visible: false }); - Overlays.editOverlay(linePreviewRight[currentCursor], { visible: false }); - } -} - -function trackMouseEvent(event) { - trackLastMouseX = event.x; - trackLastMouseY = event.y; - trackAsDelete = event.isControl; - trackAsRecolor = event.isShifted; - trackAsEyedropper = event.isMeta; - showPreviewGuides(); -} - -function trackKeyPressEvent(event) { - if (!editToolsOn) { - return; - } - - if (event.text == "CONTROL") { - trackAsDelete = true; - moveTools(); - } - if (event.text == "SHIFT") { - trackAsRecolor = true; - moveTools(); - } - if (event.text == "META") { - trackAsEyedropper = true; - moveTools(); - } - if (event.text == "ALT") { - inspectJsIsRunning = true; - } - showPreviewGuides(); -} - -function trackKeyReleaseEvent(event) { - // on TAB release, toggle our tool state - if (event.text == "TAB") { - editToolsOn = !editToolsOn; - moveTools(); - setAudioPosition(); // make sure we set the audio position before playing sounds - showPreviewGuides(); - scaleSelector.show(editToolsOn); - scriptInitSound.playRandom(); - } - - if (event.text == "ALT") { - inspectJsIsRunning = false; - } - - if (editToolsOn) { - if (event.text == "ESC") { - pasteMode = false; - moveTools(); - } - if (event.text == "-") { - scaleSelector.decrementScale(); - } - if (event.text == "+") { - scaleSelector.incrementScale(); - } - if (event.text == "CONTROL") { - trackAsDelete = false; - moveTools(); - } - if (event.text == "SHIFT") { - trackAsRecolor = false; - moveTools(); - } - if (event.text == "META") { - trackAsEyedropper = false; - moveTools(); - } - - // on F1 toggle the preview mode between cubes and lines - if (event.text == "F1") { - previewAsVoxel = !previewAsVoxel; - } - - showPreviewGuides(); - } -} - -function mousePressEvent(event) { - // if our tools are off, then don't do anything - if (!editToolsOn) { - return; - } - if (inspectJsIsRunning) { - return; - } - - if (event.deviceID == 1500) { // Left Hydra Controller - currentCursor = 0; - } else if (event.deviceID == 1501) { // Right Hydra Controller - currentCursor = 1; - } else { - currentCursor = 2; - } - - var clickedOnSomething = false; - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if (clickedOverlay == voxelTool) { - modeSwitchSound.play(0); - voxelToolSelected = !voxelToolSelected; - recolorToolSelected = false; - eyedropperToolSelected = false; - moveTools(); - clickedOnSomething = true; - } else if (clickedOverlay == recolorTool) { - modeSwitchSound.play(1); - voxelToolSelected = false; - recolorToolSelected = !recolorToolSelected; - eyedropperToolSelected = false; - moveTools(); - clickedOnSomething = true; - } else if (clickedOverlay == eyedropperTool) { - modeSwitchSound.play(2); - voxelToolSelected = false; - recolorToolSelected = false; - eyedropperToolSelected = !eyedropperToolSelected; - moveTools(); - clickedOnSomething = true; - } else if (scaleSelector.clicked(event.x, event.y)) { - if (isImporting) { - rescaleImport(); - } - clickedOnSomething = true; - } else { - // if the user clicked on one of the color swatches, update the selectedSwatch - for (s = 0; s < numColors; s++) { - if (clickedOverlay == swatches[s]) { - whichColor = s; - moveTools(); - clickedOnSomething = true; - swatchesSound.play(whichColor); - break; - } - } - } - if (clickedOnSomething || isImporting || (!voxelToolSelected && !recolorToolSelected && !eyedropperToolSelected)) { - return; // no further processing - } - - // TODO: does any of this stuff need to execute if we're panning or orbiting? - trackMouseEvent(event); // used by preview support - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - audioOptions.position = Vec3.sum(pickRay.origin, pickRay.direction); - - if (pasteMode) { - var pasteVoxel = getNewPasteVoxel(pickRay); - Clipboard.pasteVoxel(pasteVoxel.origin.x, pasteVoxel.origin.y, pasteVoxel.origin.z, pasteVoxel.voxelSize); - pasteMode = false; - moveTools(); - return; - } - - if (intersection.intersects) { - if (trackAsDelete || event.isRightButton && !trackAsEyedropper) { - // Delete voxel - voxelDetails = calculateVoxelFromIntersection(intersection,"delete"); - Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); - delVoxelSound.playRandom(); - Overlays.editOverlay(voxelPreview, { visible: false }); - } else if (eyedropperToolSelected || trackAsEyedropper) { - colors[whichColor].red = intersection.voxel.red; - colors[whichColor].green = intersection.voxel.green; - colors[whichColor].blue = intersection.voxel.blue; - moveTools(); - swatchesSound.play(whichColor); - - } else if (recolorToolSelected || trackAsRecolor) { - // Recolor Voxel - voxelDetails = calculateVoxelFromIntersection(intersection,"recolor"); - - // doing this erase then set will make sure we only recolor just the target voxel - Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, - colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); - swatchesSound.play(whichColor); - Overlays.editOverlay(voxelPreview, { visible: false }); - } else if (voxelToolSelected) { - // Add voxel on face - newColor = { red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue - }; - - voxelDetails = calculateVoxelFromIntersection(intersection,"add"); - Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, - newColor.red, newColor.green, newColor.blue); - lastVoxelPosition = { x: voxelDetails.x, y: voxelDetails.y, z: voxelDetails.z }; - lastVoxelColor = { red: newColor.red, green: newColor.green, blue: newColor.blue }; - lastVoxelScale = voxelDetails.s; - if (lastVoxelScale > MAX_VOXEL_SCALE) { - lastVoxelScale = MAX_VOXEL_SCALE; - } - - addVoxelSound.playRandom(); - - Overlays.editOverlay(voxelPreview, { visible: false }); - dragStart = { x: event.x, y: event.y }; - isAdding = true; - } - } -} - -function keyPressEvent(event) { - // if our tools are off, then don't do anything - if (editToolsOn) { - var nVal = parseInt(event.text); - if (event.text == "`") { - copyScale = true; - } else if ((nVal > 0) && (nVal <= numColors)) { - whichColor = nVal - 1; - print("Color = " + (whichColor + 1)); - swatchesSound.play(whichColor); - moveTools(); - } else if (event.text == "0" && voxelToolSelected) { - // Create a brand new 1 meter voxel in front of your avatar - var newPosition = getNewVoxelPosition(); - var newVoxel = { - x: newPosition.x, - y: newPosition.y , - z: newPosition.z, - s: NEW_VOXEL_SIZE, - red: colors[whichColor].red, - green: colors[whichColor].green, - blue: colors[whichColor].blue }; - Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); - setAudioPosition(); - initialVoxelSound.playRandom(); - } else if (event.text == "z") { - undoSound.playRandom(); - } - } - - trackKeyPressEvent(event); // used by preview support -} - -function keyReleaseEvent(event) { - trackKeyReleaseEvent(event); // used by preview support -} - - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var voxelMenuAddedDelete = false; -function setupVoxelMenus() { - // hook up menus - Menu.menuItemEvent.connect(menuItemEvent); - - // add our menuitems - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Voxels", isSeparator: true, beforeItem: "Physics" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Cut", shortcutKey: "CTRL+X", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Copy", shortcutKey: "CTRL+C", afterItem: "Cut" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste", shortcutKey: "CTRL+V", afterItem: "Copy" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Nudge", shortcutKey: "CTRL+N", afterItem: "Paste" }); - - - if (!Menu.menuItemExists("Edit","Delete")) { - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", - shortcutKeyEvent: { text: "backspace" }, afterItem: "Nudge" }); - voxelMenuAddedDelete = true; - } - - Menu.addMenuItem({ menuName: "File", menuItemName: "Voxels", isSeparator: true, beforeItem: "Settings" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Voxels", shortcutKey: "CTRL+E", afterItem: "Voxels" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Voxels", shortcutKey: "CTRL+I", afterItem: "Export Voxels" }); -} - -function cleanupMenus() { - // delete our menuitems - Menu.removeSeparator("Edit", "Voxels"); - Menu.removeMenuItem("Edit", "Cut"); - Menu.removeMenuItem("Edit", "Copy"); - Menu.removeMenuItem("Edit", "Paste"); - Menu.removeMenuItem("Edit", "Nudge"); - if (voxelMenuAddedDelete) { - Menu.removeMenuItem("Edit", "Delete"); - } - Menu.removeSeparator("File", "Voxels"); - Menu.removeMenuItem("File", "Export Voxels"); - Menu.removeMenuItem("File", "Import Voxels"); -} - -function menuItemEvent(menuItem) { - - // handle clipboard items - if (editToolsOn) { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - var intersection = Voxels.findRayIntersection(pickRay); - selectedVoxel = calculateVoxelFromIntersection(intersection,"select"); - if (menuItem == "Copy") { - print("copying..."); - Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - pasteMode = true; - moveTools(); - } - if (menuItem == "Cut") { - print("cutting..."); - Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - pasteMode = true; - moveTools(); - } - if (menuItem == "Paste") { - if (isImporting) { - print("placing import..."); - placeImport(); - showImport(false); - } else { - print("pasting..."); - Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - pasteMode = false; - moveTools(); - } - if (menuItem == "Delete") { - print("deleting..."); - if (isImporting) { - cancelImport(); - } else if (voxelToolSelected) { - Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - } - - if (menuItem == "Export Voxels") { - print("export"); - Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); - } - if (menuItem == "Import Voxels") { - print("importing..."); - if (importVoxels()) { - showImport(true); - } - moveTools(); - } - if (menuItem == "Nudge") { - print("nudge"); - Clipboard.nudgeVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s, { x: -1, y: 0, z: 0 }); - } - } -} - -function mouseMoveEvent(event) { - if (!editToolsOn || inspectJsIsRunning) { - return; - } - - if (event.deviceID == 1500) { // Left Hydra Controller - currentCursor = 0; - } else if (event.deviceID == 1501) { // Right Hydra Controller - currentCursor = 1; - } else { - currentCursor = 2; - } - - // Move Import Preview - if (isImporting) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - - var distance = 2 * scaleSelector.scale; - - if (intersection.intersects) { - var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection)); - if (intersectionDistance < distance) { - distance = intersectionDistance * 0.99; - } - - } - - var targetPosition = { x: pickRay.direction.x * distance, - y: pickRay.direction.y * distance, - z: pickRay.direction.z * distance - }; - targetPosition.x += pickRay.origin.x; - targetPosition.y += pickRay.origin.y; - targetPosition.z += pickRay.origin.z; - - if (targetPosition.x < 0) targetPosition.x = 0; - if (targetPosition.y < 0) targetPosition.y = 0; - if (targetPosition.z < 0) targetPosition.z = 0; - - var nudgeFactor = scaleSelector.scale; - var newPosition = { - x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor, - y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor, - z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor - } - - moveImport(newPosition); - } - - if (isAdding) { - var pickRay = Camera.computePickRay(event.x, event.y); - var distance = Vec3.length(Vec3.subtract(pickRay.origin, lastVoxelPosition)); - var mouseSpot = Vec3.sum(Vec3.multiply(pickRay.direction, distance), pickRay.origin); - var delta = Vec3.subtract(mouseSpot, lastVoxelPosition); - - if (!isExtruding) { - // Use the drag direction to tell which way to 'extrude' this voxel - extrudeScale = lastVoxelScale; - extrudeDirection = { x: 0, y: 0, z: 0 }; - isExtruding = true; - if (delta.x > lastVoxelScale) extrudeDirection.x = 1; - else if (delta.x < -lastVoxelScale) extrudeDirection.x = -1; - else if (delta.y > lastVoxelScale) extrudeDirection.y = 1; - else if (delta.y < -lastVoxelScale) extrudeDirection.y = -1; - else if (delta.z > lastVoxelScale) extrudeDirection.z = 1; - else if (delta.z < -lastVoxelScale) extrudeDirection.z = -1; - else isExtruding = false; - } else { - // Extrude if mouse has moved by a voxel in the extrude direction - var distanceInDirection = Vec3.dot(delta, extrudeDirection); - if (distanceInDirection > extrudeScale) { - lastVoxelPosition = Vec3.sum(lastVoxelPosition, Vec3.multiply(extrudeDirection, extrudeScale)); - Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, extrudeScale, - lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); - } - } - } - - // update the add voxel/delete voxel overlay preview - trackMouseEvent(event); -} - -function mouseReleaseEvent(event) { - // if our tools are off, then don't do anything - if (!editToolsOn) { - return; - } - if (inspectJsIsRunning) { - return; - } - - isAdding = false; - isExtruding = false; -} - -function moveTools() { - // move the swatches - swatchesX = (windowDimensions.x - (swatchesWidth + scaleSelectorWidth)) / 2; - swatchesY = windowDimensions.y - swatchHeight + 1; - - // create the overlays, position them in a row, set their colors, and for the selected one, use a different source image - // location so that it displays the "selected" marker - for (s = 0; s < numColors; s++) { - var extraWidth = 0; - - if (s == 0) { - extraWidth = swatchExtraPadding; - } - - var imageFromX = swatchExtraPadding - extraWidth + s * swatchWidth; - var imageFromY = swatchHeight + 1; - if (s == whichColor) { - imageFromY = 0; - } - - var swatchX = swatchExtraPadding - extraWidth + swatchesX + ((swatchWidth - 1) * s); - - if (s == (numColors - 1)) { - extraWidth = swatchExtraPadding; - } - - Overlays.editOverlay(swatches[s], { - x: swatchX, - y: swatchesY, - subImage: { x: imageFromX, y: imageFromY, width: swatchWidth + extraWidth, height: swatchHeight }, - color: colors[s], - alpha: 1, - visible: editToolsOn - }); - } - - // move the tools - toolsY = (windowDimensions.y - toolsHeight) / 2; - - var voxelToolOffset = 1, - recolorToolOffset = 1, - eyedropperToolOffset = 1; - - var voxelToolColor = WHITE_COLOR; - - if (recolorToolSelected) { - recolorToolOffset = 2; - } else if (eyedropperToolSelected) { - eyedropperToolOffset = 2; - } else if (voxelToolSelected) { - if (pasteMode) { - voxelToolColor = pasteModeColor; - } - voxelToolOffset = 2; - } - - Overlays.editOverlay(voxelTool, { - subImage: { x: 0, y: toolHeight * voxelToolOffset, width: toolWidth, height: toolHeight }, - x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * voxelToolAt), width: toolWidth, height: toolHeight, - color: voxelToolColor, - visible: editToolsOn - }); - - Overlays.editOverlay(recolorTool, { - subImage: { x: 0, y: toolHeight * recolorToolOffset, width: toolWidth, height: toolHeight }, - x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * recolorToolAt), width: toolWidth, height: toolHeight, - visible: editToolsOn - }); - - Overlays.editOverlay(eyedropperTool, { - subImage: { x: 0, y: toolHeight * eyedropperToolOffset, width: toolWidth, height: toolHeight }, - x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * eyedropperToolAt), width: toolWidth, height: toolHeight, - visible: editToolsOn - }); - - scaleSelector.move(); -} - -var lastFingerAddVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area -var lastFingerDeleteVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area - -function checkControllers() { - var controllersPerPalm = 2; // palm and finger - for (var palm = 0; palm < 2; palm++) { - var palmController = palm * controllersPerPalm; - var fingerTipController = palmController + 1; - var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - - var BUTTON_COUNT = 6; - var BUTTON_BASE = palm * BUTTON_COUNT; - var BUTTON_1 = BUTTON_BASE + 1; - var BUTTON_2 = BUTTON_BASE + 2; - var FINGERTIP_VOXEL_SIZE = 0.05; - - if (Controller.isButtonPressed(BUTTON_1)) { - if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerAddVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) { - newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; - - Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE, - newColor.red, newColor.green, newColor.blue); - - lastFingerAddVoxel = fingerTipPosition; - } - } else if (Controller.isButtonPressed(BUTTON_2)) { - if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerDeleteVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) { - Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE); - lastFingerDeleteVoxel = fingerTipPosition; - } - } - } -} - -function update(deltaTime) { - if (editToolsOn) { - var newWindowDimensions = Controller.getViewportDimensions(); - if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { - windowDimensions = newWindowDimensions; - moveTools(); - } - - checkControllers(); - } -} - -function wheelEvent(event) { - wheelPixelsMoved += event.delta; - if (Math.abs(wheelPixelsMoved) > WHEEL_PIXELS_PER_SCALE_CHANGE) - { - - if (wheelPixelsMoved > 0) { - scaleSelector.decrementScale(); - } else { - scaleSelector.incrementScale(); - } - trackMouseEvent(event); - wheelPixelsMoved = 0; - - if (isImporting) { - rescaleImport(); - } - } -} - -// Controller.wheelEvent.connect(wheelEvent); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); -Controller.captureKeyEvents({ text: "+" }); -Controller.captureKeyEvents({ text: "-" }); - - -function scriptEnding() { - Overlays.deleteOverlay(voxelPreview); - for (var i = 0; i < linePreviewTop.length; i++) { - Overlays.deleteOverlay(linePreviewTop[i]); - Overlays.deleteOverlay(linePreviewBottom[i]); - Overlays.deleteOverlay(linePreviewLeft[i]); - Overlays.deleteOverlay(linePreviewRight[i]); - } - for (s = 0; s < numColors; s++) { - Overlays.deleteOverlay(swatches[s]); - } - Overlays.deleteOverlay(voxelTool); - Overlays.deleteOverlay(recolorTool); - Overlays.deleteOverlay(eyedropperTool); - Controller.releaseKeyEvents({ text: "+" }); - Controller.releaseKeyEvents({ text: "-" }); - cleanupImport(); - scaleSelector.cleanup(); - cleanupMenus(); -} -Script.scriptEnding.connect(scriptEnding); - -Script.update.connect(update); - -setupVoxelMenus(); diff --git a/examples/entityBirds.js b/examples/entityBirds.js deleted file mode 100644 index 9512597af9..0000000000 --- a/examples/entityBirds.js +++ /dev/null @@ -1,202 +0,0 @@ -// -// particleBirds.js -// examples -// -// Created by Benjamin Arnold on May 29, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// This sample script creates a swarm of tweeting bird entities that fly around the avatar. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -// Multiply vector by scalar -function vScalarMult(v, s) { - var rval = { x: v.x * s, y: v.y * s, z: v.z * s }; - return rval; -} - -function printVector(v) { - print(v.x + ", " + v.y + ", " + v.z + "\n"); -} -// Create a random vector with individual lengths between a,b -function randVector(a, b) { - var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) }; - return rval; -} - -// Returns a vector which is fraction of the way between a and b -function vInterpolate(a, b, fraction) { - var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction }; - return rval; -} - -var startTimeInSeconds = new Date().getTime() / 1000; - -var birdLifetime = 20; // lifetime of the birds in seconds! -var range = 1.0; // Over what distance in meters do you want the flock to fly around -var frame = 0; - -var CHANCE_OF_MOVING = 0.1; -var CHANCE_OF_TWEETING = 0.05; -var BIRD_GRAVITY = -0.1; -var BIRD_FLAP_SPEED = 10.0; -var BIRD_VELOCITY = 0.5; -var myPosition = MyAvatar.position; - -var range = 1.0; // Distance around avatar where I can move - -// This is our Bird object -function Bird (particleID, tweetSound, targetPosition) { - this.particleID = particleID; - this.tweetSound = tweetSound; - this.previousFlapOffset = 0; - this.targetPosition = targetPosition; - this.moving = false; - this.tweeting = -1; -} - -// Array of birds -var birds = []; - -function addBird() -{ - // Decide what kind of bird we are - var tweet; - var color; - var size; - var which = Math.random(); - if (which < 0.2) { - tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/bushtit_1.raw"); - color = { red: 100, green: 50, blue: 120 }; - size = 0.08; - } else if (which < 0.4) { - tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/rosyfacedlovebird.raw"); - color = { red: 100, green: 150, blue: 75 }; - size = 0.09; - } else if (which < 0.6) { - tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/saysphoebe.raw"); - color = { red: 84, green: 121, blue: 36 }; - size = 0.05; - } else if (which < 0.8) { - tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/mexicanWhipoorwill.raw"); - color = { red: 23, green: 197, blue: 230 }; - size = 0.12; - } else { - tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/westernscreechowl.raw"); - color = { red: 50, green: 67, blue: 144 }; - size = 0.15; - } - var properties = { - type: "Sphere", - lifetime: birdLifetime, - position: Vec3.sum(randVector(-range, range), myPosition), - velocity: { x: 0, y: 0, z: 0 }, - gravity: { x: 0, y: BIRD_GRAVITY, z: 0 }, - dimensions: { x: size * 2, y: size * 2, z: size * 2 }, - color: color - }; - - birds.push(new Bird(Entities.addEntity(properties), tweet, properties.position)); -} - -var numBirds = 30; - -// Generate the birds -for (var i = 0; i < numBirds; i++) { - addBird(); -} - -// Main update function -function updateBirds(deltaTime) { - - // Check to see if we've been running long enough that our birds are dead - var nowTimeInSeconds = new Date().getTime() / 1000; - if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) { - - print("our birds are dying, stop our script"); - Script.stop(); - return; - } - - frame++; - // Only update every third frame - if ((frame % 3) == 0) { - myPosition = MyAvatar.position; - - // Update all the birds - for (var i = 0; i < numBirds; i++) { - particleID = birds[i].particleID; - var properties = Entities.getEntityProperties(particleID); - - // Tweeting behavior - if (birds[i].tweeting == 0) { - if (Math.random() < CHANCE_OF_TWEETING) { - Audio.playSound(birds[i].tweetSound, { - position: properties.position, - volume: 0.75 - }); - birds[i].tweeting = 10; - } - } else { - birds[i].tweeting -= 1; - } - - // Begin movement by getting a target - if (birds[i].moving == false) { - if (Math.random() < CHANCE_OF_MOVING) { - var targetPosition = Vec3.sum(randVector(-range, range), myPosition); - - if (targetPosition.x < 0) { - targetPosition.x = 0; - } - if (targetPosition.y < 0) { - targetPosition.y = 0; - } - if (targetPosition.z < 0) { - targetPosition.z = 0; - } - if (targetPosition.x > TREE_SCALE) { - targetPosition.x = TREE_SCALE; - } - if (targetPosition.y > TREE_SCALE) { - targetPosition.y = TREE_SCALE; - } - if (targetPosition.z > TREE_SCALE) { - targetPosition.z = TREE_SCALE; - } - - birds[i].targetPosition = targetPosition; - - birds[i].moving = true; - } - } - // If we are moving, move towards the target - if (birds[i].moving) { - var desiredVelocity = Vec3.subtract(birds[i].targetPosition, properties.position); - desiredVelocity = vScalarMult(Vec3.normalize(desiredVelocity), BIRD_VELOCITY); - - properties.velocity = vInterpolate(properties.velocity, desiredVelocity, 0.2); - // If we are near the target, we should get a new target - if (Vec3.length(Vec3.subtract(properties.position, birds[i].targetPosition)) < (properties.dimensions.x / 5.0)) { - birds[i].moving = false; - } - } - - // Use a cosine wave offset to make it look like its flapping. - var offset = Math.cos(nowTimeInSeconds * BIRD_FLAP_SPEED) * properties.dimensions.x; - properties.position.y = properties.position.y + (offset - birds[i].previousFlapOffset); - // Change position relative to previous offset. - birds[i].previousFlapOffset = offset; - - // Update the particle - Entities.editEntity(particleID, properties); - } - } -} - -// register the call back so it fires before each data send -Script.update.connect(updateBirds); diff --git a/examples/entityScripts/changeColorOnHover.js b/examples/entityScripts/changeColorOnHover.js index 638c1bece4..0cf08adf1d 100644 --- a/examples/entityScripts/changeColorOnHover.js +++ b/examples/entityScripts/changeColorOnHover.js @@ -13,34 +13,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function(){ - this.oldColor = {}; - this.oldColorKnown = false; - this.storeOldColor = function(entityID) { - var oldProperties = Entities.getEntityProperties(entityID); - this.oldColor = oldProperties.color; - this.oldColorKnown = true; - print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); - }; - - this.preload = function(entityID) { - print("preload"); - this.storeOldColor(entityID); - }; - - this.hoverEnterEntity = function(entityID, mouseEvent) { - print("hoverEnterEntity"); - if (!this.oldColorKnown) { - this.storeOldColor(entityID); - } - Entities.editEntity(entityID, { color: { red: 0, green: 255, blue: 255} }); - }; - this.hoverLeaveEntity = function(entityID, mouseEvent) { - print("hoverLeaveEntity"); - if (this.oldColorKnown) { - print("leave restoring old color... this.oldColor=" - + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); - Entities.editEntity(entityID, { color: this.oldColor }); - } - }; -}) \ No newline at end of file +(function() { + Script.include("changeColorOnHoverClass.js"); + return new ChangeColorOnHover(); +}) diff --git a/examples/entityScripts/changeColorOnHoverClass.js b/examples/entityScripts/changeColorOnHoverClass.js new file mode 100644 index 0000000000..231469f7e8 --- /dev/null +++ b/examples/entityScripts/changeColorOnHoverClass.js @@ -0,0 +1,55 @@ +// +// changeColorOnHover.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 11/1/14. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example of an entity script which when assigned to a non-model entity like a box or sphere, will +// change the color of the entity when you hover over it. This script uses the JavaScript prototype/class functionality +// to construct an object that has methods for hoverEnterEntity and hoverLeaveEntity; +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +ChangeColorOnHover = function(){ + this.oldColor = {}; + this.oldColorKnown = false; +}; + +ChangeColorOnHover.prototype = { + + storeOldColor: function(entityID) { + var oldProperties = Entities.getEntityProperties(entityID); + this.oldColor = oldProperties.color; + this.oldColorKnown = true; + print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); + }, + + preload: function(entityID) { + print("preload"); + this.storeOldColor(entityID); + }, + + hoverEnterEntity: function(entityID, mouseEvent) { + print("hoverEnterEntity"); + if (!this.oldColorKnown) { + this.storeOldColor(entityID); + } + Entities.editEntity(entityID, { color: { red: 0, green: 255, blue: 255} }); + }, + + + hoverLeaveEntity: function(entityID, mouseEvent) { + print("hoverLeaveEntity"); + if (this.oldColorKnown) { + print("leave restoring old color... this.oldColor=" + + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); + Entities.editEntity(entityID, { color: this.oldColor }); + } + } +}; + + diff --git a/examples/entityScripts/playSoundOnEnterOrLeave.js b/examples/entityScripts/playSoundOnEnterOrLeave.js index f82c05c580..b95e35ab1d 100644 --- a/examples/entityScripts/playSoundOnEnterOrLeave.js +++ b/examples/entityScripts/playSoundOnEnterOrLeave.js @@ -27,10 +27,12 @@ }; this.enterEntity = function(entityID) { + print("enterEntity("+entityID.id+")"); playSound(); }; this.leaveEntity = function(entityID) { + print("leaveEntity("+entityID.id+")"); playSound(); }; }) diff --git a/examples/audioBall.js b/examples/example/audio/audioBall.js similarity index 98% rename from examples/audioBall.js rename to examples/example/audio/audioBall.js index e0c0ce7976..91ef7c0759 100644 --- a/examples/audioBall.js +++ b/examples/example/audio/audioBall.js @@ -13,7 +13,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/mexicanWhipoorwill.raw"); var CHANCE_OF_PLAYING_SOUND = 0.01; diff --git a/examples/audioDeviceExample.js b/examples/example/audio/audioDeviceExample.js similarity index 100% rename from examples/audioDeviceExample.js rename to examples/example/audio/audioDeviceExample.js diff --git a/examples/audioMuteExample.js b/examples/example/audio/audioMuteExample.js similarity index 100% rename from examples/audioMuteExample.js rename to examples/example/audio/audioMuteExample.js diff --git a/examples/audioReverbOn.js b/examples/example/audio/audioReverbOn.js similarity index 91% rename from examples/audioReverbOn.js rename to examples/example/audio/audioReverbOn.js index 479f5bba74..72f2fa97bc 100644 --- a/examples/audioReverbOn.js +++ b/examples/example/audio/audioReverbOn.js @@ -4,6 +4,10 @@ // // Copyright 2014 High Fidelity, Inc. // +// +// Gives the ability to be set various reverb settings. +// +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -14,7 +18,7 @@ var audioOptions = new AudioEffectOptions({ roomSize: 50, // Seconds - reverbTime: 4, + reverbTime: 10, // Between 0 - 1 damping: 0.50, diff --git a/examples/birdSongs.js b/examples/example/audio/birdSongs.js similarity index 100% rename from examples/birdSongs.js rename to examples/example/audio/birdSongs.js diff --git a/examples/radio.js b/examples/example/audio/radio.js similarity index 98% rename from examples/radio.js rename to examples/example/audio/radio.js index e8300c00b5..39409df377 100644 --- a/examples/radio.js +++ b/examples/example/audio/radio.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../libraries/globals.js"); var modelURL = HIFI_PUBLIC_BUCKET + "models/entities/radio/Speakers.fbx"; var soundURL = HIFI_PUBLIC_BUCKET + "sounds/family.stereo.raw"; diff --git a/examples/speechControl.js b/examples/example/audio/speechControl.js similarity index 100% rename from examples/speechControl.js rename to examples/example/audio/speechControl.js diff --git a/examples/cameraExample.js b/examples/example/avatarcontrol/cameraExample.js similarity index 99% rename from examples/cameraExample.js rename to examples/example/avatarcontrol/cameraExample.js index 4c02ce2f2e..85d35623b6 100644 --- a/examples/cameraExample.js +++ b/examples/example/avatarcontrol/cameraExample.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var damping = 0.9; +var damping = 0.001; var yaw = 0.0; var pitch = 0.0; var roll = 0.0; diff --git a/examples/controllerExample.js b/examples/example/avatarcontrol/controllerExample.js similarity index 100% rename from examples/controllerExample.js rename to examples/example/avatarcontrol/controllerExample.js diff --git a/examples/guidedTour.js b/examples/example/avatarcontrol/guidedTour.js similarity index 100% rename from examples/guidedTour.js rename to examples/example/avatarcontrol/guidedTour.js diff --git a/examples/hideAvatarExample.js b/examples/example/avatarcontrol/hideAvatarExample.js similarity index 96% rename from examples/hideAvatarExample.js rename to examples/example/avatarcontrol/hideAvatarExample.js index 66d85becf1..856a8b3c69 100644 --- a/examples/hideAvatarExample.js +++ b/examples/example/avatarcontrol/hideAvatarExample.js @@ -12,7 +12,7 @@ // function keyReleaseEvent(event) { - if (event.text == "F2") { + if (event.text == "r") { MyAvatar.shouldRenderLocally = !MyAvatar.shouldRenderLocally; } } diff --git a/examples/lookAtExample.js b/examples/example/avatarcontrol/lookAtExample.js similarity index 92% rename from examples/lookAtExample.js rename to examples/example/avatarcontrol/lookAtExample.js index 729281fa03..e21341469d 100644 --- a/examples/lookAtExample.js +++ b/examples/example/avatarcontrol/lookAtExample.js @@ -8,8 +8,8 @@ // This is an example script that demonstrates use of the Camera class's lookAt(), keepLookingAt(), and stopLookingAt() // features. // -// To use the script, click on a voxel, and the camera will switch into independent mode and fix it's lookAt on the point -// on the face of the voxel that you clicked. Click again and it will stop looking at that point. While in this fixed mode +// To use the script, click on a entity, and the camera will switch into independent mode and fix it's lookAt on the point +// on the face of the entity that you clicked. Click again and it will stop looking at that point. While in this fixed mode // you can use the arrow keys to change the position of the camera. // // Distributed under the Apache License, Version 2.0. @@ -61,7 +61,7 @@ function mousePressEvent(event) { cancelLookAt(); } else { var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects) { // remember the old mode we were in diff --git a/examples/multipleCursorsExample.js b/examples/example/avatarcontrol/multipleCursorsExample.js similarity index 100% rename from examples/multipleCursorsExample.js rename to examples/example/avatarcontrol/multipleCursorsExample.js diff --git a/examples/multitouchExample.js b/examples/example/avatarcontrol/multitouchExample.js similarity index 100% rename from examples/multitouchExample.js rename to examples/example/avatarcontrol/multitouchExample.js diff --git a/examples/example/downloadInfoExample.js b/examples/example/downloadInfoExample.js new file mode 100644 index 0000000000..19995503bc --- /dev/null +++ b/examples/example/downloadInfoExample.js @@ -0,0 +1,66 @@ +// +// downloadInfoExample.js +// examples/example +// +// Created by David Rowe on 5 Jan 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Display downloads information the same as in the stats. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var downloadInfo, + downloadInfoOverlay; + +function formatInfo(info) { + var string = "Downloads: ", + i; + + for (i = 0; i < info.downloading.length; i += 1) { + string += info.downloading[i].toFixed(0) + "% "; + } + + string += "(" + info.pending.toFixed(0) + " pending)"; + + return string; +} + + +// Get and log the current downloads info ... + +downloadInfo = GlobalServices.getDownloadInfo(); +print(formatInfo(downloadInfo)); + + +// Display and update the downloads info in an overlay ... + +function setUp() { + downloadInfoOverlay = Overlays.addOverlay("text", { + x: 300, + y: 200, + width: 300, + height: 50, + color: { red: 255, green: 255, blue: 255 }, + alpha: 1.0, + backgroundColor: { red: 127, green: 127, blue: 127 }, + backgroundAlpha: 0.5, + topMargin: 15, + leftMargin: 20, + text: "" + }); +} + +function updateInfo(info) { + Overlays.editOverlay(downloadInfoOverlay, { text: formatInfo(info) }); +} + +function tearDown() { + Overlays.deleteOverlay(downloadInfoOverlay); +} + +setUp(); +GlobalServices.downloadInfoChanged.connect(updateInfo); +GlobalServices.updateDownloadInfo(); +Script.scriptEnding.connect(tearDown); diff --git a/examples/animationStateExample.js b/examples/example/entities/ZZZ-MOVE-TO_DOCS-animationStateExample.js similarity index 100% rename from examples/animationStateExample.js rename to examples/example/entities/ZZZ-MOVE-TO_DOCS-animationStateExample.js diff --git a/examples/animatedModelExample.js b/examples/example/entities/animatedModelExample.js similarity index 91% rename from examples/animatedModelExample.js rename to examples/example/entities/animatedModelExample.js index 3fffdc88d2..00790fecc8 100644 --- a/examples/animatedModelExample.js +++ b/examples/example/entities/animatedModelExample.js @@ -12,7 +12,7 @@ // var count = 0; -var moveUntil = 6000; +var moveUntil = 1000; var stopAfter = moveUntil + 100; var pitch = 0.0; @@ -25,16 +25,19 @@ var originalProperties = { position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z }, - - radius : 1, + dimensions: { + x: 1.62, + y: 0.41, + z: 1.13 + }, color: { red: 0, green: 255, blue: 0 }, - modelURL: "http://www.fungibleinsight.com/faces/beta.fst", + modelURL: "http://public.highfidelity.io/cozza13/club/dragon/dragon.fbx", rotation: rotation, - animationURL: "http://www.fungibleinsight.com/faces/gangnam_style_2.fbx", + animationURL: "http://public.highfidelity.io/cozza13/club/dragon/flying.fbx", animationIsPlaying: true, }; diff --git a/examples/butterflies.js b/examples/example/entities/butterflies.js similarity index 95% rename from examples/butterflies.js rename to examples/example/entities/butterflies.js index edc33f7625..336e128d83 100644 --- a/examples/butterflies.js +++ b/examples/example/entities/butterflies.js @@ -79,12 +79,12 @@ function addButterfly() { rotation: Quat.fromPitchYawRollDegrees(-80 + Math.random() * 20, Math.random() * 360.0, 0.0), velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 }, - damping: 0.9999, + damping: 0.00001, dimensions: dimensions, color: color, - animationURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/content/butterfly/butterfly.fbx", + animationURL: "http://public.highfidelity.io/models/content/butterfly/butterfly.fbx", animationSettings: "{\"firstFrame\":0,\"fps\":" + newFrameRate + ",\"frameIndex\":0,\"hold\":false,\"lastFrame\":10000,\"loop\":true,\"running\":true,\"startAutomatically\":false}", - modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/content/butterfly/butterfly.fbx" + modelURL: "http://public.highfidelity.io/models/content/butterfly/butterfly.fbx" }; butterflies.push(Entities.addEntity(properties)); } @@ -138,4 +138,4 @@ Script.scriptEnding.connect(function() { for (var i = 0; i < numButterflies; i++) { Entities.deleteEntity(butterflies[i]); } -}); \ No newline at end of file +}); diff --git a/examples/collidingEntities.js b/examples/example/entities/collidingEntities.js similarity index 96% rename from examples/collidingEntities.js rename to examples/example/entities/collidingEntities.js index 233626df23..37c35e971d 100644 --- a/examples/collidingEntities.js +++ b/examples/example/entities/collidingEntities.js @@ -64,7 +64,7 @@ function draw(deltaTime) { y: 1, z: 0 }; - var entitySize = 0.1; + var entitySize = 1.1; print("number of entitys=" + numberEntitiesAdded +"\n"); @@ -99,7 +99,7 @@ function draw(deltaTime) { Script.stop(); } - print("Particles Stats: " + Entities.getLifetimeInSeconds() + " seconds," + + print("Entity Stats: " + Entities.getLifetimeInSeconds() + " seconds," + " Queued packets:" + Entities.getLifetimePacketsQueued() + "," + " PPS:" + Entities.getLifetimePPSQueued() + "," + " BPS:" + Entities.getLifetimeBPSQueued() + "," + diff --git a/examples/editEntityExample.js b/examples/example/entities/editEntityExample.js similarity index 92% rename from examples/editEntityExample.js rename to examples/example/entities/editEntityExample.js index 422e50b1eb..96132ad471 100644 --- a/examples/editEntityExample.js +++ b/examples/example/entities/editEntityExample.js @@ -5,7 +5,7 @@ // Created by Brad Hefta-Gaub on 12/31/13. // Copyright 2014 High Fidelity, Inc. // -// This is an example script that demonstrates creating and editing a particle +// This is an example script that demonstrates creating and editing a particle. Go to the origin of the domain to see the results (0,0,0). // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -29,6 +29,11 @@ var originalProperties = { gravity: { x: 0, y: 0, z: 0 }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, color: { red: 0, @@ -74,7 +79,6 @@ function moveEntity(deltaTime) { y: originalProperties.position.y + (count * positionDelta.y), z: originalProperties.position.z + (count * positionDelta.z) }, - radius : 0.25, }; diff --git a/examples/editModelExample.js b/examples/example/entities/editModelExample.js similarity index 78% rename from examples/editModelExample.js rename to examples/example/entities/editModelExample.js index 5a4efc0746..474d9afe26 100644 --- a/examples/editModelExample.js +++ b/examples/example/entities/editModelExample.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); var count = 0; var moveUntil = 2000; @@ -23,22 +23,22 @@ var roll = 180.0; var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll) var originalProperties = { +type: "Model", position: { x: 2.0, y: 2.0, z: 0.5 }, - radius : 0.25, - - color: { red: 0, + dimensions: { + x: 2.16, + y: 3.34, + z: 0.54 + }, + color: { red: 0, green: 255, blue: 0 }, modelURL: HIFI_PUBLIC_BUCKET + "meshes/Feisar_Ship.FBX", - //modelURL: HIFI_PUBLIC_BUCKET + "meshes/birarda/birarda_head.fbx", - //modelURL: HIFI_PUBLIC_BUCKET + "meshes/pug.fbx", - //modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-large-purple.svo", - //modelURL: HIFI_PUBLIC_BUCKET + "meshes/minotaur/mino_full.fbx", - //modelURL: HIFI_PUBLIC_BUCKET + "meshes/Combat_tank_V01.FBX", + rotation: rotation }; @@ -67,10 +67,10 @@ function moveEntity(deltaTime) { return; // break early } - //print("count =" + count); + print("count =" + count); count++; - //print("entityID.creatorTokenID = " + entityID.creatorTokenID); + print("entityID.creatorTokenID = " + entityID.creatorTokenID); var newProperties = { position: { diff --git a/examples/entityModelExample.js b/examples/example/entities/entityModelExample.js similarity index 75% rename from examples/entityModelExample.js rename to examples/example/entities/entityModelExample.js index 067032fc6b..d09a349cb0 100644 --- a/examples/entityModelExample.js +++ b/examples/example/entities/entityModelExample.js @@ -11,30 +11,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../libraries/globals.js"); var count = 0; -var stopAfter = 100; +var stopAfter = 1000; var modelPropertiesA = { type: "Model", position: { x: 1, y: 1, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, damping: 0, - dimensions: { x: 0.5, y: 0.5, z: 0.5 }, + dimensions: { + x: 2.16, + y: 3.34, + z: 0.54 + }, modelURL: HIFI_PUBLIC_BUCKET + "meshes/Feisar_Ship.FBX", lifetime: 20 }; -var modelPropertiesB = { - type: "Model", - position: { x: 1, y: 1.5, z: 1 }, - velocity: { x: 0.5, y: 0, z: 0.5 }, - damping: 0, - dimensions: { x: 0.5, y: 0.5, z: 0.5 }, - modelURL: HIFI_PUBLIC_BUCKET + "meshes/orc.fbx", - lifetime: 20 -}; var ballProperties = { type: "Sphere", @@ -47,7 +42,6 @@ var ballProperties = { }; var modelAEntityID = Entities.addEntity(modelPropertiesA); -var modelBEntityID = Entities.addEntity(modelPropertiesB); var ballEntityID = Entities.addEntity(ballProperties); function endAfterAWhile(deltaTime) { diff --git a/examples/findEntitiesExample.js b/examples/example/entities/findEntitiesExample.js similarity index 100% rename from examples/findEntitiesExample.js rename to examples/example/entities/findEntitiesExample.js diff --git a/examples/flockingBirds.js b/examples/example/entities/flockingBirds.js similarity index 99% rename from examples/flockingBirds.js rename to examples/example/entities/flockingBirds.js index fd59b20c48..b07e7cf4bd 100644 --- a/examples/flockingBirds.js +++ b/examples/example/entities/flockingBirds.js @@ -5,7 +5,7 @@ // Created by Brad Hefta-Gaub on 3/4/14. // Copyright 2014 High Fidelity, Inc. // -// This is an example script that generates particles that act like flocking birds +// This is an example script that generates entities that act like flocking birds // // All birds, even flying solo... // birds don't like to fall too fast diff --git a/examples/lightExample.js b/examples/example/entities/lightExample.js similarity index 98% rename from examples/lightExample.js rename to examples/example/entities/lightExample.js index 7a90eb8714..58495a02f4 100644 --- a/examples/lightExample.js +++ b/examples/example/entities/lightExample.js @@ -27,7 +27,7 @@ var lightID = Entities.addEntity({ angularVelocity: { x: 0, y: 0, z: 0 }, angularDamping: 0, - isSpotlight: false, + isSpotlight: true, diffuseColor: { red: 255, green: 255, blue: 0 }, ambientColor: { red: 0, green: 0, blue: 0 }, specularColor: { red: 255, green: 255, blue: 255 }, diff --git a/examples/rideAlongWithAnEntityExample.js b/examples/example/entities/rideAlongWithAnEntityExample.js similarity index 100% rename from examples/rideAlongWithAnEntityExample.js rename to examples/example/entities/rideAlongWithAnEntityExample.js diff --git a/examples/spotlightExample.js b/examples/example/entities/spotlightExample.js similarity index 100% rename from examples/spotlightExample.js rename to examples/example/entities/spotlightExample.js diff --git a/examples/cleanupChessboards.js b/examples/example/games/cleanupChessboards.js similarity index 100% rename from examples/cleanupChessboards.js rename to examples/example/games/cleanupChessboards.js diff --git a/examples/clonedOverlaysExample.js b/examples/example/games/clonedOverlaysExample.js similarity index 97% rename from examples/clonedOverlaysExample.js rename to examples/example/games/clonedOverlaysExample.js index 7aea048175..aa475ee518 100644 --- a/examples/clonedOverlaysExample.js +++ b/examples/example/games/clonedOverlaysExample.js @@ -15,10 +15,10 @@ const NUM_OF_TREES = 40; const NUM_OF_SANTAS = 20; // Image source: https://openclipart.org/detail/447/christmas-tree-by-theresaknott (heavily edited by Maximillian Merlin) -const CHRISTMAS_TREE_SPRITES_URL = "http://test.thoys.nl/hifi/images/santa/christmas-tree.svg"; +const CHRISTMAS_TREE_SPRITES_URL = "https://s3.amazonaws.com/hifi-public/models/props/xmas/christmas-tree.svg"; // Image source: http://opengameart.org/content/santa-claus (CC-BY 3.0) -const SANTA_SPRITES_URL = "http://test.thoys.nl/hifi/images/santa/Santa.png"; +const SANTA_SPRITES_URL = "https://s3.amazonaws.com/hifi-public/models/props/xmas/Santa.png"; Array.prototype.contains = function(obj) { var i = this.length; diff --git a/examples/playChess.js b/examples/example/games/playChess.js similarity index 100% rename from examples/playChess.js rename to examples/example/games/playChess.js diff --git a/examples/spaceInvadersExample.js b/examples/example/games/spaceInvadersExample.js similarity index 96% rename from examples/spaceInvadersExample.js rename to examples/example/games/spaceInvadersExample.js index 832efe7e75..5ad8bbe4f6 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/example/games/spaceInvadersExample.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); var iteration = 0; @@ -59,7 +59,7 @@ var middleY = gameAt.y + (gameSize.y/2); var invaderSize = 0.4; var shipSize = 0.25; -var missileSize = 0.1; +var missileSize = 1.0; var myShip; var myShipProperties; @@ -101,27 +101,27 @@ var soundInMyHead = true; // models... var invaderModels = new Array(); invaderModels[0] = { - modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-large-purple.svo", + modelURL: HIFI_PUBLIC_BUCKET + "meshes/space_invader.fbx", modelScale: 450, modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, }; invaderModels[1] = { - modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-large-cyan.svo", + modelURL: HIFI_PUBLIC_BUCKET + "meshes/space_invader.fbx", modelScale: 450, modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, }; invaderModels[2] = { - modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-medium-cyan.svo", + modelURL: HIFI_PUBLIC_BUCKET + "meshes/space_invader.fbx", modelScale: 450, modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, }; invaderModels[3] = { - modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-medium-green.svo", + modelURL: HIFI_PUBLIC_BUCKET + "meshes/space_invader.fbx", modelScale: 450, modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, }; invaderModels[4] = { - modelURL: HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-small-green.svo", + modelURL: HIFI_PUBLIC_BUCKET + "meshes/space_invader.fbx", modelScale: 450, modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, }; @@ -141,7 +141,7 @@ function initializeMyShip() { damping: 0, dimensions: { x: shipSize * 2, y: shipSize * 2, z: shipSize * 2 }, color: { red: 0, green: 255, blue: 0 }, - modelURL: HIFI_PUBLIC_BUCKET + "meshes/myCannon16x16.svo", + modelURL: HIFI_PUBLIC_BUCKET + "meshes/space_invader.fbx", lifetime: itemLifetimes }; myShip = Entities.addEntity(myShipProperties); @@ -360,7 +360,7 @@ function keyPressEvent(key) { myShipProperties.position.x = gameAt.x + gameSize.x; } moveShipTo(myShipProperties.position); - } else if (key.text == " ") { + } else if (key.text == "f") { fireMissile(); } else if (key.text == "q") { endGame(); diff --git a/examples/globalCollisionsExample.js b/examples/example/globalCollisionsExample.js similarity index 65% rename from examples/globalCollisionsExample.js rename to examples/example/globalCollisionsExample.js index 426aebd5d9..5813cb2472 100644 --- a/examples/globalCollisionsExample.js +++ b/examples/example/globalCollisionsExample.js @@ -14,13 +14,6 @@ print("hello..."); -function entityCollisionWithVoxel(entity, voxel, collision) { - print("entityCollisionWithVoxel().."); - print(" entity.getID()=" + entity.id); - print(" voxel color...=" + voxel.red + ", " + voxel.green + ", " + voxel.blue); - Vec3.print('penetration=', collision.penetration); - Vec3.print('contactPoint=', collision.contactPoint); -} function entityCollisionWithEntity(entityA, entityB, collision) { print("entityCollisionWithParticle().."); @@ -30,7 +23,6 @@ function entityCollisionWithEntity(entityA, entityB, collision) { Vec3.print('contactPoint=', collision.contactPoint); } -Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); print("here... hello..."); diff --git a/examples/metavoxels.js b/examples/example/metavoxels/metavoxels.js similarity index 100% rename from examples/metavoxels.js rename to examples/example/metavoxels/metavoxels.js diff --git a/examples/globalServicesExample.js b/examples/example/misc/globalServicesExample.js similarity index 100% rename from examples/globalServicesExample.js rename to examples/example/misc/globalServicesExample.js diff --git a/examples/includeExample.js b/examples/example/scripts/includeExample.js similarity index 84% rename from examples/includeExample.js rename to examples/example/scripts/includeExample.js index 50a1234772..c9c882156e 100644 --- a/examples/includeExample.js +++ b/examples/example/scripts/includeExample.js @@ -15,5 +15,5 @@ Script.include("http://public.highfidelity.io/scripts/lookWithTouch.js"); // You can also include scripts that are relative to the current script -Script.include("editVoxels.js"); -Script.include("../examples/selectAudioDevice.js"); +//Script.include("../../editEntities.js"); +//Script.include("../../examples/selectAudioDevice.js"); diff --git a/examples/loadScriptFromMessage.js b/examples/example/scripts/loadScriptFromMessage.js similarity index 100% rename from examples/loadScriptFromMessage.js rename to examples/example/scripts/loadScriptFromMessage.js diff --git a/examples/locationExample.js b/examples/example/scripts/locationExample.js similarity index 100% rename from examples/locationExample.js rename to examples/example/scripts/locationExample.js diff --git a/examples/rayPickExample.js b/examples/example/scripts/rayPickExample.js similarity index 55% rename from examples/rayPickExample.js rename to examples/example/scripts/rayPickExample.js index c3b6581007..b0b7c24fef 100644 --- a/examples/rayPickExample.js +++ b/examples/example/scripts/rayPickExample.js @@ -18,30 +18,6 @@ function mouseMoveEvent(event) { print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z); print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z); var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - if (!intersection.accurate) { - print(">>> NOTE: intersection not accurate. will try calling Voxels.findRayIntersectionBlocking()"); - intersection = Voxels.findRayIntersectionBlocking(pickRay); - print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate); - } - - if (intersection.intersects) { - print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", " - + intersection.voxel.green + ", " + intersection.voxel.blue); - print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " - + intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s); - print("intersection face=" + intersection.face); - print("intersection distance=" + intersection.distance); - print("intersection intersection.x/y/z=" + intersection.intersection.x + ", " - + intersection.intersection.y + ", " + intersection.intersection.z); - - // also test the getVoxelAt() api which should find and return same voxel - - var voxelAt = Voxels.getVoxelAt(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s); - print("voxelAt.x/y/z/s=" + voxelAt.x + ", " + voxelAt.y + ", " + voxelAt.z + ": " + voxelAt.s); - print("voxelAt.red/green/blue=" + voxelAt.red + ", " + voxelAt.green + ", " + voxelAt.blue); - } - intersection = Entities.findRayIntersection(pickRay); if (!intersection.accurate) { print(">>> NOTE: intersection not accurate. will try calling Entities.findRayIntersectionBlocking()"); diff --git a/examples/settingsExample.js b/examples/example/scripts/settingsExample.js similarity index 96% rename from examples/settingsExample.js rename to examples/example/scripts/settingsExample.js index bef347ff07..f8364ff91b 100644 --- a/examples/settingsExample.js +++ b/examples/example/scripts/settingsExample.js @@ -15,4 +15,4 @@ print("mySetting: " + Settings.getValue("mySetting")); Settings.setValue("mySetting", "spam"); print("mySetting: " + Settings.getValue("mySetting")); -Script.stop(); \ No newline at end of file +//Script.stop(); \ No newline at end of file diff --git a/examples/streetAreaExample.js b/examples/example/scripts/streetAreaExample.js similarity index 100% rename from examples/streetAreaExample.js rename to examples/example/scripts/streetAreaExample.js diff --git a/examples/timer.js b/examples/example/scripts/timer.js similarity index 100% rename from examples/timer.js rename to examples/example/scripts/timer.js diff --git a/examples/dialogExample.js b/examples/example/ui/dialogExample.js similarity index 100% rename from examples/dialogExample.js rename to examples/example/ui/dialogExample.js diff --git a/examples/fileBrowserExample.js b/examples/example/ui/fileBrowserExample.js similarity index 100% rename from examples/fileBrowserExample.js rename to examples/example/ui/fileBrowserExample.js diff --git a/examples/menuExample.js b/examples/example/ui/menuExample.js similarity index 100% rename from examples/menuExample.js rename to examples/example/ui/menuExample.js diff --git a/examples/overlaysExample.js b/examples/example/ui/overlaysExample.js similarity index 99% rename from examples/overlaysExample.js rename to examples/example/ui/overlaysExample.js index 4aa5b1cd75..4e85512545 100644 --- a/examples/overlaysExample.js +++ b/examples/example/ui/overlaysExample.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); // The "Swatches" example of this script will create 9 different image overlays, that use the color feature to // display different colors as color swatches. The overlays can be clicked on, to change the "selectedSwatch" variable @@ -154,7 +154,7 @@ var sphere = Overlays.addOverlay("sphere", { }); var line3d = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z:0 }, + start: { x: 0, y: 0, z:0 }, end: { x: 10, y: 10, z:10 }, color: { red: 0, green: 255, blue: 255}, alpha: 1, diff --git a/examples/textInputOverlayExample.js b/examples/example/ui/textInputOverlayExample.js similarity index 97% rename from examples/textInputOverlayExample.js rename to examples/example/ui/textInputOverlayExample.js index 258e07fcc8..d212a547cf 100644 --- a/examples/textInputOverlayExample.js +++ b/examples/example/ui/textInputOverlayExample.js @@ -58,7 +58,7 @@ var button1 = Overlays.addOverlay("image", { // green button width: 40, height: 35, subImage: { x: 0, y: 0, width: 39, height: 35 }, - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", + imageURL: "https://public.highfidelity.io/images/thumb.png", color: readyColor, visible: true }); @@ -69,7 +69,7 @@ var button2 = Overlays.addOverlay("image", { // red button width: 40, height: 35, subImage: { x: 0, y: 0, width: 39, height: 35 }, - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png", + imageURL: "https://public.highfidelity.io/images/thumb.png", color: { red: 250, green: 2, blue: 2}, visible: true, }); diff --git a/examples/windowExample.js b/examples/example/ui/windowExample.js similarity index 100% rename from examples/windowExample.js rename to examples/example/ui/windowExample.js diff --git a/examples/fallingSand.js b/examples/fallingSand.js deleted file mode 100644 index c85196f10e..0000000000 --- a/examples/fallingSand.js +++ /dev/null @@ -1,648 +0,0 @@ -// -// fallingSand.js -// examples -// -// Created by Ben Arnold on 7/14/14. -// Copyright 2014 High Fidelity, Inc. -// -// This sample script allows the user to place sand voxels that will undergo -// cellular automata physics. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting -var previewLineWidth = 2.0; - -var voxelSize = 1; -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - -var MAX_VOXEL_SCALE_POWER = 5; -var MIN_VOXEL_SCALE_POWER = -8; -var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); -var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); - - -var linePreviewTop = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewBottom = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewLeft = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewRight = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 255}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - - -var UIColor = { red: 119, green: 103, blue: 53}; -var activeUIColor = { red: 234, green: 206, blue: 106}; - -var toolHeight = 50; -var toolWidth = 50; - -var editToolsOn = true; - -var voxelToolSelected = false; - -var scaleSelectorWidth = 144; -var scaleSelectorHeight = 37; - -var scaleSelectorX = windowDimensions.x / 5.0; -var scaleSelectorY = windowDimensions.y - scaleSelectorHeight; - -var voxelTool = Overlays.addOverlay("image", { - x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-tool.svg", - visible: editToolsOn, - color: UIColor, - alpha: 0.9 - }); - -var copyScale = true; -function ScaleSelector() { - this.x = scaleSelectorX; - this.y = scaleSelectorY; - this.width = scaleSelectorWidth; - this.height = scaleSelectorHeight; - - this.displayPower = false; - this.scale = 1.0; - this.power = 0; - - this.FIRST_PART = this.width * 40.0 / 100.0; - this.SECOND_PART = this.width * 37.0 / 100.0; - - this.buttonsOverlay = Overlays.addOverlay("image", { - x: this.x, y: this.y, - width: this.width, height: this.height, - //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - visible: editToolsOn, - color: activeUIColor - }); - this.textOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - topMargin: 13, - text: this.scale.toString(), - backgroundAlpha: 0.0, - visible: editToolsOn, - color: activeUIColor - }); - this.powerOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - leftMargin: 28, - text: this.power.toString(), - backgroundAlpha: 0.0, - visible: false, - color: activeUIColor - }); - this.setScale = function(scale) { - if (scale > MAX_VOXEL_SCALE) { - scale = MAX_VOXEL_SCALE; - } - if (scale < MIN_VOXEL_SCALE) { - scale = MIN_VOXEL_SCALE; - } - - this.scale = scale; - this.power = Math.floor(Math.log(scale) / Math.log(2)); - this.update(); - } - - this.show = function(doShow) { - Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); - Overlays.editOverlay(this.textOverlay, {visible: doShow}); - Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); - } - - this.move = function() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - - Overlays.editOverlay(this.buttonsOverlay, { - x: this.x, y: this.y, - }); - Overlays.editOverlay(this.textOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - Overlays.editOverlay(this.powerOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - } - - - this.switchDisplay = function() { - this.displayPower = !this.displayPower; - - if (this.displayPower) { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 18, - text: "2" - }); - Overlays.editOverlay(this.powerOverlay, { - text: this.power.toString(), - visible: editToolsOn - }); - } else { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 13, - text: this.scale.toString() - }); - Overlays.editOverlay(this.powerOverlay, { - visible: false - }); - } - } - - this.update = function() { - if (this.displayPower) { - Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); - } else { - Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); - } - } - - this.incrementScale = function() { - copyScale = false; - if (this.power < MAX_VOXEL_SCALE_POWER) { - ++this.power; - this.scale *= 2.0; - this.update(); - } - } - - this.decrementScale = function() { - copyScale = false; - if (MIN_VOXEL_SCALE_POWER < this.power) { - --this.power; - this.scale /= 2.0; - this.update(); - } - } - - this.clicked = function(x, y) { - if (this.x < x && x < this.x + this.width && - this.y < y && y < this.y + this.height) { - - if (x < this.x + this.FIRST_PART) { - this.decrementScale(); - } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { - this.switchDisplay(); - } else { - this.incrementScale(); - } - return true; - } - return false; - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.buttonsOverlay); - Overlays.deleteOverlay(this.textOverlay); - Overlays.deleteOverlay(this.powerOverlay); - } - -} -var scaleSelector = new ScaleSelector(); - -function calculateVoxelFromIntersection(intersection, operation) { - - var resultVoxel; - - var x; - var y; - var z; - - // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest - // ancestor voxel of our target size that contains our intersected voxel. - if (voxelSize > intersection.voxel.s) { - x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; - y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; - z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; - } else { - // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. - // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result - // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting - // voxel this still works and results in returning the intersecting voxel which is what we want - var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); - - var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); - x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; - y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; - z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; - } - resultVoxel = { x: x, y: y, z: z, s: voxelSize }; - var highlightAt = { x: x, y: y, z: z, s: voxelSize }; - - - - // we only do the "add to the face we're pointing at" adjustment, if the operation is an add - // operation, and the target voxel size is equal to or smaller than the intersecting voxel. - var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); - - // now we also want to calculate the "edge square" for the face for this voxel - if (intersection.face == "MIN_X_FACE") { - - highlightAt.x = x - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x -= voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_X_FACE") { - - highlightAt.x = x + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MIN_Y_FACE") { - - highlightAt.y = y - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y -= voxelSize; - } - - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_Y_FACE") { - - highlightAt.y = y + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y += voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - - } else if (intersection.face == "MIN_Z_FACE") { - - highlightAt.z = z - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z -= voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - highlightAt.z = z + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z += voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } - return resultVoxel; -} - -var trackLastMouseX = 0; -var trackLastMouseY = 0; - -function showPreviewLines() { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - var resultVoxel = calculateVoxelFromIntersection(intersection, ""); - Overlays.editOverlay(linePreviewTop, { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom, { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft, { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight, { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); - } else { - Overlays.editOverlay(linePreviewTop, { visible: false }); - Overlays.editOverlay(linePreviewBottom, { visible: false }); - Overlays.editOverlay(linePreviewLeft, { visible: false }); - Overlays.editOverlay(linePreviewRight, { visible: false }); - } -} - -function mouseMoveEvent(event) { - trackLastMouseX = event.x; - trackLastMouseY = event.y; - if (!voxelToolSelected) { - return; - } - showPreviewLines(); -} - -var BRUSH_RADIUS = 2; - -function mousePressEvent(event) { - var mouseX = event.x; - var mouseY = event.y; - - var clickedOnSomething = false; - // Check if we clicked an overlay - var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY}); - - if (clickedOverlay == voxelTool) { - voxelToolSelected = !voxelToolSelected; - - if (voxelToolSelected == true) { - Overlays.editOverlay(voxelTool, { - color: activeUIColor - }); - } else { - Overlays.editOverlay(voxelTool, { - color: UIColor - }); - } - - clickedOnSomething = true; - } else if (scaleSelector.clicked(event.x, event.y)) { - clickedOnSomething = true; - voxelSize = scaleSelector.scale; - } - - // Return if we clicked on the UI or the voxel tool is disabled - if (clickedOnSomething || !voxelToolSelected) { - return; - } - - // Compute the picking ray for the click - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - var resultVoxel = calculateVoxelFromIntersection(intersection, "add"); - - - //Add a clump of sand voxels - makeSphere(resultVoxel.x, resultVoxel.y, resultVoxel.z, voxelSize * BRUSH_RADIUS, voxelSize); -} - -var sandArray = []; -var numSand = 0; - - -//These arrays are used to buffer add/remove operations so they can be batched together -var addArray = []; -var addArraySize = 0; -var removeArray = []; -var removeArraySize = 0; - -//The colors must be different -var activeSandColor = { r: 234, g: 206, b: 106}; -var inactiveSandColor = { r: 233, g: 206, b: 106}; - -//This is used as an optimization, so that we -//will check our 6 neighbors at most once. -var adjacentVoxels = []; -var numAdjacentVoxels = 0; -//Stores a list of voxels we need to activate -var activateMap = {}; - -var UPDATES_PER_SECOND = 12.0; // frames per second -var frameIndex = 0.0; -var oldFrameIndex = 0; - -function update(deltaTime) { - frameIndex += deltaTime * UPDATES_PER_SECOND; - if (Math.floor(frameIndex) == oldFrameIndex) { - return; - } - oldFrameIndex++; - - //Clear the activate map each frame - activateMap = {}; - - //Update all sand in our sandArray - var i = 0; - while (i < numSand) { - //Update the sand voxel and if it doesn't move, deactivate it - if (updateSand(i) == false) { - deactivateSand(i); - } else { - i++; - } - } - - for (var i = 0; i < removeArraySize; i++) { - var voxel = removeArray[i]; - Voxels.eraseVoxel(voxel.x, voxel.y, voxel.z, voxel.s); - } - removeArraySize = 0; - - //Add all voxels that have moved - for (var i = 0; i < addArraySize; i++) { - var voxel = addArray[i]; - Voxels.setVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.r, voxel.g, voxel.b); - } - addArraySize = 0; - - for (var key in activateMap) { - var voxel = activateMap[key]; - Voxels.setVoxel(voxel.x, voxel.y, voxel.z, voxel.s, activeSandColor.r, activeSandColor.g, activeSandColor.b); - sandArray[numSand++] = { x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b }; - } -} - -//Adds a sphere of sand at the center cx,cy,cz -function makeSphere(cx, cy, cz, r, voxelSize) { - - var r2 = r * r; - var distance2; - var dx; - var dy; - var dz; - - for (var x = cx - r; x <= cx + r; x += voxelSize) { - for (var y = cy - r; y <= cy + r; y += voxelSize) { - for (var z = cz - r; z <= cz + r; z += voxelSize) { - dx = Math.abs(x - cx); - dy = Math.abs(y - cy); - dz = Math.abs(z - cz); - distance2 = dx * dx + dy * dy + dz * dz; - if (distance2 <= r2 && isVoxelEmpty(x, y, z, voxelSize)) { - Voxels.setVoxel(x, y, z, voxelSize, activeSandColor.r, activeSandColor.g, activeSandColor.b); - sandArray[numSand++] = { x: x, y: y, z: z, s: voxelSize, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b }; - } - } - } - } -} - -//Check if a given voxel is empty -function isVoxelEmpty(x, y, z, s, isAdjacent) { - var halfSize = s / 2; - var point = {x: x + halfSize, y: y + halfSize, z: z + halfSize }; - - var adjacent = Voxels.getVoxelEnclosingPointBlocking(point); - //If color is all 0, we assume its air. - - if (adjacent.red == 0 && adjacent.green == 0 && adjacent.blue == 0) { - return true; - } - - if (isAdjacent) { - adjacentVoxels[numAdjacentVoxels++] = adjacent; - } - - return false; -} - -//Moves voxel to x,y,z if the space is empty -function tryMoveVoxel(voxel, x, y, z) { - //If the adjacent voxel is empty, we will move to it. - if (isVoxelEmpty(x, y, z, voxel.s, false)) { - var hsize = voxel.s / 2; - for (var i = 0; i < 5; i++) { - var point = {x: voxel.x + directionVecs[i].x * voxel.s + hsize, y: voxel.y + directionVecs[i].y * voxel.s + hsize, z: voxel.z + directionVecs[i].z * voxel.s + hsize }; - adjacentVoxels[numAdjacentVoxels++] = Voxels.getVoxelEnclosingPointBlocking(point); - } - moveVoxel(voxel, x, y, z); - - //Get all adjacent voxels for activation - return true; - } - return false; -} - -//Moves voxel to x,y,z -function moveVoxel(voxel, x, y, z) { - activateNeighbors(); - removeArray[removeArraySize++] = {x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s}; - addArray[addArraySize++] = {x: x, y: y, z: z, s: voxel.s, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b}; - voxel.x = x; - voxel.y = y; - voxel.z = z; -} - -var LEFT = 0; -var BACK = 1; -var RIGHT = 2; -var FRONT = 3; -var TOP = 4; - -//These indicate the different directions to neighbor voxels, so we can iterate them -var directionVecs = []; -directionVecs[LEFT] = {x: -1, y: 0, z: 0}; //Left -directionVecs[BACK] = {x: 0, y: 0, z: -1}; //Back -directionVecs[RIGHT] = {x: 1, y: 0, z: 0}; //Right -directionVecs[FRONT] = {x: 0, y: 0, z: 1}; //Front -directionVecs[TOP] = {x: 0, y: 1, z: 0}; //Top - -function updateSand(i) { - var voxel = sandArray[i]; - var size = voxel.s; - var hsize = size / 2; - numAdjacentVoxels = 0; - - //Down - if (tryMoveVoxel(voxel, voxel.x, voxel.y - size, voxel.z)) { - return true; - } - - //Left, back, right, front - for (var i = 0; i < 4; i++) { - if (isVoxelEmpty(voxel.x + directionVecs[i].x * size, voxel.y + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size, size, true) - && isVoxelEmpty(voxel.x + directionVecs[i].x * size, (voxel.y - size) + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size, size, false)) { - //get the rest of the adjacent voxels - for (var j = i + 1; j < 5; j++) { - var point = {x: voxel.x + directionVecs[j].x * size + hsize, y: voxel.y + directionVecs[j].y * size + hsize, z: voxel.z + directionVecs[j].z * size + hsize }; - adjacentVoxels[numAdjacentVoxels++] = Voxels.getVoxelEnclosingPointBlocking(point); - } - moveVoxel(voxel, voxel.x + directionVecs[i].x * size, voxel.y + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size); - return true; - } - } - - return false; -} - -function activateNeighbors() { - for (var i = 0; i < numAdjacentVoxels; i++) { - var voxel = adjacentVoxels[i]; - //Check if this neighbor is inactive, if so, activate it - if (voxel.red == inactiveSandColor.r && voxel.green == inactiveSandColor.g && voxel.blue == inactiveSandColor.b) { - activateMap[voxel.x.toString() + "," + voxel.y.toString() + ',' + voxel.z.toString()] = voxel; - } - } -} - -//Deactivates a sand voxel to save processing power -function deactivateSand(i) { - var voxel = sandArray[i]; - addArray[addArraySize++] = {x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s, r: inactiveSandColor.r, g: inactiveSandColor.g, b: inactiveSandColor.b}; - sandArray[i] = sandArray[numSand-1]; - numSand--; -} - -//Cleanup -function scriptEnding() { - for (var i = 0; i < numSand; i++) { - var voxel = sandArray[i]; - Voxels.eraseVoxel(voxel.x, voxel.y, voxel.z, voxel.s); - } - Overlays.deleteOverlay(linePreviewTop); - Overlays.deleteOverlay(linePreviewBottom); - Overlays.deleteOverlay(linePreviewLeft); - Overlays.deleteOverlay(linePreviewRight); - scaleSelector.cleanup(); - Overlays.deleteOverlay(voxelTool); -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); - -Script.update.connect(update); -Script.scriptEnding.connect(scriptEnding); - -Voxels.setMaxPacketSize(1); //this is needed or a bug occurs :( -Voxels.setPacketsPerSecond(10000); \ No newline at end of file diff --git a/examples/followThroughOverlappingAction.js b/examples/followThroughOverlappingAction.js deleted file mode 100644 index fdbd5e5550..0000000000 --- a/examples/followThroughOverlappingAction.js +++ /dev/null @@ -1,986 +0,0 @@ -// -// follow-through-and-overlapping-action.js -// -// Simple demonstration showing the visual effect of adding the Disney -// follow through and overlapping action animation technique to avatar movement. -// -// Designed and created by David Wooldridge and Ozan Serim, August 2014 -// -// Version 1.001 -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// location of overlay images -var pathToOverlays = "https://s3.amazonaws.com/hifi-public/ArmSwingScript/ArmSwingOverlays/"; - -// animation -var LEFT = 1; -var RIGHT = 2; -var DIRECTION = 0; - -// min max -var weightMin = 1; -var weightMax = 20; -var jointEffectMax = 5; - -// animation effect variables -var handEffect = 3.4; // 0 to jointEffectMax -var forearmEffect = 2.5; // 0 to jointEffectMax -var limbWeight = 8; // will only use nearest integer, as defines an array length -var effectStrength = 1; // 0 to 1 - overall effect strength -// Overshoot: false uses upper arm as driver for forearm and hand -// true uses upper arm for forearm and lower arm as driver for hand. -var overShoot = false; - -// animate self (tap the 'r' key) -var animateSelf = false; -var selfAnimateFrequency = 7.5; - -// overlay values -var handleValue = 0; -var controlPosX = Window.innerWidth / 2 - 500; -var controlPosY = 0; -var minSliderX = controlPosX + 18; -var sliderRangeX = 190; -var minHandleX = controlPosX - 50; -var handleRangeX = 350 / 2; -var handlePosition = 0; - -// background overlay -var controllerBackground = Overlays.addOverlay("image", { - bounds: {x: controlPosX, y: controlPosY, width: 250, height: 380}, - imageURL: pathToOverlays + "flourish-augmentation-control-overlay.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1 - }); -var controllerRadioSelectedBackground = Overlays.addOverlay("image", { - bounds: {x: controlPosX, y: controlPosY, width: 250, height: 380}, - imageURL: pathToOverlays + "flourish-augmentation-control-radio-selected-overlay.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -// handle overlay -var applyMotionHandle = Overlays.addOverlay("image", { - bounds: {x: minHandleX+handleRangeX-39, y: controlPosY+232, - width: 79, height: 100}, - imageURL: pathToOverlays + "flourish-augmentation-handle-overlay.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1 - }); -// slider overlays -var handEffectSlider = Overlays.addOverlay("image", { - bounds: {x: minSliderX + (handEffect / jointEffectMax * sliderRangeX), - y: controlPosY + 46, width: 25, height: 25}, - imageURL: pathToOverlays + "ddao-slider-handle.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1 - }); -var forearmEffectSlider = Overlays.addOverlay("image", { - bounds: {x: minSliderX + (forearmEffect / jointEffectMax * sliderRangeX), y: controlPosY + 86, - width: 25, height: 25}, - imageURL: pathToOverlays + "ddao-slider-handle.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1 - }); -var limbWeightSlider = Overlays.addOverlay("image", { - bounds: {x: minSliderX + (limbWeight / weightMax * sliderRangeX), y: controlPosY+126, - width: 25, height: 25}, - imageURL: pathToOverlays + "ddao-slider-handle.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1 - }); -var effectStrengthSlider = Overlays.addOverlay("image", { - bounds: {x: minSliderX + (effectStrength * sliderRangeX), y: controlPosY+206, - width: 25, height: 25}, - imageURL: pathToOverlays + "ddao-slider-handle.png", - color: {red: 255, green: 255, blue: 255}, - alpha: 1 - }); - - -// main loop - using averaging filters to add limb element follow-through -var upperArmPDampingFilter = []; -upperArmPDampingFilter.length = parseInt(limbWeight); // sets amount of damping for upper arm pitch -var forearmPDampingFilter = []; -forearmPDampingFilter.length = parseInt(limbWeight) + 2; // sets amount of damping for lower arm pitch - -var cumulativeTime = 0; - -Script.update.connect(function(deltaTime) { - - // used for self animating (press r to invoke) - cumulativeTime += deltaTime; - - // blend three keyframes using handle position to determine progress between keyframes - var animationProgress = handleValue; - - if(animateSelf) { - animationProgress = Math.sin(cumulativeTime * selfAnimateFrequency); - animationProgress++; - animationProgress /= 2; - } - - var keyframeOneWeight = 0; - var keyframeTwoWeight = 0; - var keyframeThreeWeight = 0; - - if(movingHandle || animateSelf) { - keyframeOneWeight = 0; - keyframeTwoWeight = animationProgress; - keyframeThreeWeight = 1 - animationProgress; - } - else if(!movingHandle) { - // idle - keyframeOneWeight = 1; - keyframeTwoWeight = 0; - keyframeThreeWeight = 0; - } - - var shoulderPitch = - keyframeOneWeight * keyFrameOne.joints[8].pitchOffset + - keyframeTwoWeight * keyFrameTwo.joints[8].pitchOffset + - keyframeThreeWeight * keyFrameThree.joints[8].pitchOffset; - - var upperArmPitch = - keyframeOneWeight * keyFrameOne.joints[9].pitchOffset + - keyframeTwoWeight * keyFrameTwo.joints[9].pitchOffset + - keyframeThreeWeight * keyFrameThree.joints[9].pitchOffset; - - // get the change in upper arm pitch and use to add weight effect to forearm (always) and hand (only for overShoot) - var deltaUpperArmPitch = effectStrength * - (upperArmPDampingFilter[upperArmPDampingFilter.length - 1] - - upperArmPDampingFilter[0]); - - var forearmPitch = - keyframeOneWeight * keyFrameOne.joints[10].pitchOffset + - keyframeTwoWeight * keyFrameTwo.joints[10].pitchOffset + - keyframeThreeWeight * keyFrameThree.joints[10].pitchOffset - - (deltaUpperArmPitch/(jointEffectMax - forearmEffect)); - - // there are two methods for calculating the hand follow through - var handPitch = 0; - if(overShoot) { - - // get the change in forearm pitch and use to add weight effect to hand - var deltaForearmPitch = effectStrength * - (forearmPDampingFilter[forearmPDampingFilter.length - 1] - - forearmPDampingFilter[0]); - handPitch = - keyframeOneWeight * keyFrameOne.joints[11].pitchOffset + - keyframeTwoWeight * keyFrameTwo.joints[11].pitchOffset + - keyframeThreeWeight * keyFrameThree.joints[11].pitchOffset + - (deltaForearmPitch /(jointEffectMax - handEffect)); // hand driven by forearm - - } else { - - handPitch = - keyframeOneWeight * keyFrameOne.joints[11].pitchOffset + - keyframeTwoWeight * keyFrameTwo.joints[11].pitchOffset + - keyframeThreeWeight * keyFrameThree.joints[11].pitchOffset - - (deltaUpperArmPitch /(jointEffectMax - handEffect)); // hand driven by upper arm - } - - var shoulderYaw = - keyframeOneWeight * keyFrameOne.joints[8].yawOffset + - keyframeTwoWeight * keyFrameTwo.joints[8].yawOffset + - keyframeThreeWeight * keyFrameThree.joints[8].yawOffset; - - var upperArmYaw = - keyframeOneWeight * keyFrameOne.joints[9].yawOffset + - keyframeTwoWeight * keyFrameTwo.joints[9].yawOffset + - keyframeThreeWeight * keyFrameThree.joints[9].yawOffset; - - var lowerArmYaw = - keyframeOneWeight * keyFrameOne.joints[10].yawOffset + - keyframeTwoWeight * keyFrameTwo.joints[10].yawOffset + - keyframeThreeWeight * keyFrameThree.joints[10].yawOffset; - - var handYaw = - keyframeOneWeight * keyFrameOne.joints[11].yawOffset + - keyframeTwoWeight * keyFrameTwo.joints[11].yawOffset + - keyframeThreeWeight * keyFrameThree.joints[11].yawOffset; - - var shoulderRoll = - keyframeOneWeight * keyFrameOne.joints[8].rollOffset + - keyframeTwoWeight * keyFrameTwo.joints[8].rollOffset + - keyframeThreeWeight * keyFrameThree.joints[8].rollOffset; - - var upperArmRoll = - keyframeOneWeight * keyFrameOne.joints[9].rollOffset + - keyframeTwoWeight * keyFrameTwo.joints[9].rollOffset + - keyframeThreeWeight * keyFrameThree.joints[9].rollOffset; - - var lowerArmRoll = - keyframeOneWeight * keyFrameOne.joints[10].rollOffset + - keyframeTwoWeight * keyFrameTwo.joints[10].rollOffset + - keyframeThreeWeight * keyFrameThree.joints[10].rollOffset; - - var handRoll = - keyframeOneWeight * keyFrameOne.joints[11].rollOffset + - keyframeTwoWeight * keyFrameTwo.joints[11].rollOffset + - keyframeThreeWeight * keyFrameThree.joints[11].rollOffset; - - // filter upper arm pitch - upperArmPDampingFilter.push(upperArmPitch); - upperArmPDampingFilter.shift(); - var upperArmPitchFiltered = 0; - for(ea in upperArmPDampingFilter) upperArmPitchFiltered += upperArmPDampingFilter[ea]; - upperArmPitchFiltered /= upperArmPDampingFilter.length; - upperArmPitch = (effectStrength * upperArmPitchFiltered) + ((1 - effectStrength) * upperArmPitch); - - // filter forearm pitch only if using for hand follow-though - if(overShoot) { - - forearmPDampingFilter.push(forearmPitch); - forearmPDampingFilter.shift(); - var forearmPitchFiltered = 0; - for(ea in forearmPDampingFilter) forearmPitchFiltered += forearmPDampingFilter[ea]; - forearmPitchFiltered /= forearmPDampingFilter.length; - forearmPitch = (effectStrength*forearmPitchFiltered) + ((1-effectStrength) * forearmPitch); - } - - // apply the new rotation data to the joints - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(shoulderPitch, shoulderYaw, shoulderRoll)); - MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees(upperArmPitch, -upperArmYaw, upperArmRoll)); - MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees(forearmPitch, lowerArmYaw, lowerArmRoll)); - MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollDegrees(handPitch, handYaw, handRoll)); -}); - - -// mouse handling -var movingHandEffectSlider = false; -var movingForearmEffectSlider = false; -var movingLimbWeightSlider = false; -var movingDampingSlider = false; -var movingEffectStrengthSlider = false; -var movingHandle = false; - -function mousePressEvent(event) { - - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if(clickedOverlay === applyMotionHandle) movingHandle = true; - else if(clickedOverlay === handEffectSlider) movingHandEffectSlider = true; - else if(clickedOverlay === forearmEffectSlider) movingForearmEffectSlider = true; - else if(clickedOverlay === limbWeightSlider) movingLimbWeightSlider = true; - else if(clickedOverlay === effectStrengthSlider) movingEffectStrengthSlider = true; - else if(clickedOverlay === controllerRadioSelectedBackground && - event.x > 477 && event.x < 497 && event.y > 338 && event.y < 360) { - - overShoot = false; - Overlays.editOverlay(controllerBackground, {visible: true}); - Overlays.editOverlay(controllerRadioSelectedBackground, {visible: false}); - } - else if(clickedOverlay === controllerBackground && - event.x > 477 && event.x < 497 && event.y > 338 && event.y < 360){ - - overShoot = true; - Overlays.editOverlay(controllerBackground, {visible: false}); - Overlays.editOverlay(controllerRadioSelectedBackground, {visible: true}); - } -} -function mouseMoveEvent(event) { - - if(movingHandle) { - - var thumbClickOffsetX = event.x - minHandleX; - var thumbPositionNormalised = (thumbClickOffsetX - handleRangeX) / handleRangeX; - if(thumbPositionNormalised <= -1) thumbPositionNormalised = -1; - else if(thumbPositionNormalised > 1) thumbPositionNormalised = 1; - - if(thumbPositionNormalised < 0) DIRECTION = LEFT; - else DIRECTION = RIGHT; - - handleValue = (thumbPositionNormalised + 1) / 2; - var handleX = (thumbPositionNormalised * handleRangeX) + handleRangeX - 39; - Overlays.editOverlay(applyMotionHandle, {x: handleX + minHandleX}); - return; - } - else if(movingHandEffectSlider) { - - var thumbClickOffsetX = event.x - minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX; - if(thumbPositionNormalised < 0) thumbPositionNormalised = 0; - if(thumbPositionNormalised > 1) thumbPositionNormalised = 1; - handEffect = (thumbPositionNormalised - 0.08) * jointEffectMax; - var sliderX = thumbPositionNormalised * sliderRangeX ; - Overlays.editOverlay(handEffectSlider, {x: sliderX + minSliderX}); - } - else if(movingForearmEffectSlider) { - - var thumbClickOffsetX = event.x - minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX; - if(thumbPositionNormalised < 0) thumbPositionNormalised = 0; - if(thumbPositionNormalised > 1) thumbPositionNormalised = 1; - forearmEffect = (thumbPositionNormalised - 0.1) * jointEffectMax; - var sliderX = thumbPositionNormalised * sliderRangeX ; - Overlays.editOverlay(forearmEffectSlider, {x: sliderX + minSliderX}); - } - else if(movingLimbWeightSlider) { - - var thumbClickOffsetX = event.x - minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX; - if(thumbPositionNormalised<0) thumbPositionNormalised = 0; - if(thumbPositionNormalised>1) thumbPositionNormalised = 1; - limbWeight = thumbPositionNormalised * weightMax; - if(limbWeight < weightMin) limbWeight = weightMin; - upperArmPDampingFilter.length = parseInt(limbWeight); - var sliderX = thumbPositionNormalised * sliderRangeX ; - Overlays.editOverlay(limbWeightSlider, {x: sliderX + minSliderX}); - } - else if(movingEffectStrengthSlider) { - - var thumbClickOffsetX = event.x - minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX; - if(thumbPositionNormalised < 0) thumbPositionNormalised = 0; - if(thumbPositionNormalised > 1) thumbPositionNormalised = 1; - effectStrength = thumbPositionNormalised; - var sliderX = thumbPositionNormalised * sliderRangeX ; - Overlays.editOverlay(effectStrengthSlider, {x: sliderX + minSliderX}); - return; - } -} -function mouseReleaseEvent(event) { - - if(movingHandle) { - - movingHandle = false; - handleValue = 0; - Overlays.editOverlay(applyMotionHandle, {x: minHandleX+handleRangeX - 39}); - } - else if(movingHandEffectSlider) movingHandEffectSlider = false; - else if(movingForearmEffectSlider) movingForearmEffectSlider = false; - else if(movingLimbWeightSlider) movingLimbWeightSlider = false; - else if(movingEffectStrengthSlider) movingEffectStrengthSlider = false; - else if(movingDampingSlider) movingDampingSlider = false; -} - -// set up mouse and keyboard callbacks -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); -Controller.keyPressEvent.connect(keyPressEvent); - -// keyboard command -function keyPressEvent(event) { - - if (event.text == "q") { - print('hand effect = ' + handEffect + '\n'); - print('forearmEffect = ' + forearmEffect + '\n'); - print('limbWeight = ' + limbWeight + '\n'); - print('effectStrength = ' + effectStrength + '\n'); - } - else if (event.text == "r") { - animateSelf = !animateSelf; - } - else if (event.text == "[") { - selfAnimateFrequency += 0.5; - print('selfAnimateFrequency = '+selfAnimateFrequency); - } - else if (event.text == "]") { - selfAnimateFrequency -= 0.5; - print('selfAnimateFrequency = '+selfAnimateFrequency); - } -} - - -// zero out all joints -function resetJoints() { - - var avatarJointNames = MyAvatar.getJointNames(); - for (var i = 0; i < avatarJointNames.length; i++) - MyAvatar.clearJointData(avatarJointNames[i]); -} - -// Script ending -Script.scriptEnding.connect(function() { - - // delete the overlays - Overlays.deleteOverlay(controllerBackground); - Overlays.deleteOverlay(controllerRadioSelectedBackground); - Overlays.deleteOverlay(handEffectSlider); - Overlays.deleteOverlay(forearmEffectSlider); - Overlays.deleteOverlay(limbWeightSlider); - Overlays.deleteOverlay(effectStrengthSlider); - Overlays.deleteOverlay(applyMotionHandle); - - // leave the avi in zeroed out stance - resetJoints(); -}); - - -// animation data. animation keyframes produced using walk.js -MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees(80,0,0)); -var keyFrameOne = -{ - "name":"FemaleStandingOne", - "settings":{ - "baseFrequency":70, - "flyingHipsPitch":60, - "takeFlightVelocity":40, - "maxBankingAngle":40 - }, - "adjusters":{ - "legsSeparation":{ - "strength":-0.03679245283018867, - "separationAngle":50 - }, - "stride":{ - "strength":0, - "upperLegsPitch":30, - "lowerLegsPitch":15, - "upperLegsPitchOffset":0.2, - "lowerLegsPitchOffset":1.5 - } - }, - "joints":[ - { - "name":"hips", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0, - "thrust":0, - "bob":0, - "sway":0, - "thrustPhase":180, - "bobPhase":0, - "swayPhase":-90, - "thrustOffset":0, - "bobOffset":0, - "swayOffset":0 - }, - { - "name":"upperLegs", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"lowerLegs", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"feet", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"toes", - "pitch":2.0377358490566038, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":4.415094339622641, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine", - "pitch":1.660377358490566, - "yaw":0, - "roll":0, - "pitchPhase":-180, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine1", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine2", - "pitch":2.1132075471698113, - "yaw":0, - "roll":0, - "pitchPhase":-0.6792452830188722, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"shoulders", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0.6792452830188678, - "yawOffset":-5.20754716981132, - "rollOffset":-2.9433962264150937 - }, - { - "name":"upperArms", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":77.77358490566039, - "yawOffset":9.169811320754715, - "rollOffset":0 - }, - { - "name":"lowerArms", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"hands", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":1.6981132075471694, - "yawOffset":-1.0188679245283017, - "rollOffset":1.0188679245283017 - }, - { - "name":"head", - "pitch":0, - "yaw":1.7358490566037734, - "roll":1.5094339622641508, - "pitchPhase":-90.33962264150944, - "yawPhase":94.41509433962267, - "rollPhase":0, - "pitchOffset":1.6981132075471694, - "yawOffset":0, - "rollOffset":0 - } - ] -}; -var keyFrameTwo = -{ - "name":"FemaleStandingOne", - "settings":{ - "baseFrequency":70, - "flyingHipsPitch":60, - "takeFlightVelocity":40, - "maxBankingAngle":40 - }, - "adjusters":{ - "legsSeparation":{ - "strength":-0.03679245283018867, - "separationAngle":50 - }, - "stride":{ - "strength":0, - "upperLegsPitch":30, - "lowerLegsPitch":15, - "upperLegsPitchOffset":0.2, - "lowerLegsPitchOffset":1.5 - } - }, - "joints":[ - { - "name":"hips", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0, - "thrust":0, - "bob":0, - "sway":0, - "thrustPhase":180, - "bobPhase":0, - "swayPhase":-90, - "thrustOffset":0, - "bobOffset":0, - "swayOffset":0 - }, - { - "name":"upperLegs", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"lowerLegs", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"feet", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"toes", - "pitch":2.0377358490566038, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":4.415094339622641, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine", - "pitch":1.660377358490566, - "yaw":0, - "roll":0, - "pitchPhase":-180, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine1", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine2", - "pitch":2.1132075471698113, - "yaw":0, - "roll":0, - "pitchPhase":-0.6792452830188722, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"shoulders", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0.6792452830188678, - "yawOffset":-5.20754716981132, - "rollOffset":-2.9433962264150937 - }, - { - "name":"upperArms", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":49.584905660377345, - "yawOffset":9.169811320754715, - "rollOffset":0 - }, - { - "name":"lowerArms", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"hands", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":-13, - "yawOffset":-1.0188679245283017, - "rollOffset":1.0188679245283017 - }, - { - "name":"head", - "pitch":0, - "yaw":1.7358490566037734, - "roll":1.5094339622641508, - "pitchPhase":-90.33962264150944, - "yawPhase":94.41509433962267, - "rollPhase":0, - "pitchOffset":1.6981132075471694, - "yawOffset":0, - "rollOffset":0 - } - ] -}; -var keyFrameThree = -{ - "name":"FemaleStandingOne", - "settings":{ - "baseFrequency":70, - "flyingHipsPitch":60, - "takeFlightVelocity":40, - "maxBankingAngle":40 - }, - "adjusters":{ - "legsSeparation":{ - "strength":-0.03679245283018867, - "separationAngle":50 - }, - "stride":{ - "strength":0, - "upperLegsPitch":30, - "lowerLegsPitch":15, - "upperLegsPitchOffset":0.2, - "lowerLegsPitchOffset":1.5 - } - }, - "joints":[ - { - "name":"hips", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0, - "thrust":0, - "bob":0, - "sway":0, - "thrustPhase":180, - "bobPhase":0, - "swayPhase":-90, - "thrustOffset":0, - "bobOffset":0, - "swayOffset":0 - }, - { - "name":"upperLegs", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"lowerLegs", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"feet", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"toes", - "pitch":2.0377358490566038, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":4.415094339622641, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine", - "pitch":1.660377358490566, - "yaw":0, - "roll":0, - "pitchPhase":-180, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine1", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"spine2", - "pitch":2.1132075471698113, - "yaw":0, - "roll":0, - "pitchPhase":-0.6792452830188722, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"shoulders", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":-21.0566037735849, - "yawOffset":-5.20754716981132, - "rollOffset":-2.9433962264150937 - }, - { - "name":"upperArms", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":-33.28301886792452, - "yawOffset":9.169811320754715, - "rollOffset":0 - }, - { - "name":"lowerArms", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":0, - "yawOffset":0, - "rollOffset":0 - }, - { - "name":"hands", - "pitch":0, - "yaw":0, - "roll":0, - "pitchPhase":0, - "yawPhase":0, - "rollPhase":0, - "pitchOffset":-13, - "yawOffset":-1.0188679245283017, - "rollOffset":1.0188679245283017 - }, - { - "name":"head", - "pitch":0, - "yaw":1.7358490566037734, - "roll":1.5094339622641508, - "pitchPhase":-90.33962264150944, - "yawPhase":94.41509433962267, - "rollPhase":0, - "pitchOffset":1.6981132075471694, - "yawOffset":0, - "rollOffset":0 - } - ] -}; \ No newline at end of file diff --git a/examples/fountain.js b/examples/fountain.js deleted file mode 100644 index aea53fb405..0000000000 --- a/examples/fountain.js +++ /dev/null @@ -1,77 +0,0 @@ -// -// fountain.js -// examples -// -// 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 -// - -function vLength(v) { - return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); -} - -function printVector(v) { - print(v.x + ", " + v.y + ", " + v.z + "\n"); -} - -// Create a random vector with individual lengths between a,b -function randVector(a, b) { - var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) }; - return rval; -} - -function vMinus(a, b) { - var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }; - return rval; -} - -function vPlus(a, b) { - var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; - return rval; -} - -function vCopy(a, b) { - a.x = b.x; - a.y = b.y; - a.z = b.z; - return; -} - -// Returns a vector which is fraction of the way between a and b -function vInterpolate(a, b, fraction) { - var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction }; - return rval; -} - -var position = { x: 5.0, y: 0.6, z: 5.0 }; -Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255); - -var totalEntities = 0; -function makeFountain(deltaTime) { - if (Math.random() < 0.10) { - //print("Made entity!\n"); - var radius = (0.02 + (Math.random() * 0.05)); - var properties = { - type: "Sphere", - position: position, - dimensions: { x: radius, y: radius, z: radius}, - color: { red: 0, green: 0, blue: 128 }, - velocity: { x: (Math.random() * 1.0 - 0.5), - y: (1.0 + (Math.random() * 2.0)), - z: (Math.random() * 1.0 - 0.5) }, - gravity: { x: 0, y: -0.1, z: 0 }, - damping: 0.25, - lifetime: 1 - } - - Entities.addEntity(properties); - totalEntities++; - } - if (totalEntities > 100) { - Script.stop(); - } -} -// register the call back so it fires before each data send -Script.update.connect(makeFountain); \ No newline at end of file diff --git a/examples/gameoflife.js b/examples/gameoflife.js deleted file mode 100644 index 3fcbfa8138..0000000000 --- a/examples/gameoflife.js +++ /dev/null @@ -1,140 +0,0 @@ -// -// gameoflife.js -// examples -// -// Copyright 2014 High Fidelity, Inc. -// -// The following is an example of Conway's Game of Life (http://en.wikipedia.org/wiki/Conway's_Game_of_Life) -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var NUMBER_OF_CELLS_EACH_DIMENSION = 64; -var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIMENSION; - -var currentCells = []; -var nextCells = []; - -var METER_LENGTH = 1; -var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; - -// randomly populate the cell start values -for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - // create the array to hold this row - currentCells[i] = []; - - // create the array to hold this row in the nextCells array - nextCells[i] = []; - - for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - currentCells[i][j] = Math.floor(Math.random() * 2); - - // put the same value in the nextCells array for first board draw - nextCells[i][j] = currentCells[i][j]; - } -} - -function isNeighbourAlive(i, j) { - if (i < 0 || i >= NUMBER_OF_CELLS_EACH_DIMENSION - || i < 0 || j >= NUMBER_OF_CELLS_EACH_DIMENSION) { - return 0; - } else { - return currentCells[i][j]; - } -} - -function updateCells() { - var i = 0; - var j = 0; - - for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - // figure out the number of live neighbours for the i-j cell - var liveNeighbours = - isNeighbourAlive(i + 1, j - 1) + isNeighbourAlive(i + 1, j) + isNeighbourAlive(i + 1, j + 1) + - isNeighbourAlive(i, j - 1) + isNeighbourAlive(i, j + 1) + - isNeighbourAlive(i - 1, j - 1) + isNeighbourAlive(i - 1, j) + isNeighbourAlive(i - 1, j + 1); - - if (currentCells[i][j]) { - // live cell - - if (liveNeighbours < 2) { - // rule #1 - under-population - this cell will die - // mark it zero to mark the change - nextCells[i][j] = 0; - } else if (liveNeighbours < 4) { - // rule #2 - this cell lives - // mark it -1 to mark no change - nextCells[i][j] = -1; - } else { - // rule #3 - overcrowding - this cell dies - // mark it zero to mark the change - nextCells[i][j] = 0; - } - } else { - // dead cell - if (liveNeighbours == 3) { - // rule #4 - reproduction - this cell revives - // mark it one to mark the change - nextCells[i][j] = 1; - } else { - // this cell stays dead - // mark it -1 for no change - nextCells[i][j] = -1; - } - } - - if (Math.random() < 0.001) { - // Random mutation to keep things interesting in there. - nextCells[i][j] = 1; - } - } - } - - for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - if (nextCells[i][j] != -1) { - // there has been a change to this cell, change the value in the currentCells array - currentCells[i][j] = nextCells[i][j]; - } - } - } -} - -function sendNextCells() { - for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { - for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) { - if (nextCells[i][j] != -1) { - // there has been a change to the state of this cell, send it - - // find the x and y position for this voxel, z = 0 - var x = j * cellScale; - var y = i * cellScale; - - // queue a packet to add a voxel for the new cell - var color = (nextCells[i][j] == 1) ? 255 : 1; - Voxels.setVoxel(x, y, 0, cellScale, color, color, color); - } - } - } -} - -var sentFirstBoard = false; - -function step(deltaTime) { - if (sentFirstBoard) { - // we've already sent the first full board, perform a step in time - updateCells(); - } else { - // this will be our first board send - sentFirstBoard = true; - } - - sendNextCells(); -} - -print("here"); -Script.update.connect(step); -Voxels.setPacketsPerSecond(200); -print("now here"); diff --git a/examples/grenadeLauncher.js b/examples/grenadeLauncher.js deleted file mode 100644 index 3907e41ea6..0000000000 --- a/examples/grenadeLauncher.js +++ /dev/null @@ -1,368 +0,0 @@ -// -// grenadeLauncher.js -// examples -// Created by Ben Arnold on 7/11/14. -// This is a modified version of gun.js by Brad Hefta-Gaub. -// -// Copyright 2013 High Fidelity, Inc. -// -// This is an example script that turns the hydra controllers and mouse into a entity gun. -// It reads the controller, watches for trigger pulls, and launches entities. -// When entities collide with voxels they blow big holes out of the voxels. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -function getRandomFloat(min, max) { - return Math.random() * (max - min) + min; -} - -var lastX = 0; -var lastY = 0; -var yawFromMouse = 0; -var pitchFromMouse = 0; -var isMouseDown = false; - -var BULLET_VELOCITY = 3.0; -var MIN_THROWER_DELAY = 1000; -var MAX_THROWER_DELAY = 1000; -var LEFT_BUTTON_1 = 1; -var LEFT_BUTTON_3 = 3; -var RELOAD_INTERVAL = 5; - -var showScore = false; - -// Load some sound to use for loading and firing -var fireSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw"); -var loadSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw"); -var impactSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/BulletImpact2.raw"); -var targetHitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw"); -var targetLaunchSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw"); - -var gunModel = "http://public.highfidelity.io/models/attachments/HaloGun.fst"; - -var audioOptions { - volume: 0.9 -} - -var shotsFired = 0; - -var shotTime = new Date(); - -// initialize our triggers -var triggerPulled = new Array(); -var numberOfTriggers = Controller.getNumberOfTriggers(); -for (t = 0; t < numberOfTriggers; t++) { - triggerPulled[t] = false; -} - -var isLaunchButtonPressed = false; - -var score = 0; - -// Create a reticle image in center of screen -var screenSize = Controller.getViewportDimensions(); -var reticle = Overlays.addOverlay("image", { - x: screenSize.x / 2 - 16, - y: screenSize.y / 2 - 16, - width: 32, - height: 32, - imageURL: HIFI_PUBLIC_BUCKET + "images/reticle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - -if (showScore) { - var text = Overlays.addOverlay("text", { - x: screenSize.x / 2 - 100, - y: screenSize.y / 2 - 50, - width: 150, - height: 50, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 0, blue: 0}, - topMargin: 4, - leftMargin: 4, - text: "Score: " + score - }); -} - -function printVector(string, vector) { - print(string + " " + vector.x + ", " + vector.y + ", " + vector.z); -} - -function shootBullet(position, velocity) { - var BULLET_SIZE = 0.1; - var BULLET_GRAVITY = -3.0; - //Creates a grenade with a reasonable lifetime so that one is less likely to accidentally blow up - //far away voxels - Entities.addEntity( - { type: "Sphere", - position: position, - collisionsWillMove: true, - dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, - color: { red: 10, green: 10, blue: 10 }, - velocity: velocity, - gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, - lifetime: 10.0, - damping: 0 }); - - // Play firing sounds - audioOptions.position = position; - Audio.playSound(fireSound, audioOptions); - shotsFired++; - if ((shotsFired % RELOAD_INTERVAL) == 0) { - Audio.playSound(loadSound, audioOptions); - } -} - -function shootTarget() { - var TARGET_SIZE = 0.25; - var TARGET_GRAVITY = -0.6; - var TARGET_UP_VELOCITY = 3.0; - var TARGET_FWD_VELOCITY = 5.0; - var DISTANCE_TO_LAUNCH_FROM = 3.0; - var camera = Camera.getPosition(); - //printVector("camera", camera); - var targetDirection = Quat.angleAxis(getRandomFloat(-20.0, 20.0), { x:0, y:1, z:0 }); - targetDirection = Quat.multiply(Camera.getOrientation(), targetDirection); - var forwardVector = Quat.getFront(targetDirection); - //printVector("forwardVector", forwardVector); - var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_TO_LAUNCH_FROM)); - //printVector("newPosition", newPosition); - var velocity = Vec3.multiply(forwardVector, TARGET_FWD_VELOCITY); - velocity.y += TARGET_UP_VELOCITY; - //printVector("velocity", velocity); - - Entities.addEntity( - { type: "Sphere", - position: newPosition, - collisionsWillMove: true, - dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, - color: { red: 0, green: 200, blue: 200 }, - velocity: velocity, - gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, - lifetime: 1000.0, - damping: 0.99 }); - - // Record start time - shotTime = new Date(); - - // Play target shoot sound - audioOptions.position = newPosition; - Audio.playSound(targetLaunchSound, audioOptions); -} - - - -function entityCollisionWithVoxel(entity, voxel, collision) { - -print("entityCollisionWithVoxel...."); - - var VOXEL_SIZE = 0.5; - // Don't make this big. I mean it. - var CRATER_RADIUS = 5; - var entityProperties = Entities.getEntityProperties(entity); - var position = entityProperties.position; - Entities.deleteEntity(entity); - - audioOptions.position = collision.contactPoint; - Audio.playSound(impactSound, audioOptions); - - // Make a crater - var center = collision.contactPoint; - var RADIUS = CRATER_RADIUS * VOXEL_SIZE; - var RADIUS2 = RADIUS * RADIUS; - var distance2; - var dx; - var dy; - var dz; - for (var x = center.x - RADIUS; x <= center.x + RADIUS; x += VOXEL_SIZE) { - for (var y = center.y - RADIUS; y <= center.y + RADIUS; y += VOXEL_SIZE) { - for (var z = center.z - RADIUS; z <= center.z + RADIUS; z += VOXEL_SIZE) { - dx = Math.abs(x - center.x); - dy = Math.abs(y - center.y); - dz = Math.abs(z - center.z); - distance2 = dx * dx + dy * dy + dz * dz; - if (distance2 <= RADIUS2) { - Voxels.eraseVoxel(x, y, z, VOXEL_SIZE); - } - } - } - } -} - -function entityCollisionWithEntity(entity1, entity2, collision) { - score++; - if (showScore) { - Overlays.editOverlay(text, { text: "Score: " + score } ); - } - - // Record shot time - var endTime = new Date(); - var msecs = endTime.valueOf() - shotTime.valueOf(); - //print("hit, msecs = " + msecs); - //Vec3.print("penetration = ", collision.penetration); - //Vec3.print("contactPoint = ", collision.contactPoint); - Entities.deleteEntity(entity1); - Entities.deleteEntity(entity2); - // play the sound near the camera so the shooter can hear it - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(targetHitSound, audioOptions); -} - -function keyPressEvent(event) { - // if our tools are off, then don't do anything - if (event.text == "t") { - var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY; - Script.setTimeout(shootTarget, time); - } else if (event.text == ".") { - shootFromMouse(); - } else if (event.text == "r") { - playLoadSound(); - } -} - -function playLoadSound() { - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(loadSound, audioOptions); -} - -//MyAvatar.attach(gunModel, "RightHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); -MyAvatar.attach(gunModel, "LeftHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); - -// Give a bit of time to load before playing sound -Script.setTimeout(playLoadSound, 2000); - -function update(deltaTime) { - - // Check for mouseLook movement, update rotation - // rotate body yaw for yaw received from controller or mouse - var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMouse, z: 0 } )); - MyAvatar.orientation = newOrientation; - yawFromMouse = 0; - - // apply pitch from controller or mouse - var newPitch = MyAvatar.headPitch + pitchFromMouse; - MyAvatar.headPitch = newPitch; - pitchFromMouse = 0; - - // Check hydra controller for launch button press - if (!isLaunchButtonPressed && Controller.isButtonPressed(LEFT_BUTTON_3)) { - isLaunchButtonPressed = true; - var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY; - Script.setTimeout(shootTarget, time); - } else if (isLaunchButtonPressed && !Controller.isButtonPressed(LEFT_BUTTON_3)) { - isLaunchButtonPressed = false; - - } - - // Check hydra controller for trigger press - - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - - // this is expected for hydras - if (numberOfTriggers == 2 && controllersPerTrigger == 2) { - for (var t = 0; t < numberOfTriggers; t++) { - var shootABullet = false; - var triggerValue = Controller.getTriggerValue(t); - - if (triggerPulled[t]) { - // must release to at least 0.1 - if (triggerValue < 0.1) { - triggerPulled[t] = false; // unpulled - } - } else { - // must pull to at least 0.9 - if (triggerValue > 0.9) { - triggerPulled[t] = true; // pulled - shootABullet = true; - } - } - - if (shootABullet) { - - var palmController = t * controllersPerTrigger; - var palmPosition = Controller.getSpatialControlPosition(palmController); - - var fingerTipController = palmController + 1; - var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - - var palmToFingerTipVector = - { x: (fingerTipPosition.x - palmPosition.x), - y: (fingerTipPosition.y - palmPosition.y), - z: (fingerTipPosition.z - palmPosition.z) }; - - // just off the front of the finger tip - var position = { x: fingerTipPosition.x + palmToFingerTipVector.x/2, - y: fingerTipPosition.y + palmToFingerTipVector.y/2, - z: fingerTipPosition.z + palmToFingerTipVector.z/2}; - - var linearVelocity = 25; - - var velocity = { x: palmToFingerTipVector.x * linearVelocity, - y: palmToFingerTipVector.y * linearVelocity, - z: palmToFingerTipVector.z * linearVelocity }; - - shootBullet(position, velocity); - } - } - } -} - -function mousePressEvent(event) { - isMouseDown = true; - lastX = event.x; - lastY = event.y; - //audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - //Audio.playSound(loadSound, audioOptions); -} - -function shootFromMouse() { - var DISTANCE_FROM_CAMERA = 2.0; - var camera = Camera.getPosition(); - var forwardVector = Quat.getFront(Camera.getOrientation()); - var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA)); - var velocity = Vec3.multiply(forwardVector, BULLET_VELOCITY); - shootBullet(newPosition, velocity); -} - -function mouseReleaseEvent(event) { - // position - isMouseDown = false; -} - -function mouseMoveEvent(event) { - //Move the camera if LEFT_BUTTON_1 is pressed - if (Controller.isButtonPressed(LEFT_BUTTON_1)) { - var MOUSE_YAW_SCALE = -0.25; - var MOUSE_PITCH_SCALE = -12.5; - var FIXED_MOUSE_TIMESTEP = 0.016; - yawFromMouse += ((event.x - lastX) * MOUSE_YAW_SCALE * FIXED_MOUSE_TIMESTEP); - pitchFromMouse += ((event.y - lastY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP); - lastX = event.x; - lastY = event.y; - } -} - -function scriptEnding() { - Overlays.deleteOverlay(reticle); - Overlays.deleteOverlay(text); - MyAvatar.detachOne(gunModel); -} - -Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel); -Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); -Script.scriptEnding.connect(scriptEnding); -Script.update.connect(update); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.keyPressEvent.connect(keyPressEvent); - - - diff --git a/examples/growTrees.js b/examples/growTrees.js deleted file mode 100644 index a5b55eecd6..0000000000 --- a/examples/growTrees.js +++ /dev/null @@ -1,834 +0,0 @@ -// -// growPlants.js -// examples -// -// Created by Benjamin Arnold on May 29, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// This sample script allows the user to grow different types of plants on the voxels -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting -var previewLineWidth = 2.0; - -var voxelSize = 1; -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - -var MAX_VOXEL_SCALE_POWER = 5; -var MIN_VOXEL_SCALE_POWER = -8; -var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); -var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); - - -var linePreviewTop = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewBottom = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewLeft = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - -var linePreviewRight = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z: 0}, - end: { x: 0, y: 0, z: 0}, - color: { red: 0, green: 255, blue: 0}, - alpha: 1, - visible: false, - lineWidth: previewLineWidth - }); - - -var UIColor = { red: 0, green: 160, blue: 0}; -var activeUIColor = { red: 0, green: 255, blue: 0}; - -var toolHeight = 50; -var toolWidth = 50; - -var editToolsOn = true; - -var voxelToolSelected = false; - -var scaleSelectorWidth = 144; -var scaleSelectorHeight = 37; - -var scaleSelectorX = windowDimensions.x / 5.0; -var scaleSelectorY = windowDimensions.y - scaleSelectorHeight; - -var voxelTool = Overlays.addOverlay("image", { - x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-tool.svg", - visible: editToolsOn, - color: UIColor, - alpha: 0.9 - }); - -var copyScale = true; -function ScaleSelector() { - this.x = scaleSelectorX; - this.y = scaleSelectorY; - this.width = scaleSelectorWidth; - this.height = scaleSelectorHeight; - - this.displayPower = false; - this.scale = 1.0; - this.power = 0; - - this.FIRST_PART = this.width * 40.0 / 100.0; - this.SECOND_PART = this.width * 37.0 / 100.0; - - this.buttonsOverlay = Overlays.addOverlay("image", { - x: this.x, y: this.y, - width: this.width, height: this.height, - //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - visible: editToolsOn, - color: activeUIColor - }); - this.textOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - topMargin: 13, - text: this.scale.toString(), - backgroundAlpha: 0.0, - visible: editToolsOn, - color: activeUIColor - }); - this.powerOverlay = Overlays.addOverlay("text", { - x: this.x + this.FIRST_PART, y: this.y, - width: this.SECOND_PART, height: this.height, - leftMargin: 28, - text: this.power.toString(), - backgroundAlpha: 0.0, - visible: false, - color: activeUIColor - }); - this.setScale = function(scale) { - if (scale > MAX_VOXEL_SCALE) { - scale = MAX_VOXEL_SCALE; - } - if (scale < MIN_VOXEL_SCALE) { - scale = MIN_VOXEL_SCALE; - } - - this.scale = scale; - this.power = Math.floor(Math.log(scale) / Math.log(2)); - this.update(); - } - - this.show = function(doShow) { - Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); - Overlays.editOverlay(this.textOverlay, {visible: doShow}); - Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); - } - - this.move = function() { - this.x = swatchesX + swatchesWidth; - this.y = swatchesY; - - Overlays.editOverlay(this.buttonsOverlay, { - x: this.x, y: this.y, - }); - Overlays.editOverlay(this.textOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - Overlays.editOverlay(this.powerOverlay, { - x: this.x + this.FIRST_PART, y: this.y, - }); - } - - - this.switchDisplay = function() { - this.displayPower = !this.displayPower; - - if (this.displayPower) { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 18, - text: "2" - }); - Overlays.editOverlay(this.powerOverlay, { - text: this.power.toString(), - visible: editToolsOn - }); - } else { - Overlays.editOverlay(this.textOverlay, { - leftMargin: 13, - text: this.scale.toString() - }); - Overlays.editOverlay(this.powerOverlay, { - visible: false - }); - } - } - - this.update = function() { - if (this.displayPower) { - Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); - } else { - Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); - } - } - - this.incrementScale = function() { - copyScale = false; - if (this.power < MAX_VOXEL_SCALE_POWER) { - ++this.power; - this.scale *= 2.0; - this.update(); - } - } - - this.decrementScale = function() { - copyScale = false; - if (MIN_VOXEL_SCALE_POWER < this.power) { - --this.power; - this.scale /= 2.0; - this.update(); - } - } - - this.clicked = function(x, y) { - if (this.x < x && x < this.x + this.width && - this.y < y && y < this.y + this.height) { - - if (x < this.x + this.FIRST_PART) { - this.decrementScale(); - } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { - this.switchDisplay(); - } else { - this.incrementScale(); - } - return true; - } - return false; - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.buttonsOverlay); - Overlays.deleteOverlay(this.textOverlay); - Overlays.deleteOverlay(this.powerOverlay); - } - -} -var scaleSelector = new ScaleSelector(); - - -function calculateVoxelFromIntersection(intersection, operation) { - - var resultVoxel; - - var x; - var y; - var z; - - // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest - // ancestor voxel of our target size that contains our intersected voxel. - if (voxelSize > intersection.voxel.s) { - x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; - y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; - z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; - } else { - // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. - // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result - // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting - // voxel this still works and results in returning the intersecting voxel which is what we want - var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); - - var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); - x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; - y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; - z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; - } - resultVoxel = { x: x, y: y, z: z, s: voxelSize }; - var highlightAt = { x: x, y: y, z: z, s: voxelSize }; - - - - // we only do the "add to the face we're pointing at" adjustment, if the operation is an add - // operation, and the target voxel size is equal to or smaller than the intersecting voxel. - var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); - - // now we also want to calculate the "edge square" for the face for this voxel - if (intersection.face == "MIN_X_FACE") { - - highlightAt.x = x - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x -= voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_X_FACE") { - - highlightAt.x = x + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.x += resultVoxel.s; - } - - resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MIN_Y_FACE") { - - highlightAt.y = y - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y -= voxelSize; - } - - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; - - } else if (intersection.face == "MAX_Y_FACE") { - - highlightAt.y = y + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.y += voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; - - } else if (intersection.face == "MIN_Z_FACE") { - - highlightAt.z = z - zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z -= voxelSize; - } - - resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } else if (intersection.face == "MAX_Z_FACE") { - - highlightAt.z = z + voxelSize + zFightingSizeAdjust; - if (wantAddAdjust) { - resultVoxel.z += voxelSize; - } - - resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; - resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; - resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; - - } - return resultVoxel; -} - -var trackLastMouseX = 0; -var trackLastMouseY = 0; - -function showPreviewLines() { - - var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); - - var intersection = Voxels.findRayIntersection(pickRay); - - if (intersection.intersects) { - var resultVoxel = calculateVoxelFromIntersection(intersection, ""); - Overlays.editOverlay(linePreviewTop, { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); - Overlays.editOverlay(linePreviewBottom, { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); - Overlays.editOverlay(linePreviewLeft, { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); - Overlays.editOverlay(linePreviewRight, { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); - } else { - Overlays.editOverlay(linePreviewTop, { visible: false }); - Overlays.editOverlay(linePreviewBottom, { visible: false }); - Overlays.editOverlay(linePreviewLeft, { visible: false }); - Overlays.editOverlay(linePreviewRight, { visible: false }); - } -} - -function mouseMoveEvent(event) { - trackLastMouseX = event.x; - trackLastMouseY = event.y; - if (!voxelToolSelected) { - return; - } - showPreviewLines(); -} - - -// Array of possible trees, right now there is only one -var treeTypes = []; - -treeTypes.push({ - name: "Tall Green", - // Voxel Colors - wood: { r: 133, g: 81, b: 53 }, - leaves: { r: 22, g: 83, b: 31 }, - - // How tall the tree is - height: { min: 20, max: 60 }, - middleHeight: 0.3, - - // Chance of making a branch - branchChance: { min: 0.01, max: 0.1 }, - branchLength: { min: 30, max: 60 }, - branchThickness: { min: 2, max: 7}, - - // The width of the core, affects width and shape - coreWidth: { min: 1, max: 4 }, - - //TODO: Make this quadratic splines instead of linear - bottomThickness: { min: 2, max: 8 }, - middleThickness: { min: 1, max: 4 }, - topThickness: { min: 3, max: 6 }, - - //Modifies leaves at top - leafCapSizeOffset: 0 -}); - -// Applies noise to color -var colorNoiseRange = 0.2; - - -// Useful constants -var LEFT = 0; -var BACK = 1; -var RIGHT = 2; -var FRONT = 3; -var UP = 4; - -// Interpolates between min and max of treevar based on b -function interpolate(treeVar, b) { - return (treeVar.min + (treeVar.max - treeVar.min) * b); -} - -function makeBranch(x, y, z, step, length, dir, thickness, wood, leaves) { - var moveDir; - - var currentThickness; - //thickness attenuates to thickness - 3 - var finalThickness = thickness - 3; - if (finalThickness < 1) { - finalThickness = 1; - } - //Iterative branch generation - while (true) { - - //If we are at the end, place a ball of leaves - if (step == 0) { - makeSphere(x, y, z, 2 + finalThickness, leaves); - return; - } - //thickness attenuation - currentThickness = Math.round((finalThickness + (thickness - finalThickness) * (step/length))) - 1; - - - // If the branch is thick, grow a vertical slice - if (currentThickness > 0) { - for (var i = -currentThickness; i <= currentThickness; i++) { - var len = currentThickness - Math.abs(i); - switch (dir) { - case 0: //left - case 2: //right - growInDirection(x, y + i * voxelSize, z, len, len, BACK, wood, false, true); - growInDirection(x, y + i * voxelSize, z, len, len, FRONT, wood, false, false) - break; - case 1: //back - case 3: //front - growInDirection(x, y + i * voxelSize, z, len, len, LEFT, wood, false, true); - growInDirection(x, y + i * voxelSize, z, len, len, RIGHT, wood, false, false) - break; - } - } - } else { - //Otherwise place a single voxel - var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; - Voxels.setVoxel(x, y, z, voxelSize, wood.r * colorNoise, wood.g * colorNoise, wood.b * colorNoise); - } - - // determines random change in direction for branch - var r = Math.floor(Math.random() * 9); - - - if (r >= 6){ - moveDir = dir; //in same direction - } else if (r >= 4) { - moveDir = UP; //up - } - else if (dir == LEFT){ - if (r >= 2){ - moveDir = FRONT; - } - else{ - moveDir = BACK; - } - } - else if (dir == BACK){ - if (r >= 2){ - moveDir = LEFT; - } - else{ - moveDir = RIGHT; - } - } - else if (dir == RIGHT){ - if (r >= 2){ - moveDir = BACK; - } - else{ - moveDir = FRONT; - } - } - else if (dir == FRONT){ - if (r >= 2){ - moveDir = RIGHT; - } - else{ - moveDir = LEFT; - } - } - - //Move the branch by moveDir - switch (moveDir) { - case 0: //left - x = x - voxelSize; - break; - case 1: //back - z = z - voxelSize; - break; - case 2: //right - x = x + voxelSize; - break; - case 3: //front - z = z + voxelSize; - break; - case 4: //up - y = y + voxelSize; - break; - } - - step--; - } -} - -// Places a sphere of voxels -function makeSphere(x, y, z, radius, color) { - if (radius <= 0) { - return; - } - var width = radius * 2 + 1; - var distance; - - for (var i = -radius; i <= radius; i++){ - for (var j = -radius; j <= radius; j++){ - for (var k = -radius; k <= radius; k++){ - distance = Math.sqrt(i * i + j * j + k * k); - if (distance <= radius){ - var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; - Voxels.setVoxel(x + i * voxelSize, y + j * voxelSize, z + k * voxelSize, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise); - } - } - } - } -} - -function growInDirection(x, y, z, step, length, dir, color, isSideBranching, addVoxel) { - - - if (addVoxel == true) { - var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; - Voxels.setVoxel(x, y, z, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise); - } - - // If this is a main vein, it will branch outward perpendicular to its motion - if (isSideBranching == true){ - var step2; - if (step >= length - 1){ - step2 = length; - } - else{ - step2 = step + 1; - } - growInDirection(x, y, z, step, length, BACK, color, false, false); - growInDirection(x, y, z, step, length, FRONT, color, false, false); - } - - if (step < 1) return; - - // Recursively move in the direction - if (dir == LEFT) { //left - growInDirection(x - voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true); - } - else if (dir == BACK) { //back - growInDirection(x, y, z - voxelSize, step - 1, length, dir, color, isSideBranching, true); - } - else if (dir == RIGHT) { //right - growInDirection(x + voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true); - } - else if (dir == FRONT) {//front - growInDirection(x, y, z + voxelSize, step - 1, length, dir, color, isSideBranching, true); - } - -} - -// Grows the thickness of the tree -function growHorizontalSlice(x, y, z, thickness, color, side) { - // The side variable determines which directions we should grow in - // it is an optimization that prevents us from visiting voxels multiple - // times for trees with a coreWidth > 1 - - // side: - // 8 == all directions - // 0 1 2 - // 3 -1 4 - // 5 6 7 - - Voxels.setVoxel(x, y, z, voxelSize, color.r, color.g, color.b); - - //We are done if there is no thickness - if (thickness == 0) { - return; - } - - - switch (side) { - case 0: - growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false); - break; - case 1: - growInDirection(x, y, z, thickness, thickness, BACK, color, false, false); - break; - case 2: - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); - break; - case 3: - growInDirection(x, y, z, thickness, thickness, LEFT, color, false, false); - break; - case 4: - growInDirection(x, y, z, thickness, thickness, BACK, color, false, false); - break; - case 5: - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); - break; - case 6: - growInDirection(x, y, z, thickness, thickness, FRONT, color, false, false); - break; - case 7: - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); - break; - case 8: - if (thickness > 1){ - growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false); - growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false) - } else if (thickness == 1){ - Voxels.setVoxel(x - voxelSize, y, z, voxelSize, color.r, color.g, color.b); - Voxels.setVoxel(x + voxelSize, y, z, voxelSize, color.r, color.g, color.b); - Voxels.setVoxel(x, y, z - voxelSize, voxelSize, color.r, color.g, color.b); - Voxels.setVoxel(x, y, z + voxelSize, voxelSize, color.r, color.g, color.b); - } - break; - } -} - -function computeSide(x, z, coreWidth) { - // side: - // 8 == all directions - // 0 1 2 - // 3 -1 4 - // 5 6 7 - - // if the core is only a single block, we can grow out in all directions - if (coreWidth == 1){ - return 8; - } - - // Back face - if (z == 0) { - if (x == 0) { - return 0; - } else if (x == coreWidth - 1) { - return 2; - } else { - return 1; - } - } - - // Front face - if (z == (coreWidth - 1)) { - if (x == 0) { - return 5; - } else if (x == (coreWidth - 1)) { - return 7; - } else { - return 6; - } - } - - // Left face - if (x == 0) { - return 3; - } - - // Right face - if (x == (coreWidth - 1)) { - return 4; - } - - //Interior - return -1; -} - - -function growTree(x, y, z, tree) { - - // The size of the tree, from 0-1 - var treeSize = Math.random(); - - // Get tree properties by interpolating with the treeSize - var height = interpolate(tree.height, treeSize); - var baseHeight = Math.ceil(tree.middleHeight * height); - var bottomThickness = interpolate(tree.bottomThickness, treeSize); - var middleThickness = interpolate(tree.middleThickness, treeSize); - var topThickness = interpolate(tree.topThickness, treeSize); - var coreWidth = Math.ceil(interpolate(tree.coreWidth, treeSize)); - - var thickness; - var side; - - //Loop upwards through each slice of the tree - for (var i = 0; i < height; i++){ - - //Branch properties are based on current height as well as the overall tree size - var branchChance = interpolate(tree.branchChance, i / height); - var branchLength = Math.ceil(interpolate(tree.branchLength, (i / height) * treeSize)); - var branchThickness = Math.round(interpolate(tree.branchThickness, (i / height) * treeSize)); - - // Get the "thickness" of the tree by doing linear interpolation between the middle thickness - // and the top and bottom thickness. - if (i <= baseHeight && baseHeight != 0){ - thickness = (i / (baseHeight) * (middleThickness - bottomThickness) + bottomThickness); - } else { - var denom = ((height - baseHeight)) * (topThickness - middleThickness) + middleThickness; - if (denom != 0) { - thickness = (i - baseHeight) / denom; - } else { - thickness = 0; - } - } - // The core of the tree is a vertical rectangular prism through the middle of the tree - - //Loop through the "core", which helps shape the trunk - var startX = x - Math.floor(coreWidth / 2) * voxelSize; - var startZ = z - Math.floor(coreWidth / 2) * voxelSize; - for (var j = 0; j < coreWidth; j++) { - for (var k = 0; k < coreWidth; k++) { - //determine which side of the tree we are on - side = computeSide(j, k, coreWidth); - //grow a horizontal slice of the tree - growHorizontalSlice(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, Math.floor(thickness), tree.wood, side); - - // Branches - if (side != -1) { - var r = Math.random(); - if (r <= branchChance){ - var dir = Math.floor((Math.random() * 4)); - makeBranch(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, branchLength, branchLength, dir, branchThickness, tree.wood, tree.leaves); - - } - } - } - } - } - - makeSphere(x, y + height * voxelSize, z, topThickness + coreWidth + tree.leafCapSizeOffset, tree.leaves); -} - -function mousePressEvent(event) { - var mouseX = event.x; - var mouseY = event.y; - - var clickedOnSomething = false; - // Check if we clicked an overlay - var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY}); - - if (clickedOverlay == voxelTool) { - voxelToolSelected = !voxelToolSelected; - - if (voxelToolSelected == true) { - Overlays.editOverlay(voxelTool, { - color: activeUIColor - }); - } else { - Overlays.editOverlay(voxelTool, { - color: UIColor - }); - } - - clickedOnSomething = true; - } else if (scaleSelector.clicked(event.x, event.y)) { - clickedOnSomething = true; - voxelSize = scaleSelector.scale; - } - - // Return if we clicked on the UI or the voxel tool is disabled - if (clickedOnSomething || !voxelToolSelected) { - return; - } - - // Compute the picking ray for the click - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); - var resultVoxel = calculateVoxelFromIntersection(intersection, "add"); - - // Currently not in use, could randomly select a tree - var treeIndex = Math.floor(Math.random() * treeTypes.length); - - // Grow the first tree type - growTree(resultVoxel.x, resultVoxel.y, resultVoxel.z, treeTypes[0]); - -} - - -function scriptEnding() { - Overlays.deleteOverlay(linePreviewTop); - Overlays.deleteOverlay(linePreviewBottom); - Overlays.deleteOverlay(linePreviewLeft); - Overlays.deleteOverlay(linePreviewRight); - scaleSelector.cleanup(); - Overlays.deleteOverlay(voxelTool); -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); - -Script.scriptEnding.connect(scriptEnding); - -Voxels.setPacketsPerSecond(10000); diff --git a/examples/headMove.js b/examples/headMove.js index 943664b70f..3152976383 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -36,7 +36,7 @@ var warpSphere = Overlays.addOverlay("sphere", { var WARP_LINE_HEIGHT = 5; var warpLine = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z:0 }, + start: { x: 0, y: 0, z:0 }, end: { x: 0, y: 0, z: 0 }, color: { red: 0, green: 255, blue: 255}, alpha: 1, @@ -120,7 +120,7 @@ function updateWarp() { visible: willMove, }); Overlays.editOverlay(warpLine, { - position: Vec3.sum(warpPosition, { x: 0, y: -WARP_LINE_HEIGHT / 2.0, z: 0 }), + start: Vec3.sum(warpPosition, { x: 0, y: -WARP_LINE_HEIGHT / 2.0, z: 0 }), end: Vec3.sum(warpPosition, { x: 0, y: WARP_LINE_HEIGHT / 2.0, z: 0 }), visible: willMove, }); diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 4e22637ad6..6b576e557d 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -31,8 +31,13 @@ } function createEmitTextPropertyUpdateFunction(propertyName) { return function() { + var properties = {}; + properties[propertyName] = this.value; EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":"' + this.value + '"}}' + JSON.stringify({ + type: "update", + properties: properties, + }) ); }; } @@ -84,6 +89,8 @@ var elDimensionsY = document.getElementById("property-dim-y"); var elDimensionsZ = document.getElementById("property-dim-z"); var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); + var elRescaleDimensionsPct = document.getElementById("dimension-rescale-pct"); + var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button"); var elRegistrationX = document.getElementById("property-reg-x"); var elRegistrationY = document.getElementById("property-reg-y"); @@ -107,7 +114,7 @@ var elGravityY = document.getElementById("property-grav-y"); var elGravityZ = document.getElementById("property-grav-z"); - var elMass = document.getElementById("property-mass"); + var elDensity = document.getElementById("property-density"); var elIgnoreForCollisions = document.getElementById("property-ignore-for-collisions"); var elCollisionsWillMove = document.getElementById("property-collisions-will-move"); var elLifetime = document.getElementById("property-lifetime"); @@ -144,6 +151,9 @@ var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); var elModelAnimationFrame = document.getElementById("property-model-animation-frame"); + var elModelAnimationSettings = document.getElementById("property-model-animation-settings"); + var elModelTextures = document.getElementById("property-model-textures"); + var elModelOriginalTextures = document.getElementById("property-model-original-textures"); var elTextSections = document.querySelectorAll(".text-section"); var elTextText = document.getElementById("property-text-text"); @@ -209,7 +219,7 @@ elGravityY.value = properties.gravity.y.toFixed(2); elGravityZ.value = properties.gravity.z.toFixed(2); - elMass.value = properties.mass.toFixed(2); + elDensity.value = properties.density.toFixed(2); elIgnoreForCollisions.checked = properties.ignoreForCollisions; elCollisionsWillMove.checked = properties.collisionsWillMove; elLifetime.value = properties.lifetime; @@ -242,6 +252,10 @@ elModelAnimationURL.value = properties.animationURL; elModelAnimationPlaying.checked = properties.animationIsPlaying; elModelAnimationFPS.value = properties.animationFPS; + elModelAnimationFrame.value = properties.animationFrameIndex; + elModelAnimationSettings.value = properties.animationSettings; + elModelTextures.value = properties.textures; + elModelOriginalTextures.value = properties.originalTextures; } if (properties.type != "Text") { @@ -342,7 +356,7 @@ elGravityY.addEventListener('change', gravityChangeFunction); elGravityZ.addEventListener('change', gravityChangeFunction); - elMass.addEventListener('change', createEmitNumberPropertyUpdateFunction('mass')); + elDensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('density')); elIgnoreForCollisions.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ignoreForCollisions')); elCollisionsWillMove.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionsWillMove')); elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); @@ -385,6 +399,8 @@ elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying')); elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS')); elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); + elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings')); + elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); @@ -419,7 +435,13 @@ action: "resetToNaturalDimensions", })); }); - + elRescaleDimensionsButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "rescaleDimensions", + percentage: parseInt(elRescaleDimensionsPct.value), + })); + }); var resizing = false; var startX = 0; @@ -537,6 +559,12 @@
+
+ % +
+ + + @@ -588,9 +616,9 @@ - Mass + Density - + @@ -618,7 +646,7 @@ Script URL - + @@ -637,13 +665,13 @@ Model URL - + Animation URL - + @@ -664,6 +692,24 @@ + + Animation Settings + + + + + + Textures + + + + + + Original Textures + + + + diff --git a/examples/html/gridControls.html b/examples/html/gridControls.html deleted file mode 100644 index 06090da423..0000000000 --- a/examples/html/gridControls.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - -
- -
- -
- -
- - - - -
- -
- - - - -
- -
- - - - -
- -
- - - - -
- -
- - - - -
- -
- - -
- -
- - - -
-
- - - -
-
- - diff --git a/examples/html/style.css b/examples/html/style.css index aa23cf97ab..7ffbacb15e 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -90,12 +90,21 @@ input[type=button] { font-size: .9em; } -input { +textarea, input { padding: 2px; border: 1px solid #999; background-color: #eee; } +textarea { + width: 100%; + resize: vertical; +} + +input.url { + width: 100%; +} + table#entity-table { border-collapse: collapse; font-family: Sans-Serif; @@ -171,7 +180,7 @@ table#properties-table { } #properties-table td { - padding: 5px 0px 5px 10px; + padding: 5px; } col#col-label { diff --git a/examples/inspect.js b/examples/inspect.js index 49ebc86de1..ff0925db97 100644 --- a/examples/inspect.js +++ b/examples/inspect.js @@ -221,13 +221,11 @@ function mousePressEvent(event) { // Compute trajectories related values var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); - var voxelIntersection = Voxels.findRayIntersection(pickRay); var modelIntersection = Entities.findRayIntersection(pickRay); position = Camera.getPosition(); var avatarTarget = MyAvatar.getTargetAvatarPosition(); - var voxelTarget = voxelIntersection.intersection; var distance = -1; @@ -246,13 +244,6 @@ function mousePressEvent(event) { string = "Inspecting avatar"; } - if ((distance == -1 || Vec3.length(Vec3.subtract(voxelTarget, position)) < distance) && - (voxelTarget.x != 0 || voxelTarget.y != 0 || voxelTarget.z != 0)) { - distance = Vec3.length(Vec3.subtract(voxelTarget, position)); - center = voxelTarget; - string = "Inspecting voxel"; - } - if (distance == -1) { return; } diff --git a/examples/laserPointer.js b/examples/laserPointer.js deleted file mode 100644 index bedafe6a18..0000000000 --- a/examples/laserPointer.js +++ /dev/null @@ -1,23 +0,0 @@ -// -// laserPointer.js -// examples -// -// Created by Clément Brisset on 7/18/14. -// 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 -// - -var LEFT = 0; -var RIGHT = 1; -var LEFT_HAND_FLAG = 1; -var RIGHT_HAND_FLAG = 2; - -function update() { - var state = ((Controller.getTriggerValue(LEFT) > 0.9) ? LEFT_HAND_FLAG : 0) + - ((Controller.getTriggerValue(RIGHT) > 0.9) ? RIGHT_HAND_FLAG : 0); - MyAvatar.setHandState(state); -} - -Script.update.connect(update); \ No newline at end of file diff --git a/examples/libraries/ModelImporter.js b/examples/libraries/ModelImporter.js index a0c35bb663..1e52c8fdec 100644 --- a/examples/libraries/ModelImporter.js +++ b/examples/libraries/ModelImporter.js @@ -93,7 +93,7 @@ ModelImporter = function (opts) { this.mouseMoveEvent = function (event) { if (self._importing) { var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Voxels.findRayIntersection(pickRay); + var intersection = Entities.findRayIntersection(pickRay); var distance = 2;// * self._scale; diff --git a/examples/libraries/ToolTip.js b/examples/libraries/ToolTip.js index 590eba36d0..f12525af57 100644 --- a/examples/libraries/ToolTip.js +++ b/examples/libraries/ToolTip.js @@ -68,7 +68,7 @@ function Tooltip() { text += "Lifetime: " + properties.lifetime + "\n" } text += "Age: " + properties.ageAsText + "\n" - text += "Mass: " + properties.mass + "\n" + text += "Density: " + properties.density + "\n" text += "Script: " + properties.script + "\n" diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index 803a58f48e..b9170dc25d 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +Script.include("libraries/overlayUtils.js"); + var MOUSE_SENSITIVITY = 0.9; var SCROLL_SENSITIVITY = 0.05; var PAN_ZOOM_SCALE_RATIO = 0.4; @@ -41,6 +43,17 @@ var easeOutCubic = function(t) { EASE_TIME = 0.5; +function mergeObjects(obj1, obj2) { + var newObj = {}; + for (key in obj1) { + newObj[key] = obj1[key]; + } + for (key in obj2) { + newObj[key] = obj2[key]; + } + return newObj; +} + CameraManager = function() { var that = {}; @@ -93,7 +106,7 @@ CameraManager = function() { that.updateCamera(); - cameraTool.setVisible(false); + cameraTool.setVisible(true); } that.disable = function(ignoreCamera) { @@ -140,6 +153,11 @@ CameraManager = function() { that.updateCamera(); } + that.setTargetPitchYaw = function(pitch, yaw) { + that.targetPitch = pitch; + that.targetYaw = yaw; + } + that.moveFocalPoint = function(dPos) { that.setFocalPoint(Vec3.sum(that.focalPoint, dPos)); } @@ -228,6 +246,10 @@ CameraManager = function() { } that.mousePressEvent = function(event) { + if (cameraTool.mousePressEvent(event)) { + return true; + } + if (!that.enabled) return; if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) { @@ -247,7 +269,7 @@ CameraManager = function() { return true; } - return cameraTool.mousePressEvent(event); + return false; } that.mouseReleaseEvent = function(event) { @@ -271,7 +293,10 @@ CameraManager = function() { } that.updateCamera = function() { - if (!that.enabled || Camera.mode != "independent") return; + if (!that.enabled || Camera.mode != "independent") { + cameraTool.update(); + return; + } var yRot = Quat.angleAxis(that.yaw, { x: 0, y: 1, z: 0 }); var xRot = Quat.angleAxis(that.pitch, { x: 1, y: 0, z: 0 }); @@ -290,6 +315,8 @@ CameraManager = function() { } Camera.setOrientation(q); + + cameraTool.update(); } function normalizeDegrees(degrees) { @@ -301,6 +328,7 @@ CameraManager = function() { // Ease the position and orbit of the camera that.update = function(dt) { if (Camera.mode != "independent") { + that.updateCamera(); return; } @@ -363,315 +391,177 @@ CameraManager = function() { return that; } -var ZoomTool = function(opts) { - var that = {}; - - var position = opts.position || { x: 0, y: 0 }; - var height = opts.height || 200; - var color = opts.color || { red: 255, green: 0, blue: 0 }; - var arrowButtonSize = opts.buttonSize || 20; - var arrowButtonBackground = opts.arrowBackground || { red: 255, green: 255, blue: 255 }; - var zoomBackground = { red: 128, green: 0, blue: 0 }; - var zoomHeight = height - (arrowButtonSize * 2); - var zoomBarY = position.y + arrowButtonSize, - - var onIncreasePressed = opts.onIncreasePressed; - var onDecreasePressed = opts.onDecreasePressed; - var onPercentageSet = opts.onPercentageSet; - - var increaseButton = Overlays.addOverlay("text", { - x: position.x, - y: position.y, - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: arrowButtonBackground, - topMargin: 4, - leftMargin: 4, - text: "+", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - var decreaseButton = Overlays.addOverlay("text", { - x: position.x, - y: position.y + arrowButtonSize + zoomHeight, - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: arrowButtonBackground, - topMargin: 4, - leftMargin: 4, - text: "-", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - var zoomBar = Overlays.addOverlay("text", { - x: position.x + 5, - y: zoomBarY, - width: 10, - height: zoomHeight, - color: { red: 0, green: 255, blue: 0 }, - backgroundColor: zoomBackground, - topMargin: 4, - leftMargin: 4, - text: "", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - var zoomHandle = Overlays.addOverlay("text", { - x: position.x, - y: position.y + arrowButtonSize, - width: arrowButtonSize, - height: 10, - backgroundColor: { red: 0, green: 255, blue: 0 }, - topMargin: 4, - leftMargin: 4, - text: "", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - - var allOverlays = [ - increaseButton, - decreaseButton, - zoomBar, - zoomHandle, - ]; - - that.destroy = function() { - for (var i = 0; i < allOverlays.length; i++) { - Overlays.deleteOverlay(allOverlays[i]); - } - }; - - that.setVisible = function(visible) { - for (var i = 0; i < allOverlays.length; i++) { - Overlays.editOverlay(allOverlays[i], { visible: visible }); - } - } - - that.setZoomPercentage = function(pct) { - var yOffset = (zoomHeight - 10) * pct; - Overlays.editOverlay(zoomHandle, { - y: position.y + arrowButtonSize + yOffset, - }); - } - - that.mouseReleaseEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - var clicked = false; - if (clickedOverlay == increaseButton) { - if (onIncreasePressed) onIncreasePressed(); - clicked = true; - } else if (clickedOverlay == decreaseButton) { - if (onDecreasePressed) onDecreasePressed(); - clicked = true; - } else if (clickedOverlay == zoomBar) { - if (onPercentageSet) onPercentageSet((event.y - zoomBarY) / zoomHeight); - clicked = true; - } - return clicked; - } - - return that; -}; - -var ArrowTool = function(opts) { - var that = {}; - - var position = opts.position || { x: 0, y: 0 }; - var arrowButtonSize = opts.buttonSize || 20; - var color = opts.color || { red: 255, green: 0, blue: 0 }; - var arrowButtonBackground = opts.arrowBackground || { red: 255, green: 255, blue: 255 }; - var centerButtonBackground = opts.centerBackground || { red: 255, green: 255, blue: 255 }; - var onUpPressed = opts.onUpPressed; - var onDownPressed = opts.onDownPressed; - var onLeftPressed = opts.onLeftPressed; - var onRightPressed = opts.onRightPressed; - var onCenterPressed = opts.onCenterPressed; - - var upButton = Overlays.addOverlay("text", { - x: position.x + arrowButtonSize, - y: position.y, - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: arrowButtonBackground, - topMargin: 4, - leftMargin: 4, - text: "^", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - var leftButton = Overlays.addOverlay("text", { - x: position.x, - y: position.y + arrowButtonSize, - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: arrowButtonBackground, - topMargin: 4, - leftMargin: 4, - text: "<", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - var rightButton = Overlays.addOverlay("text", { - x: position.x + (arrowButtonSize * 2), - y: position.y + arrowButtonSize, - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: arrowButtonBackground, - topMargin: 4, - leftMargin: 4, - text: ">", - alpha: 1.0, - visible: true, - }); - var downButton = Overlays.addOverlay("text", { - x: position.x + arrowButtonSize, - y: position.y + (arrowButtonSize * 2), - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: arrowButtonBackground, - topMargin: 4, - leftMargin: 4, - text: "v", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - var centerButton = Overlays.addOverlay("text", { - x: position.x + arrowButtonSize, - y: position.y + arrowButtonSize, - width: arrowButtonSize, - height: arrowButtonSize, - color: color, - backgroundColor: centerButtonBackground, - topMargin: 4, - leftMargin: 4, - text: "", - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true, - }); - - var allOverlays = [ - upButton, - downButton, - leftButton, - rightButton, - centerButton, - ]; - - that.destroy = function() { - for (var i = 0; i < allOverlays.length; i++) { - Overlays.deleteOverlay(allOverlays[i]); - } - }; - - that.setVisible = function(visible) { - for (var i = 0; i < allOverlays.length; i++) { - Overlays.editOverlay(allOverlays[i], { visible: visible }); - } - } - - that.mouseReleaseEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - var clicked = false; - if (clickedOverlay == leftButton) { - if (onLeftPressed) onLeftPressed(); - clicked = true; - } else if (clickedOverlay == rightButton) { - if (onRightPressed) onRightPressed(); - clicked = true; - } else if (clickedOverlay == upButton) { - if (onUpPressed) onUpPressed(); - clicked = true; - } else if (clickedOverlay == downButton) { - if (onDownPressed) onDownPressed(); - clicked = true; - } else if (clickedOverlay == centerButton) { - if (onCenterPressed) onCenterPressed(); - clicked = true; - } - return clicked; - } - - return that; -} - - CameraTool = function(cameraManager) { var that = {}; - var toolsPosition = { x: 20, y: 280 }; - var orbitToolPosition = toolsPosition; - var panToolPosition = { x: toolsPosition.x + 80, y: toolsPosition.y }; - var zoomToolPosition = { x: toolsPosition.x + 20, y: toolsPosition.y + 80 }; + var RED = { red: 191, green: 78, blue: 38 }; + var GREEN = { red: 26, green: 193, blue: 105 }; + var BLUE = { red: 0, green: 131, blue: 204 }; - var orbitIncrement = 15; - orbitTool = ArrowTool({ - position: orbitToolPosition, - arrowBackground: { red: 192, green: 192, blue: 192 }, - centerBackground: { red: 128, green: 128, blue: 255 }, - color: { red: 0, green: 0, blue: 0 }, - onUpPressed: function() { cameraManager.addPitch(orbitIncrement); }, - onDownPressed: function() { cameraManager.addPitch(-orbitIncrement); }, - onLeftPressed: function() { cameraManager.addYaw(-orbitIncrement); }, - onRightPressed: function() { cameraManager.addYaw(orbitIncrement); }, - onCenterPressed: function() { cameraManager.focus(); }, + var BORDER_WIDTH = 1; + + var ORIENTATION_OVERLAY_SIZE = 26; + var ORIENTATION_OVERLAY_HALF_SIZE = ORIENTATION_OVERLAY_SIZE / 2; + var ORIENTATION_OVERLAY_CUBE_SIZE = 10.5, + + var ORIENTATION_OVERLAY_OFFSET = { + x: 30, + y: 30, + } + + var UI_WIDTH = 70; + var UI_HEIGHT = 70; + var UI_PADDING = 10; + + var lastKnownWidth = Window.innerWidth; + + var uiPosition = { + x: lastKnownWidth - UI_WIDTH - UI_PADDING, + y: UI_PADDING, + }; + + var backgroundBorder = Overlays.addOverlay("text", { + x: uiPosition.x - BORDER_WIDTH, + y: uiPosition.y - BORDER_WIDTH, + width: UI_WIDTH + BORDER_WIDTH * 2, + height: UI_HEIGHT + BORDER_WIDTH * 2, + alpha: 0, + text: "", + backgroundColor: { red: 101, green: 101, blue: 101 }, + backgroundAlpha: 1.0, + visible: false, }); - panTool = ArrowTool({ - position: panToolPosition, - arrowBackground: { red: 192, green: 192, blue: 192 }, - centerBackground: { red: 128, green: 128, blue: 255 }, - color: { red: 0, green: 0, blue: 0 }, - onUpPressed: function() { cameraManager.pan({ x: 0, y: 15 }); }, - onDownPressed: function() { cameraManager.pan({ x: 0, y: -15 }); }, - onLeftPressed: function() { cameraManager.pan({ x: -15, y: 0 }); }, - onRightPressed: function() { cameraManager.pan({ x: 15, y: 0 }); }, + + var background = Overlays.addOverlay("text", { + x: uiPosition.x, + y: uiPosition.y, + width: UI_WIDTH, + height: UI_HEIGHT, + alpha: 0, + text: "", + backgroundColor: { red: 51, green: 51, blue: 51 }, + backgroundAlpha: 1.0, + visible: false, }); - zoomTool = ZoomTool({ - position: zoomToolPosition, - arrowBackground: { red: 192, green: 192, blue: 192 }, - color: { red: 0, green: 0, blue: 0 }, - onIncreasePressed: function() { cameraManager.addZoom(-10); }, - onDecreasePressed: function() { cameraManager.addZoom(10); }, - onPercentageSet: function(pct) { cameraManager.setZoomPercentage(pct); } + + var defaultCubeProps = { + size: ORIENTATION_OVERLAY_CUBE_SIZE, + alpha: 1, + color: { red: 255, green: 0, blue: 0 }, + solid: true, + visible: true, + drawOnHUD: true, + }; + var defaultLineProps = { + lineWidth: 1.5, + alpha: 1, + position: { x: 0, y: 0, z: 0 }, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 255, green: 0, blue: 0 }, + visible: false, + drawOnHUD: true, + }; + + var orientationOverlay = OverlayGroup({ + position: { + x: uiPosition.x + UI_WIDTH / 2, + y: uiPosition.y + UI_HEIGHT / 2, + }, + visible: false, }); + var OOHS = ORIENTATION_OVERLAY_HALF_SIZE; + var cubeX = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, { + position: { x: -OOHS, y: OOHS, z: OOHS }, + color: RED, + })); + var cubeY = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, { + position: { x: OOHS, y: -OOHS, z: OOHS }, + color: GREEN, + })); + var cubeZ = orientationOverlay.createOverlay("cube", mergeObjects(defaultCubeProps, { + position: { x: OOHS, y: OOHS, z: -OOHS }, + color: BLUE, + })); + orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, { + start: { x: -OOHS, y: OOHS, z: OOHS }, + end: { x: OOHS, y: OOHS, z: OOHS }, + color: RED, + })); + orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, { + start: { x: OOHS, y: -OOHS, z: OOHS }, + end: { x: OOHS, y: OOHS, z: OOHS }, + color: GREEN, + })); + orientationOverlay.createOverlay("line3d", mergeObjects(defaultLineProps, { + start: { x: OOHS, y: OOHS, z: -OOHS }, + end: { x: OOHS, y: OOHS, z: OOHS }, + color: BLUE, + })); + Script.scriptEnding.connect(function() { - orbitTool.destroy(); - panTool.destroy(); - zoomTool.destroy(); + orientationOverlay.destroy(); + Overlays.deleteOverlay(background); + Overlays.deleteOverlay(backgroundBorder); }); + var flip = Quat.fromPitchYawRollDegrees(0, 180, 0); + that.update = function() { + orientationOverlay.setProperties({ + rotation: Quat.multiply(flip, Quat.inverse(Camera.orientation)), + }); + + if (Window.innerWidth != lastKnownWidth) { + lastKnownWidth = Window.innerWidth; + uiPosition = { + x: lastKnownWidth - UI_WIDTH - UI_PADDING, + y: UI_PADDING, + }; + orientationOverlay.setProperties({ + position: { + x: uiPosition.x + ORIENTATION_OVERLAY_OFFSET.x, + y: uiPosition.y + ORIENTATION_OVERLAY_OFFSET.y, + } + }); + Overlays.editOverlay(backgroundBorder, { + x: uiPosition.x - BORDER_WIDTH, + y: uiPosition.y - BORDER_WIDTH, + }); + Overlays.editOverlay(background, { + x: uiPosition.x, + y: uiPosition.y, + }); + } + } + that.mousePressEvent = function(event) { - return orbitTool.mouseReleaseEvent(event) - || panTool.mouseReleaseEvent(event) - || zoomTool.mouseReleaseEvent(event); + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + if (clickedOverlay == cubeX) { + targetPitch = 0; + targetYaw = event.isLeftButton ? 90 : -90; + cameraManager.setTargetPitchYaw(targetPitch, targetYaw); + return true; + } else if (clickedOverlay == cubeY) { + targetPitch = event.isLeftButton ? 90 : -90; + targetYaw = 0; + cameraManager.setTargetPitchYaw(targetPitch, targetYaw); + return true; + } else if (clickedOverlay == cubeZ) { + targetPitch = 0; + targetYaw = event.isLeftButton ? 0 : 180; + cameraManager.setTargetPitchYaw(targetPitch, targetYaw); + return true; + } }; that.setVisible = function(visible) { - orbitTool.setVisible(visible); - panTool.setVisible(visible); - zoomTool.setVisible(visible); + orientationOverlay.setProperties({ visible: visible }); + Overlays.editOverlay(background, { visible: visible }); + Overlays.editOverlay(backgroundBorder, { visible: visible }); }; - Script.update.connect(function() { - cameraManager.getZoomPercentage(); - zoomTool.setZoomPercentage(cameraManager.getZoomPercentage()); - }); - that.setVisible(false); return that; diff --git a/examples/libraries/entityPropertyDialogBox.js b/examples/libraries/entityPropertyDialogBox.js index a686ebb0f2..0cb76276d8 100644 --- a/examples/libraries/entityPropertyDialogBox.js +++ b/examples/libraries/entityPropertyDialogBox.js @@ -164,7 +164,7 @@ EntityPropertyDialogBox = (function () { array.push({ label: "Collisions:", type: "header" }); index++; - array.push({ label: "Mass:", value: properties.mass.toFixed(decimals) }); + array.push({ label: "Density:", value: properties.density.toFixed(decimals) }); index++; array.push({ label: "Ignore for Collisions:", type: "checkbox", value: properties.ignoreForCollisions }); index++; @@ -353,7 +353,7 @@ EntityPropertyDialogBox = (function () { properties.gravity.z = array[index++].value; index++; // skip header - properties.mass = array[index++].value; + properties.density = array[index++].value; properties.ignoreForCollisions = array[index++].value; properties.collisionsWillMove = array[index++].value; diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 8aff9c32ed..40db7b057a 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -242,6 +242,9 @@ SelectionDisplay = (function () { var ROTATION_DISPLAY_SIZE_Y_MULTIPLIER = 0.18; var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.17; + var ROTATE_ARROW_WEST_NORTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-north.png"; + var ROTATE_ARROW_WEST_SOUTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-south.png"; + var showExtendedStretchHandles = false; var spaceMode = SPACE_LOCAL; @@ -590,7 +593,7 @@ SelectionDisplay = (function () { }); var yawHandle = Overlays.addOverlay("billboard", { - url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png", + url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, color: rotateHandleColor, alpha: rotateHandleAlpha, @@ -603,7 +606,7 @@ SelectionDisplay = (function () { var pitchHandle = Overlays.addOverlay("billboard", { - url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png", + url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, color: rotateHandleColor, alpha: rotateHandleAlpha, @@ -616,7 +619,7 @@ SelectionDisplay = (function () { var rollHandle = Overlays.addOverlay("billboard", { - url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png", + url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, color: rotateHandleColor, alpha: rotateHandleAlpha, @@ -835,8 +838,8 @@ SelectionDisplay = (function () { rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: far }; - Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-south.png" }); - Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-south.png" }); + Overlays.editOverlay(pitchHandle, { url: ROTATE_ARROW_WEST_SOUTH_URL }); + Overlays.editOverlay(rollHandle, { url: ROTATE_ARROW_WEST_SOUTH_URL }); } else { @@ -867,8 +870,8 @@ SelectionDisplay = (function () { pitchCenter = { x: right, y: boundsCenter.y, z: boundsCenter.z }; rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: near}; - Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); - Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); + Overlays.editOverlay(pitchHandle, { url: ROTATE_ARROW_WEST_NORTH_URL }); + Overlays.editOverlay(rollHandle, { url: ROTATE_ARROW_WEST_NORTH_URL }); } } else { @@ -899,8 +902,8 @@ SelectionDisplay = (function () { pitchCenter = { x: left, y: boundsCenter.y, z: boundsCenter.z }; rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: far}; - Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); - Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); + Overlays.editOverlay(pitchHandle, { url: ROTATE_ARROW_WEST_NORTH_URL }); + Overlays.editOverlay(rollHandle, { url: ROTATE_ARROW_WEST_NORTH_URL }); } else { @@ -928,8 +931,8 @@ SelectionDisplay = (function () { rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: near }; pitchCenter = { x: left, y: boundsCenter.y, z: boundsCenter.z}; - Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); - Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); + Overlays.editOverlay(pitchHandle, { url: ROTATE_ARROW_WEST_NORTH_URL }); + Overlays.editOverlay(rollHandle, { url: ROTATE_ARROW_WEST_NORTH_URL }); } } diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 7d98befec8..87b7f907e2 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -1,35 +1,35 @@ Grid = function(opts) { var that = {}; - var color = { red: 100, green: 152, blue: 203 }; - var gridColor = { red: 100, green: 152, blue: 203 }; - var gridAlpha = 1.0; + var colors = [ + { red: 0, green: 255, blue: 0 }, + { red: 255, green: 255, blue: 255 }, + { red: 0, green: 0, blue: 0 }, + { red: 0, green: 0, blue: 255 }, + { red: 255, green: 0, blue: 0 }, + ]; + var colorIndex = 0; + var gridAlpha = 0.6; var origin = { x: 0, y: 0, z: 0 }; var majorGridEvery = 5; - var minorGridSpacing = 0.2; + var minorGridWidth = 0.2; var halfSize = 40; var yOffset = 0.001; var worldSize = 16384; - var minorGridWidth = 0.5; - var majorGridWidth = 1.5; - var snapToGrid = false; var gridOverlay = Overlays.addOverlay("grid", { position: { x: 0 , y: 0, z: 0 }, visible: true, - color: { red: 0, green: 0, blue: 128 }, - alpha: 1.0, + color: colors[0], + alpha: gridAlpha, rotation: Quat.fromPitchYawRollDegrees(90, 0, 0), minorGridWidth: 0.1, majorGridEvery: 2, }); - that.getMinorIncrement = function() { return minorGridSpacing; }; - that.getMajorIncrement = function() { return minorGridSpacing * majorGridEvery; }; - that.visible = false; that.enabled = false; @@ -37,13 +37,39 @@ Grid = function(opts) { return origin; } + that.getMinorIncrement = function() { return minorGridWidth; }; + that.getMajorIncrement = function() { return minorGridWidth * majorGridEvery; }; + + that.getMinorGridWidth = function() { return minorGridWidth; }; + that.setMinorGridWidth = function(value) { + minorGridWidth = value; + updateGrid(); + }; + + that.getMajorGridEvery = function() { return majorGridEvery; }; + that.setMajorGridEvery = function(value) { + majorGridEvery = value; + updateGrid(); + }; + + that.getColorIndex = function() { return colorIndex; }; + that.setColorIndex = function(value) { + colorIndex = value; + updateGrid(); + }; + that.getSnapToGrid = function() { return snapToGrid; }; + that.setSnapToGrid = function(value) { + snapToGrid = value; + that.emitUpdate(); + }; that.setEnabled = function(enabled) { that.enabled = enabled; updateGrid(); } + that.getVisible = function() { return that.visible; }; that.setVisible = function(visible, noUpdate) { that.visible = visible; updateGrid(); @@ -78,7 +104,7 @@ Grid = function(opts) { dimensions = { x: 0, y: 0, z: 0 }; } - var spacing = majorOnly ? (minorGridSpacing * majorGridEvery) : minorGridSpacing; + var spacing = majorOnly ? (minorGridWidth * majorGridEvery) : minorGridWidth; position = Vec3.subtract(position, origin); @@ -94,7 +120,7 @@ Grid = function(opts) { return delta; } - var spacing = majorOnly ? (minorGridSpacing * majorGridEvery) : minorGridSpacing; + var spacing = majorOnly ? (minorGridWidth * majorGridEvery) : minorGridWidth; var snappedDelta = { x: Math.round(delta.x / spacing) * spacing, @@ -121,12 +147,11 @@ Grid = function(opts) { if (that.onUpdate) { that.onUpdate({ origin: origin, - minorGridSpacing: minorGridSpacing, + minorGridWidth: minorGridWidth, majorGridEvery: majorGridEvery, gridSize: halfSize, visible: that.visible, snapToGrid: snapToGrid, - gridColor: gridColor, }); } }; @@ -144,16 +169,16 @@ Grid = function(opts) { that.setPosition(pos, true); } - if (data.minorGridSpacing) { - minorGridSpacing = data.minorGridSpacing; + if (data.minorGridWidth) { + minorGridWidth = data.minorGridWidth; } if (data.majorGridEvery) { majorGridEvery = data.majorGridEvery; } - if (data.gridColor) { - gridColor = data.gridColor; + if (data.colorIndex !== undefined) { + colorIndex = data.colorIndex; } if (data.gridSize) { @@ -171,10 +196,10 @@ Grid = function(opts) { Overlays.editOverlay(gridOverlay, { position: { x: origin.y, y: origin.y, z: -origin.y }, visible: that.visible && that.enabled, - minorGridWidth: minorGridSpacing, + minorGridWidth: minorGridWidth, majorGridEvery: majorGridEvery, - color: gridColor, - alpha: gridAlpha, + color: colors[colorIndex], + alpha: gridAlpha, }); that.emitUpdate(); @@ -199,46 +224,273 @@ Grid = function(opts) { GridTool = function(opts) { var that = {}; + var UI_URL = HIFI_PUBLIC_BUCKET + "images/tools/grid-toolbar.svg"; + var UI_WIDTH = 854; + var UI_HEIGHT = 37; + var horizontalGrid = opts.horizontalGrid; - var verticalGrid = opts.verticalGrid; - var listeners = []; - var url = Script.resolvePath('html/gridControls.html'); - var webView = new WebWindow('Grid', url, 200, 280); + var uiOverlays = {}; + var allOverlays = []; - horizontalGrid.addListener(function(data) { - webView.eventBridge.emitScriptEvent(JSON.stringify(data)); - selectionDisplay.updateHandles(); - }); + function addUIOverlay(key, overlay, x, y, width, height) { + uiOverlays[key] = { + overlay: overlay, + x: x, + y: y, + width: width, + height: height, + }; + allOverlays.push(overlay); + } - webView.eventBridge.webEventReceived.connect(function(data) { - data = JSON.parse(data); - if (data.type == "init") { - horizontalGrid.emitUpdate(); - } else if (data.type == "update") { - horizontalGrid.update(data); - for (var i = 0; i < listeners.length; i++) { - listeners[i](data); - } - } else if (data.type == "action") { - var action = data.action; - if (action == "moveToAvatar") { - grid.setPosition(MyAvatar.position); - } else if (action == "moveToSelection") { - var newPosition = selectionManager.worldPosition; - newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 }); - grid.setPosition(newPosition); - } + var lastKnownWindowWidth = null; + function repositionUI() { + if (lastKnownWindowWidth == Window.innerWidth) { + return; } - }); - that.addListener = function(callback) { - listeners.push(callback); + lastKnownWindowWidth = Window.innerWidth; + var x = Window.innerWidth / 2 - UI_WIDTH / 2; + var y = 10; + + for (var key in uiOverlays) { + info = uiOverlays[key]; + Overlays.editOverlay(info.overlay, { + x: x + info.x, + y: y + info.y, + }); + } + } + + // "Spritesheet" is laid out horizontally in this order + var UI_SPRITE_LIST = [ + { name: "gridText", width: 54 }, + { name: "visibleCheckbox", width: 60 }, + { name: "snapToGridCheckbox", width: 105 }, + + { name: "color0", width: 27 }, + { name: "color1", width: 27 }, + { name: "color2", width: 27 }, + { name: "color3", width: 27 }, + { name: "color4", width: 27 }, + + { name: "minorGridIcon", width: 34 }, + { name: "minorGridDecrease", width: 25 }, + { name: "minorGridInput", width: 26 }, + { name: "minorGridIncrease", width: 25 }, + + { name: "majorGridIcon", width: 40 }, + { name: "majorGridDecrease", width: 25 }, + { name: "majorGridInput", width: 26 }, + { name: "majorGridIncrease", width: 25 }, + + { name: "yPositionLabel", width: 160 }, + { name: "moveToLabel", width: 54 }, + { name: "moveToAvatar", width: 26 }, + { name: "moveToSelection", width: 34 }, + ]; + + // Add all overlays from spritesheet + var baseOverlay = null; + var x = 0; + for (var i = 0; i < UI_SPRITE_LIST.length; i++) { + var info = UI_SPRITE_LIST[i]; + + var props = { + imageURL: UI_URL, + subImage: { x: x, y: 0, width: info.width, height: UI_HEIGHT }, + width: info.width, + height: UI_HEIGHT, + alpha: 1.0, + visible: false, + }; + + var overlay; + if (baseOverlay == null) { + overlay = Overlays.addOverlay("image", { + imageURL: UI_URL, + }); + baseOverlay = overlay; + } else { + overlay = Overlays.cloneOverlay(baseOverlay); + } + + Overlays.editOverlay(overlay, props); + + addUIOverlay(info.name, overlay, x, 0, info.width, UI_HEIGHT); + + x += info.width; + } + + // Add Text overlays + var textProperties = { + color: { red: 255, green: 255, blue: 255 }, + topMargin: 6, + leftMargin: 4, + alpha: 1, + backgroundAlpha: 0, + text: "", + font: { size: 12 }, + visible: false, + }; + var minorGridWidthText = Overlays.addOverlay("text", textProperties); + var majorGridEveryText = Overlays.addOverlay("text", textProperties); + var yPositionText = Overlays.addOverlay("text", textProperties); + + addUIOverlay('minorGridWidthText', minorGridWidthText, 414, 8, 24, 24); + addUIOverlay('majorGridEveryText', majorGridEveryText, 530, 8, 24, 24); + addUIOverlay('yPositionText', yPositionText, 660, 8, 24, 24); + + var NUM_COLORS = 5; + function updateColorIndex(index) { + if (index < 0 || index >= NUM_COLORS) { + return; + } + + for (var i = 0 ; i < NUM_COLORS; i++) { + var info = uiOverlays['color' + i]; + Overlays.editOverlay(info.overlay, { + subImage: { + x: info.x, + y: i == index ? UI_HEIGHT : 0, + width: info.width, + height: info.height, + } + }); + } + } + + function updateGridVisible(value) { + var info = uiOverlays.visibleCheckbox; + Overlays.editOverlay(info.overlay, { + subImage: { + x: info.x, + y: value ? UI_HEIGHT : 0, + width: info.width, + height: info.height, + } + }); + } + + function updateSnapToGrid(value) { + var info = uiOverlays.snapToGridCheckbox; + Overlays.editOverlay(info.overlay, { + subImage: { + x: info.x, + y: value ? UI_HEIGHT : 0, + width: info.width, + height: info.height, + } + }); + } + + function updateMinorGridWidth(value) { + Overlays.editOverlay(minorGridWidthText, { + text: value.toFixed(1), + }); + } + + function updateMajorGridEvery(value) { + Overlays.editOverlay(majorGridEveryText, { + text: value, + }); + } + + function updateYPosition(value) { + Overlays.editOverlay(yPositionText, { + text: value.toFixed(2), + }); + } + + function updateOverlays() { + updateGridVisible(horizontalGrid.getVisible()); + updateSnapToGrid(horizontalGrid.getSnapToGrid()); + updateColorIndex(horizontalGrid.getColorIndex()); + + updateMinorGridWidth(horizontalGrid.getMinorGridWidth()); + updateMajorGridEvery(horizontalGrid.getMajorGridEvery()); + + updateYPosition(horizontalGrid.getOrigin().y); } that.setVisible = function(visible) { - webView.setVisible(visible); + for (var i = 0; i < allOverlays.length; i++) { + Overlays.editOverlay(allOverlays[i], { visible: visible }); + } } + that.mousePressEvent = function(event) { + var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + + if (allOverlays.indexOf(overlay) >= 0) { + if (overlay == uiOverlays.color0.overlay) { + horizontalGrid.setColorIndex(0); + } else if (overlay == uiOverlays.color1.overlay) { + horizontalGrid.setColorIndex(1); + } else if (overlay == uiOverlays.color2.overlay) { + horizontalGrid.setColorIndex(2); + } else if (overlay == uiOverlays.color3.overlay) { + horizontalGrid.setColorIndex(3); + } else if (overlay == uiOverlays.color4.overlay) { + horizontalGrid.setColorIndex(4); + } else if (overlay == uiOverlays.visibleCheckbox.overlay) { + horizontalGrid.setVisible(!horizontalGrid.getVisible()); + } else if (overlay == uiOverlays.snapToGridCheckbox.overlay) { + horizontalGrid.setSnapToGrid(!horizontalGrid.getSnapToGrid()); + } else if (overlay == uiOverlays.moveToAvatar.overlay) { + var position = MyAvatar.getJointPosition("LeftFoot"); + if (position.x == 0 && position.y == 0 && position.z == 0) { + position = MyAvatar.position; + } + horizontalGrid.setPosition(position); + } else if (overlay == uiOverlays.moveToSelection.overlay) { + var newPosition = selectionManager.worldPosition; + newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 }); + horizontalGrid.setPosition(newPosition); + } else if (overlay == uiOverlays.minorGridDecrease.overlay) { + var newValue = Math.max(0.1, horizontalGrid.getMinorGridWidth() - 0.1); + horizontalGrid.setMinorGridWidth(newValue); + } else if (overlay == uiOverlays.minorGridIncrease.overlay) { + horizontalGrid.setMinorGridWidth(horizontalGrid.getMinorGridWidth() + 0.1); + } else if (overlay == uiOverlays.majorGridDecrease.overlay) { + var newValue = Math.max(2, horizontalGrid.getMajorGridEvery() - 1); + horizontalGrid.setMajorGridEvery(newValue); + } else if (overlay == uiOverlays.majorGridIncrease.overlay) { + horizontalGrid.setMajorGridEvery(horizontalGrid.getMajorGridEvery() + 1); + } else if (overlay == uiOverlays.yPositionLabel.overlay) { + var newValue = Window.prompt("Y Position:", horizontalGrid.getOrigin().y.toFixed(4)); + if (newValue !== null) { + var y = parseFloat(newValue) + if (isNaN(y)) { + Window.alert("Invalid position"); + } else { + horizontalGrid.setPosition({ x: 0, y: y, z: 0 }); + } + } + } + + // Clicking anywhere within the toolbar will "consume" this press event + return true; + } + + return false; + }; + + Script.scriptEnding.connect(function() { + for (var i = 0; i < allOverlays.length; i++) { + Overlays.deleteOverlay(allOverlays[i]); + } + }); + Script.update.connect(repositionUI); + + horizontalGrid.addListener(function() { + selectionDisplay.updateHandles(); + updateOverlays(); + }); + + updateOverlays(); + repositionUI(); + return that; }; diff --git a/examples/libraries/modelUploader.js b/examples/libraries/modelUploader.js index d83fc8c16d..7f575a54ef 100644 --- a/examples/libraries/modelUploader.js +++ b/examples/libraries/modelUploader.js @@ -274,19 +274,11 @@ modelUploader = (function () { } } - if (view.string(0, 18) === "Kaydara FBX Binary") { - previousNodeFilename = ""; - - index = 27; - while (index < view.byteLength - 39 && !EOF) { - parseBinaryFBX(); - } - - } else { + readTextFBX(); - } + } function readModel() { diff --git a/examples/libraries/overlayUtils.js b/examples/libraries/overlayUtils.js new file mode 100644 index 0000000000..636ea40825 --- /dev/null +++ b/examples/libraries/overlayUtils.js @@ -0,0 +1,64 @@ +/** + * OverlayGroup provides a way to create composite overlays and control their + * position relative to a settable rootPosition and rootRotation. + */ +OverlayGroup = function(opts) { + var that = {}; + + var overlays = {}; + + var rootPosition = opts.position || { x: 0, y: 0, z: 0 }; + var rootRotation = opts.rotation || Quat.fromPitchYawRollRadians(0, 0, 0); + var visible = opts.visible == true; + + function updateOverlays() { + for (overlayID in overlays) { + var overlay = overlays[overlayID]; + var newPosition = Vec3.multiplyQbyV(rootRotation, overlay.position); + newPosition = Vec3.sum(rootPosition, newPosition); + Overlays.editOverlay(overlayID, { + visible: visible, + position: newPosition, + rotation: Quat.multiply(rootRotation, overlay.rotation), + }); + }; + } + + that.createOverlay = function(type, properties) { + properties.position = properties.position || { x: 0, y: 0, z: 0 }; + properties.rotation = properties.rotation || Quat.fromPitchYawRollRadians(0, 0, 0); + + var overlay = Overlays.addOverlay(type, properties); + + overlays[overlay] = { + position: properties.position, + rotation: properties.rotation, + }; + + updateOverlays(); + + return overlay; + } + + that.setProperties = function(properties) { + if (properties.position !== undefined) { + rootPosition = properties.position; + } + if (properties.rotation !== undefined) { + rootRotation = properties.rotation; + } + if (properties.visible !== undefined) { + visible = properties.visible; + } + updateOverlays(); + }; + + that.destroy = function() { + for (var overlay in overlays) { + Overlays.deleteOverlay(overlay); + } + overlays = {}; + } + + return that; +}; diff --git a/examples/libraries/unitTest.js b/examples/libraries/unitTest.js new file mode 100644 index 0000000000..530528e6a3 --- /dev/null +++ b/examples/libraries/unitTest.js @@ -0,0 +1,104 @@ +// +// Unittest.js +// examples +// +// Created by Ryan Huffman on 5/4/14 +// Copyright 2014 High Fidelity, Inc. +// +// This provides very basic unit testing functionality. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +test = function(name, func) { + print("Running test: " + name); + + var unitTest = new UnitTest(name, func); + + try { + unitTest.run(); + print(" Success: " + unitTest.numAssertions + " assertions passed"); + } catch (error) { + print(" Failure: " + error.name + " " + error.message); + } +}; + +AssertionException = function(expected, actual, message) { + print("Creating exception"); + this.message = message + "\n: " + actual + " != " + expected; + this.name = 'AssertionException'; +}; + +UnthrownException = function(message) { + print("Creating exception"); + this.message = message + "\n"; + this.name = 'UnthrownException'; +}; + +UnitTest = function(name, func) { + this.numAssertions = 0; + this.func = func; +}; + +UnitTest.prototype.run = function() { + this.func(); +}; + +UnitTest.prototype.assertNotEquals = function(expected, actual, message) { + this.numAssertions++; + if (expected == actual) { + throw new AssertionException(expected, actual, message); + } +}; + +UnitTest.prototype.assertEquals = function(expected, actual, message) { + this.numAssertions++; + if (expected != actual) { + throw new AssertionException(expected, actual, message); + } +}; + +UnitTest.prototype.assertContains = function (expected, actual, message) { + this.numAssertions++; + if (actual.indexOf(expected) == -1) { + throw new AssertionException(expected, actual, message); + } +}; + +UnitTest.prototype.assertHasProperty = function(property, actual, message) { + this.numAssertions++; + if (actual[property] === undefined) { + throw new AssertionException(property, actual, message); + } +}; + +UnitTest.prototype.assertNull = function(value, message) { + this.numAssertions++; + if (value !== null) { + throw new AssertionException(value, null, message); + } +} + +UnitTest.prototype.arrayEqual = function(array1, array2, message) { + this.numAssertions++; + if (array1.length !== array2.length) { + throw new AssertionException(array1.length , array2.length , message); + } + for (var i = 0; i < array1.length; ++i) { + if (array1[i] !== array2[i]) { + throw new AssertionException(array1[i], array2[i], i + " " + message); + } + } +} + +UnitTest.prototype.raises = function(func, message) { + this.numAssertions++; + try { + func(); + } catch (error) { + return; + } + + throw new UnthrownException(message); +} \ No newline at end of file diff --git a/examples/libraries/walkApi.js b/examples/libraries/walkApi.js index d2622d5833..f800682af5 100644 --- a/examples/libraries/walkApi.js +++ b/examples/libraries/walkApi.js @@ -181,7 +181,9 @@ spatialInformation = (function() { // use the blocking version of findRayIntersection to avoid errors var pickRay = {origin: MyAvatar.position, direction: {x:0, y:-1, z:0}}; - return Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;; + + // TODO: change this to use entities? + return false; // Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;; } } diff --git a/examples/lobby.js b/examples/lobby.js index b03be7c29b..15a8aca328 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -138,8 +138,10 @@ function drawLobby() { // add an attachment on this avatar so other people see them in the lobby MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15); - // start the drone sound - currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); + if (droneSound.downloaded) { + // start the drone sound + currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); + } // start one of our muzak sounds playRandomMuzak(); @@ -353,7 +355,7 @@ function update(deltaTime) { Overlays.editOverlay(descriptionText, { position: textOverlayPosition() }); // if the reticle is up then we may need to play the next muzak - if (!Audio.isInjectorPlaying(currentMuzakInjector)) { + if (currentMuzakInjector && !Audio.isInjectorPlaying(currentMuzakInjector)) { playNextMuzak(); } } diff --git a/examples/localVoxelsExample.js b/examples/localVoxelsExample.js deleted file mode 100644 index d64138b214..0000000000 --- a/examples/localVoxelsExample.js +++ /dev/null @@ -1,63 +0,0 @@ -// -// localVoxelsExample.js -// examples -// -// 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 -// - -var TREE_SCALE = 16384; -var tree = LocalVoxels("tree"); -tree.setVoxel(0, 0, 0, - 0.5 * TREE_SCALE, - 255, 0, 0); -tree.setVoxel(0.5 * TREE_SCALE, - 0.5 * TREE_SCALE, - 0.5 * TREE_SCALE, - 0.5 * TREE_SCALE, - 0, 255, 0); - -var copy = LocalVoxels("copy"); -tree.pasteFrom(0, 0, 0, TREE_SCALE, "copy"); -tree.pasteFrom(0, 0, 0, TREE_SCALE, "clipboard"); - -var overlay1 = Overlays.addOverlay("localvoxels", { - position: {x: 1, y: 1, z: 1}, - size: 1, - name: "tree" - }); -var overlay2 = Overlays.addOverlay("localvoxels", { - position: {x: 1, y: 2, z: 1}, - size: 1, - name: "tree" - }); -var overlay3 = Overlays.addOverlay("localvoxels", { - position: {x: 1, y: 3, z: 1}, - size: 1, - name: "tree" - }); -var overlay4 = Overlays.addOverlay("localvoxels", { - position: {x: 1, y: 4, z: 1}, - size: 1, - name: "copy" - }); - -var clipboard = Overlays.addOverlay("localvoxels", { - position: {x: 1, y: 5, z: 1}, - size: 1, - name: "clipboard" - }); - - - -// When our script shuts down, we should clean up all of our overlays -function scriptEnding() { - Overlays.deleteOverlay(overlay1); - Overlays.deleteOverlay(overlay2); - Overlays.deleteOverlay(overlay3); - Overlays.deleteOverlay(overlay4); - Overlays.deleteOverlay(clipboard); -} -Script.scriptEnding.connect(scriptEnding); \ No newline at end of file diff --git a/examples/locationsMenu.js b/examples/locationsMenu.js deleted file mode 100644 index 30fa377a6f..0000000000 --- a/examples/locationsMenu.js +++ /dev/null @@ -1,304 +0,0 @@ -// -// locationsMenu.js -// examples -// -// Created by Ryan Huffman on 5/28/14 -// 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 -// - -Script.include("libraries/globals.js"); - -var scriptUrl = "https://script.google.com/macros/s/AKfycbwIo4lmF-qUwX1Z-9eA_P-g2gse9oFhNcjVyyksGukyDDEFXgU/exec?action=listOwners&domain=alpha.highfidelity.io"; - -var LocationMenu = function(opts) { - var self = this; - - var pageSize = opts.pageSize || 10; - var menuWidth = opts.menuWidth || 150; - var menuHeight = opts.menuItemHeight || 24; - - var inactiveColor = { red: 51, green: 102, blue: 102 }; - var activeColor = { red: 18, green: 66, blue: 66 }; - var prevNextColor = { red: 192, green: 192, blue: 192 }; - var disabledColor = { red: 64, green: 64, blue: 64}; - var position = { x: 0, y: 0 }; - - var locationIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/location.svg"; - var toolHeight = 50; - var toolWidth = 50; - var visible = false; - var menuItemOffset = { - x: 55, - y: 0, - }; - var menuItemPadding = 5; - var margin = 7; - var fullMenuHeight = (2 * menuItemOffset.y) + (menuHeight * (pageSize + 1)); - var menuOffset = -fullMenuHeight + toolHeight; - - var windowDimensions = Controller.getViewportDimensions(); - - this.locations = []; - this.numPages = 1; - this.page = 0; - - this.menuToggleButton = Overlays.addOverlay("image", { - x: position.x, - y: position.y, - width: toolWidth, height: toolHeight, - subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, - imageURL: locationIconUrl, - alpha: 0.9 - }); - - this.background = Overlays.addOverlay("text", { - x: 0, - y: 0, - width: menuWidth + 10, - height: (menuHeight * (pageSize + 1)) + 10, - backgroundColor: { red: 0, green: 0, blue: 0}, - topMargin: 4, - leftMargin: 4, - text: "", - visible: visible, - }); - - this.menuItems = []; - for (var i = 0; i < pageSize; i++) { - var menuItem = Overlays.addOverlay("text", { - x: 0, - y: 0, - width: menuWidth, - height: menuHeight, - backgroundColor: inactiveColor, - topMargin: margin, - leftMargin: margin, - text: (i == 0) ? "Loading..." : "", - visible: visible, - }); - this.menuItems.push({ overlay: menuItem, location: null }); - } - - this.previousButton = Overlays.addOverlay("text", { - x: 0, - y: 0, - width: menuWidth / 2, - height: menuHeight, - backgroundColor: disabledColor, - topMargin: margin, - leftMargin: margin, - text: "Previous", - visible: visible, - }); - - this.nextButton = Overlays.addOverlay("text", { - x: 0, - y: 0, - width: menuWidth / 2, - height: menuHeight, - backgroundColor: disabledColor, - topMargin: margin, - leftMargin: margin, - text: "Next", - visible: visible, - }); - - this.reposition = function(force) { - var newWindowDimensions = Controller.getViewportDimensions(); - if (force || newWindowDimensions.y != windowDimensions.y) { - windowDimensions = newWindowDimensions; - - position.x = 8; - position.y = Math.floor(windowDimensions.y / 2) + 25 + 50 + 8; - - Overlays.editOverlay(self.menuToggleButton, { - x: position.x, - y: position.y, - }); - Overlays.editOverlay(self.background, { - x: position.x + menuItemOffset.x, - y: position.y + menuItemOffset.y - 2 * menuItemPadding + menuOffset, - }); - for (var i = 0; i < pageSize; i++) { - Overlays.editOverlay(self.menuItems[i].overlay, { - x: position.x + menuItemOffset.x + menuItemPadding, - y: position.y + menuItemOffset.y - menuItemPadding + (i * menuHeight) + menuOffset, - }); - } - Overlays.editOverlay(self.previousButton, { - x: position.x + menuItemOffset.x + menuItemPadding, - y: position.y + menuItemOffset.y - menuItemPadding + (pageSize * menuHeight) + menuOffset, - }); - Overlays.editOverlay(self.nextButton, { - x: position.x + menuItemOffset.x + menuItemPadding + (menuWidth / 2), - y: position.y + menuItemOffset.y - menuItemPadding + (pageSize * menuHeight) + menuOffset, - }); - } - } - - this.updateLocations = function(locations) { - this.locations = locations; - this.numPages = Math.ceil(locations.length / pageSize); - this.goToPage(0); - } - - this.setError = function() { - Overlays.editOverlay(this.menuItems[0].overlay, { text: "Error loading data" }); - } - - this.toggleMenu = function() { - visible = !visible; - for (var i = 0; i < this.menuItems.length; i++) { - Overlays.editOverlay(this.menuItems[i].overlay, { visible: visible}); - } - Overlays.editOverlay(this.previousButton, { visible: visible}); - Overlays.editOverlay(this.nextButton, { visible: visible}); - Overlays.editOverlay(this.background, { visible: visible}); - if (visible) { - Overlays.editOverlay(this.menuToggleButton, { subImage: { x: 0, y: 0, width: toolWidth, height: toolHeight } }), - } else { - Overlays.editOverlay(this.menuToggleButton, { subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight } }), - } - } - - this.goToPage = function(pageNumber) { - if (pageNumber < 0 || pageNumber >= this.numPages) { - return; - } - - this.page = pageNumber; - var start = pageNumber * pageSize; - for (var i = 0; i < pageSize; i++) { - var update = {}; - var location = null; - if (start + i < this.locations.length) { - location = this.locations[start + i]; - update.text = (start + i + 1) + ". " + location.username; - update.backgroundColor = inactiveColor; - } else { - update.text = ""; - update.backgroundColor = disabledColor; - } - Overlays.editOverlay(this.menuItems[i].overlay, update); - this.menuItems[i].location = location; - } - - this.previousEnabled = pageNumber > 0; - this.nextEnabled = pageNumber < (this.numPages - 1); - - Overlays.editOverlay(this.previousButton, { backgroundColor: this.previousEnabled ? prevNextColor : disabledColor}); - Overlays.editOverlay(this.nextButton, { backgroundColor: this.nextEnabled ? prevNextColor : disabledColor }); - } - - this.mousePressEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if (clickedOverlay == self.menuToggleButton) { - self.toggleMenu(); - } else if (clickedOverlay == self.previousButton) { - if (self.previousEnabled) { - Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor }); - } - } else if (clickedOverlay == self.nextButton) { - if (self.nextEnabled) { - Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor }); - } - } else { - for (var i = 0; i < self.menuItems.length; i++) { - if (clickedOverlay == self.menuItems[i].overlay) { - if (self.menuItems[i].location != null) { - Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor }); - } - break; - } - } - } - } - - this.mouseReleaseEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if (clickedOverlay == self.previousButton) { - if (self.previousEnabled) { - Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor }); - self.goToPage(self.page - 1); - } - } else if (clickedOverlay == self.nextButton) { - if (self.nextEnabled) { - Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor }); - self.goToPage(self.page + 1); - } - } else { - for (var i = 0; i < self.menuItems.length; i++) { - if (clickedOverlay == self.menuItems[i].overlay) { - if (self.menuItems[i].location != null) { - Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor }); - var location = self.menuItems[i].location; - Window.location = "hifi://" + location.domain + "/" - + location.x + "," + location.y + "," + location.z; - } - break; - } - } - } - } - - this.cleanup = function() { - for (var i = 0; i < self.menuItems.length; i++) { - Overlays.deleteOverlay(self.menuItems[i].overlay); - } - Overlays.deleteOverlay(self.menuToggleButton); - Overlays.deleteOverlay(self.previousButton); - Overlays.deleteOverlay(self.nextButton); - Overlays.deleteOverlay(self.background); - } - - Controller.mousePressEvent.connect(this.mousePressEvent); - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); - Script.update.connect(this.reposition); - Script.scriptEnding.connect(this.cleanup); - - this.reposition(true); -}; - -var locationMenu = new LocationMenu({ pageSize: 8 }); - -print("Loading strip data from " + scriptUrl); - -var req = new XMLHttpRequest(); -req.responseType = 'json'; - -req.onreadystatechange = function() { - if (req.readyState == req.DONE) { - if (req.status == 200 && req.response != null) { - for (var domain in req.response) { - var locations = req.response[domain]; - var users = []; - for (var i = 0; i < locations.length; i++) { - var loc = locations[i]; - var x1 = loc[1], - x2 = loc[2], - y1 = loc[3], - y2 = loc[4]; - users.push({ - domain: domain, - username: loc[0], - x: x1, - y: 300, - z: y1, - }); - } - locationMenu.updateLocations(users); - } - } else { - print("Error loading data: " + req.status + " " + req.statusText + ", " + req.errorCode + ": " + req.responseText); - locationMenu.setError(); - } - } -} - -req.open("GET", scriptUrl); -req.send(); diff --git a/examples/movingVoxel.js b/examples/movingVoxel.js deleted file mode 100644 index c55957cd04..0000000000 --- a/examples/movingVoxel.js +++ /dev/null @@ -1,52 +0,0 @@ -// -// movingVoxel.js -// examples -// -// Copyright 2014 High Fidelity, Inc. -// -// This sample script creates a voxel moving back and forth in a line -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var position = { x: 0, y: 0, z: 0 }; -var oldPosition = { x: 0, y: 0, z:0 }; -var size = 0.25; -var direction = 1.0; -var range = 2.0; -var color = { r: 100, g: 50, b: 150 }; -var colorEdge = { r:255, g:250, b:175 }; -var frame = 0; -var thisColor = color; - -function moveVoxel(deltaTime) { - frame++; - if (frame % 3 == 0) { - // Get a new position - position.x += direction * size; - if (position.x < 0) { - direction *= -1.0; - position.x = 0; - thisColor = colorEdge; - } - if (position.x > range) { - direction *= -1.0; - position.x = range; - thisColor = colorEdge; - } - // Create a new voxel - Voxels.setVoxel(position.x, position.y, position.z, size, thisColor.r, thisColor.g, thisColor.b); - // delete old voxel - Voxels.eraseVoxel(oldPosition.x, oldPosition.y, oldPosition.z, size); - // Copy old location to new - oldPosition.x = position.x; - oldPosition.y = position.y; - oldPosition.z = position.z; - thisColor = color; - } -} - -Voxels.setPacketsPerSecond(300); -// Connect a call back that happens every frame -Script.update.connect(moveVoxel); \ No newline at end of file diff --git a/examples/myBalance.js b/examples/myBalance.js deleted file mode 100644 index 43f1f40eae..0000000000 --- a/examples/myBalance.js +++ /dev/null @@ -1,121 +0,0 @@ -// -// myBalance.js -// examples -// -// Created by Stojce Slavkovski on June 5, 2014 -// Copyright 2014 High Fidelity, Inc. -// -// Show wallet ₵ balance -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Script.include("libraries/globals.js"); - -var Controller = Controller || {}; -var Overlays = Overlays || {}; -var Script = Script || {}; -var Account = Account || {}; - -(function () { - "use strict"; - var iconUrl = HIFI_PUBLIC_BUCKET + 'images/tools/', - overlayWidth = 150, - overlayHeight = 50, - overlayTopOffset = 15, - overlayRightOffset = 140, - textRightOffset = 105, - maxIntegers = 5, - downColor = { - red: 0, - green: 0, - blue: 255 - }, - upColor = { - red: 0, - green: 255, - blue: 0 - }, - normalColor = { - red: 204, - green: 204, - blue: 204 - }, - balance = -1, - walletBox = Overlays.addOverlay("image", { - x: 0, - y: overlayTopOffset, - width: 122, - height: 32, - imageURL: iconUrl + "wallet.svg", - alpha: 1 - }), - textOverlay = Overlays.addOverlay("text", { - x: 0, - y: overlayTopOffset, - topMargin: 10, - font: { - size: 16 - }, - color: normalColor - }); - - function scriptEnding() { - Overlays.deleteOverlay(walletBox); - Overlays.deleteOverlay(textOverlay); - } - - function update(deltaTime) { - var xPos = Controller.getViewportDimensions().x; - Overlays.editOverlay(walletBox, { - x: xPos - overlayRightOffset, - visible: Account.isLoggedIn() - }); - - Overlays.editOverlay(textOverlay, { - x: xPos - textRightOffset, - visible: Account.isLoggedIn() - }); - } - - function formatedBalance() { - var integers = balance.toFixed(0).length, - decimals = Math.abs(maxIntegers - integers) + 2; - - var x = balance.toFixed(decimals).split('.'), - x1 = x[0], - x2 = x.length > 1 ? '.' + x[1] : ''; - var rgx = /(\d+)(\d{3})/; - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + ',' + '$2'); - } - return x1 + x2; - } - - function updateBalance(newBalance) { - if (balance === newBalance) { - return; - } - - var change = newBalance - balance, - textColor = change < 0 ? downColor : upColor; - - balance = newBalance; - Overlays.editOverlay(textOverlay, { - text: formatedBalance(), - color: textColor - }); - - Script.setTimeout(function () { - Overlays.editOverlay(textOverlay, { - color: normalColor - }); - }, 1000); - } - - updateBalance(Account.getBalance()); - Account.balanceChanged.connect(updateBalance); - Script.scriptEnding.connect(scriptEnding); - Script.update.connect(update); -}()); \ No newline at end of file diff --git a/examples/notifications.js b/examples/notifications.js index 2c2c4a5c0b..5527fc35fc 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -1,25 +1,32 @@ // -// notifications.js +// notifications.js +// Version 0.801 // Created by Adrian // // Adrian McCarlie 8-10-14 // This script demonstrates on-screen overlay type notifications. // 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 -// This script demonstrates notifications created via a number of ways, such as: -// Simple key press alerts, which only depend on a key being pressed, -// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". -// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. - -// System generated alerts such as users joining and leaving and chat messages which mention this user. -// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. -// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, -// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. +// This script generates notifications created via a number of ways, such as: +// keystroke: +// +// "q" returns number of users currently online (for debug purposes) +// CTRL/s for snapshot. +// CTRL/m for mic mute and unmute. +// System generated notifications: +// Displays users online at startup. +// If Screen is resized. +// Triggers notification if @MyUserName is mentioned in chat. +// Announces existing user logging out. +// Announces new user logging in. +// If mic is muted for any reason. +// // To add a new System notification type: // // 1. Set the Event Connector at the bottom of the script. @@ -45,22 +52,23 @@ // 2. Declare a text string. // 3. Call createNotifications(text) parsing the text. // example: -// if (key.text == "a") { -// var noteString = "Turning to the Left"; -// createNotification(noteString); -// } +// if (key.text == "q") { //queries number of users online +// var numUsers = GlobalServices.onlineUsers.length; +// var welcome = "There are " + numUsers + " users online now."; +// createNotification(welcome); +// } var width = 340.0; //width of notification overlay var height = 40.0; // height of a single line notification overlay var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window -var overlayLocationX = (windowDimensions.x - (width + 60.0));// positions window 60px from the right of the interface window +var overlayLocationX = (windowDimensions.x - (width + 20.0));// positions window 20px from the right of the interface window var buttonLocationX = overlayLocationX + (width - 28.0); var locationY = 20.0; // position down from top of interface window var topMargin = 13.0; var leftMargin = 10.0; var textColor = { red: 228, green: 228, blue: 228}; // text color -var backColor = { red: 38, green: 38, blue: 38}; // background color +var backColor = { red: 2, green: 2, blue: 2}; // background color was 38,38,38 var backgroundAlpha = 0; var fontSize = 12.0; var persistTime = 10.0; // time in seconds before notification fades @@ -115,7 +123,6 @@ function createNotification(text) { color: textColor, backgroundColor: backColor, alpha: backgroundAlpha, - backgroundAlpha: backgroundAlpha, topMargin: topMargin, leftMargin: leftMargin, font: {size: fontSize}, @@ -125,8 +132,8 @@ function createNotification(text) { var buttonProperties = { x: buttonLocationX, y: bLevel, - width: 15.0, - height: 15.0, + width: 10.0, + height: 10.0, subImage: { x: 0, y: 0, width: 10, height: 10 }, imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", color: { red: 255, green: 255, blue: 255}, @@ -161,7 +168,7 @@ function fadeIn(noticeIn, buttonIn) { pauseTimer = Script.setInterval(function() { q++; qFade = q / 10.0; - Overlays.editOverlay(noticeIn, {alpha: qFade, backgroundAlpha: qFade}); + Overlays.editOverlay(noticeIn, {alpha: qFade}); Overlays.editOverlay(buttonIn, {alpha: qFade}); if (q >= 9.0) { Script.clearInterval(pauseTimer); @@ -203,41 +210,18 @@ function keyPressEvent(key) { if (key.key == 16777249) { ctrlIsPressed = true; } - if (key.text == "a") { - var noteString = "Turning to the Left"; - createNotification(noteString); - } - if (key.text == "d") { - var noteString = "Turning to the Right"; - createNotification(noteString); - } + if (key.text == "q") { //queries number of users online + var numUsers = GlobalServices.onlineUsers.length; + var welcome = "There are " + numUsers + " users online now."; + createNotification(welcome); + } + if (key.text == "s") { if (ctrlIsPressed == true){ - var noteString = "You have taken a snapshot"; + var noteString = "Snapshot taken."; createNotification(noteString); } } - if (key.text == "q") { - var noteString = "Enable Scripted Motor control is now on."; - wordWrap(noteString); - } - if (key.text == "w") { - var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; - var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; - wordWrap(noteString); - } - if (key.text == "e") { - var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." - wordWrap(noteString); - } - if (key.text == "r") { - var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; - wordWrap(noteString); - } - if (key.text == "SPACE") { - var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; - wordWrap(noteString); - } } // formats string to add newline every 43 chars @@ -275,18 +259,14 @@ function checkSize(){ // Triggers notification if a user logs on or off function onOnlineUsersChanged(users) { - var joiners = []; - var leavers = []; for (user in users) { - if (last_users.indexOf(users[user]) == -1.0) { - joiners.push(users[user]); - createNotification(users[user] + " Has joined"); + if (last_users.indexOf(users[user]) == -1.0) { + createNotification(users[user] + " has joined"); } } for (user in last_users) { if (users.indexOf(last_users[user]) == -1.0) { - leavers.push(last_users[user]); - createNotification(last_users[user] + " Has left"); + createNotification(last_users[user] + " has left"); } } last_users = users; @@ -303,8 +283,8 @@ function onIncomingMessage(user, message) { } // Triggers mic mute notification function onMuteStateChanged() { - var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; - var muteString = "Microphone is set to " + muteState; + var muteState = AudioDevice.getMuted() ? "muted" : "unmuted"; + var muteString = "Microphone is now " + muteState; createNotification(muteString); } @@ -345,7 +325,7 @@ function fadeOut(noticeOut, buttonOut, arraysOut) { pauseTimer = Script.setInterval(function() { r--; rFade = r / 10.0; - Overlays.editOverlay(noticeOut, {alpha: rFade, backgroundAlpha: rFade}); + Overlays.editOverlay(noticeOut, {alpha: rFade}); Overlays.editOverlay(buttonOut, {alpha: rFade}); if (r < 0) { dismiss(noticeOut, buttonOut, arraysOut); @@ -368,10 +348,17 @@ function dismiss(firstNoteOut, firstButOut, firstOut) { myAlpha.splice(firstOut,1); } -onMuteStateChanged(); +// This is meant to show users online at startup but currently shows 0 users. +function onConnected() { + var numUsers = GlobalServices.onlineUsers.length; + var welcome = "Welcome! There are " + numUsers + " users online now."; + createNotification(welcome); +} + AudioDevice.muteToggled.connect(onMuteStateChanged); Controller.keyPressEvent.connect(keyPressEvent); Controller.mousePressEvent.connect(mousePressEvent); +GlobalServices.connected.connect(onConnected); GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); GlobalServices.incomingMessage.connect(onIncomingMessage); Controller.keyReleaseEvent.connect(keyReleaseEvent); diff --git a/examples/playSound.js b/examples/playSound.js deleted file mode 100644 index bc21204665..0000000000 --- a/examples/playSound.js +++ /dev/null @@ -1,27 +0,0 @@ -// -// playSound.js -// examples -// -// Copyright 2014 High Fidelity, Inc. -// Plays a sample audio file at the avatar's current location -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -Script.include("libraries/globals.js"); - -// First, load a sample sound from a URL -var bird = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/bushtit_1.raw"); - -function maybePlaySound(deltaTime) { - if (Math.random() < 0.01) { - // Set the location and other info for the sound to play - Audio.playSound(bird, { - position: MyAvatar.position, - volume: 0.5 - }); - } -} - -// Connect a call back that happens every frame -Script.update.connect(maybePlaySound); \ No newline at end of file diff --git a/examples/playSoundOrbit.js b/examples/playSoundOrbit.js deleted file mode 100644 index 16ba5e52af..0000000000 --- a/examples/playSoundOrbit.js +++ /dev/null @@ -1,43 +0,0 @@ -// -// playSoundPath.js -// examples -// -// Created by Craig Hansen-Sturm on 05/27/14. -// 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 -// - -Script.include("libraries/globals.js"); - -var soundClip = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Voxels/voxel create 3.raw"); - -var currentTime = 1.570079; // pi/2 -var deltaTime = 0.05; -var distance = 1; -var debug = 0; - -function playSound() { - currentTime += deltaTime; - - var s = distance * Math.sin(currentTime); - var c = distance * Math.cos(currentTime); - - var soundOffset = { x:s, y:0, z:c }; - - if (debug) { - print("t=" + currentTime + "offset=" + soundOffset.x + "," + soundOffset.y + "," + soundOffset.z); - } - - var avatarPosition = MyAvatar.position; - var soundPosition = Vec3.sum(avatarPosition,soundOffset); - - Audio.playSound(soundClip, { - position: soundPosition - }); -} - -Script.setInterval(playSound, 250); - - diff --git a/examples/ribbon.js b/examples/ribbon.js deleted file mode 100644 index dd3d46fbfc..0000000000 --- a/examples/ribbon.js +++ /dev/null @@ -1,176 +0,0 @@ -// -// ribbon.js -// examples -// -// Created by Andrzej Kapolka on 2/24/14. -// 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 -// - -function vectorMultiply(vector, scalar) { - return [ vector[0] * scalar, vector[1] * scalar, vector[2] * scalar ]; -} - -function vectorAdd(firstVector, secondVector) { - return [ firstVector[0] + secondVector[0], firstVector[1] + secondVector[1], firstVector[2] + secondVector[2] ]; -} - -function vectorSubtract(firstVector, secondVector) { - return [ firstVector[0] - secondVector[0], firstVector[1] - secondVector[1], firstVector[2] - secondVector[2] ]; -} - -function vectorCross(firstVector, secondVector) { - return [ firstVector[1] * secondVector[2] - firstVector[2] * secondVector[1], - firstVector[2] * secondVector[0] - firstVector[0] * secondVector[2], - firstVector[0] * secondVector[1] - firstVector[1] * secondVector[0] ]; -} - -function vectorLength(vector) { - return Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]); -} - -function vectorNormalize(vector) { - return vectorMultiply(vector, 1.0 / vectorLength(vector)); -} - -function vectorClone(vector) { - return [ vector[0], vector[1], vector[2] ]; -} - -function mix(first, second, amount) { - return first + (second - first) * amount; -} - -function vectorMix(firstVector, secondVector, amount) { - return vectorAdd(firstVector, vectorMultiply(vectorSubtract(secondVector, firstVector), amount)); -} - -function randomVector(minVector, maxVector) { - return [ mix(minVector[0], maxVector[0], Math.random()), mix(minVector[1], maxVector[1], Math.random()), - mix(minVector[2], maxVector[2], Math.random()) ]; -} - -function applyToLine(start, end, granularity, fn) { - // determine the number of steps from the maximum length - var steps = Math.max( - Math.abs(Math.floor(start[0] / granularity) - Math.floor(end[0] / granularity)), - Math.abs(Math.floor(start[1] / granularity) - Math.floor(end[1] / granularity)), - Math.abs(Math.floor(start[2] / granularity) - Math.floor(end[2] / granularity))); - var position = vectorClone(start); - var increment = vectorMultiply(vectorSubtract(end, start), 1.0 / steps); - for (var i = 0; i <= steps; i++) { - fn(granularity * Math.floor(position[0] / granularity), - granularity * Math.floor(position[1] / granularity), - granularity * Math.floor(position[2] / granularity), - granularity); - position = vectorAdd(position, increment); - } -} - -function drawLine(start, end, color, granularity) { - applyToLine(start, end, granularity, function(x, y, z, scale) { - Voxels.setVoxel(x, y, z, scale, color[0], color[1], color[2]); - }); -} - -function eraseLine(start, end, granularity) { - applyToLine(start, end, granularity, function(x, y, z, scale) { - Voxels.eraseVoxel(x, y, z, scale); - }); -} - -function getHueColor(hue) { - // see http://en.wikipedia.org/wiki/HSL_and_HSV - var hPrime = hue / 60.0; - var x = Math.floor(255.0 * (1.0 - Math.abs(hPrime % 2.0 - 1.0))); - if (hPrime < 1) { - return [255, x, 0]; - - } else if (hPrime < 2) { - return [x, 255, 0]; - - } else if (hPrime < 3) { - return [0, 255, x]; - - } else if (hPrime < 4) { - return [0, x, 255]; - - } else if (hPrime < 5) { - return [x, 0, 255]; - - } else { // hPrime < 6 - return [255, 0, x]; - } -} - -var UNIT_MIN = [-1.0, -1.0, -1.0]; -var UNIT_MAX = [1.0, 1.0, 1.0]; - -var EPSILON = 0.00001; - -var BOUNDS_MIN = [5.0, 0.0, 5.0]; -var BOUNDS_MAX = [15.0, 10.0, 15.0]; - -var GRANULARITY = 1.0 / 16.0; - -var WIDTH = 0.5; - -var HISTORY_LENGTH = 300; - -var stateHistory = []; -var position; -var velocity; -var hueAngle = 0; -var smoothedOffset; - -function step(deltaTime) { - if (stateHistory.length === 0) { - // start at a random position within the bounds, with a random velocity - position = randomVector(BOUNDS_MIN, BOUNDS_MAX); - do { - velocity = randomVector(UNIT_MIN, UNIT_MAX); - } while (vectorLength(velocity) < EPSILON); - velocity = vectorMultiply(velocity, GRANULARITY * 0.5 / vectorLength(velocity)); - smoothedOffset = [0.0, 0.0, 0.0]; - } - - var right = vectorCross(velocity, [0.0, 1.0, 0.0]); - if (vectorLength(right) < EPSILON) { - right = [1.0, 0.0, 0.0]; - } else { - right = vectorNormalize(right); - } - var up = vectorNormalize(vectorCross(right, velocity)); - var ANGULAR_SPEED = 2.0; - var radians = hueAngle * Math.PI * ANGULAR_SPEED / 180.0; - var offset = vectorAdd(vectorMultiply(right, WIDTH * Math.cos(radians)), vectorMultiply(up, WIDTH * Math.sin(radians))); - var OFFSET_SMOOTHING = 0.9; - smoothedOffset = vectorMix(offset, smoothedOffset, OFFSET_SMOOTHING); - - var state = { start: vectorAdd(position, smoothedOffset), end: vectorSubtract(position, smoothedOffset) }; - drawLine(state.start, state.end, getHueColor(hueAngle), GRANULARITY); - stateHistory.push(state); - if (stateHistory.length > HISTORY_LENGTH) { - var last = stateHistory.shift(); - eraseLine(last.start, last.end, GRANULARITY); - } - - // update position, check against bounds - position = vectorAdd(position, velocity); - for (var i = 0; i < 3; i++) { - if (position[i] < BOUNDS_MIN[i]) { - velocity[i] = -velocity[i]; - position[i] += 2.0 * (BOUNDS_MIN[i] - position[i]); - - } else if (position[i] > BOUNDS_MAX[i]) { - velocity[i] = -velocity[i]; - position[i] += 2.0 * (BOUNDS_MAX[i] - position[i]); - } - } - var MAX_HUE_ANGLE = 360; - hueAngle = (hueAngle + 1) % MAX_HUE_ANGLE; -} - -Script.update.connect(step); diff --git a/examples/rockPaperScissorsCells.js b/examples/rockPaperScissorsCells.js deleted file mode 100644 index 2a9cb00a0b..0000000000 --- a/examples/rockPaperScissorsCells.js +++ /dev/null @@ -1,272 +0,0 @@ -// rockPaperScissorsCells.js -// examples -// -// Created by Ben Arnold on 7/16/14. -// Copyright 2014 High Fidelity, Inc. -// -// This sample script creates a voxel wall that simulates the Rock Paper Scissors cellular -// automata. http://www.gamedev.net/blog/844/entry-2249737-another-cellular-automaton-video/ -// If multiple instances of this script are run, they will combine into a larger wall. -// NOTE: You must run each instance one at a time. If they all start at once there are race conditions. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var NUMBER_OF_CELLS_EACH_DIMENSION = 48; -var NUMBER_OF_CELLS_REGION_EACH_DIMESION = 16; -var REGIONS_EACH_DIMENSION = NUMBER_OF_CELLS_EACH_DIMENSION / NUMBER_OF_CELLS_REGION_EACH_DIMESION; - -var isLocal = false; - -var currentCells = []; -var nextCells = []; - -var cornerPosition = {x: 100, y: 0, z: 0 } -var position = {x: 0, y: 0, z: 0 }; - -var METER_LENGTH = 1; -var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; - -var viewerPosition = {x: cornerPosition.x + (NUMBER_OF_CELLS_EACH_DIMENSION / 2) * cellScale, y: cornerPosition.y + (NUMBER_OF_CELLS_EACH_DIMENSION / 2) * cellScale, z: cornerPosition.z }; - -viewerPosition.z += 50; -var yaw = 0; -var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0); - -//Feel free to add new cell types here. It can be more than three. -var cellTypes = []; -cellTypes[0] = { r: 255, g: 0, b: 0 }; -cellTypes[1] = { r: 0, g: 255, b: 0 }; -cellTypes[2] = { r: 0, g:0, b: 255 }; -cellTypes[3] = { r: 0, g: 255, b: 255 }; - - -//Check for free region for AC -var regionMarkerX = -1; -var regionMarkerY = -1; -var regionMarkerI = -1; -var regionMarkerJ = -1; - -var regionMarkerColor = {r: 254, g: 0, b: 253}; - -function setRegionToColor(startX, startY, width, height, color) { - for (var i = startY; i < startY + height; i++) { - for (var j = startX; j < startX + width; j++) { - - currentCells[i][j] = { changed: true, type: color }; - - // put the same value in the nextCells array for first board draw - nextCells[i][j] = { changed: true, type: color }; - } - } -} - -function init() { - - for (var i = 0; i < REGIONS_EACH_DIMENSION; i++) { - for (var j = 0; j < REGIONS_EACH_DIMENSION; j++) { - var x = cornerPosition.x + (j) * cellScale; - var y = cornerPosition.y + (i + NUMBER_OF_CELLS_EACH_DIMENSION) * cellScale; - var z = cornerPosition.z; - var voxel = Voxels.getVoxelAt(x, y, z, cellScale); - if (voxel.x != x || voxel.y != y || voxel.z != z || voxel.s != cellScale || - voxel.red != regionMarkerColor.r || voxel.green != regionMarkerColor.g || voxel.blue != regionMarkerColor.b) { - regionMarkerX = x; - regionMarkerY = y; - regionMarkerI = i; - regionMarkerJ = j; - i = REGIONS_EACH_DIMENSION; //force quit loop - break; - } - } - } - - //Didnt find an open spot, end script - if (regionMarkerX == -1) { - Script.stop(); - } - - position.x = cornerPosition.x + regionMarkerJ * NUMBER_OF_CELLS_REGION_EACH_DIMESION; - position.y = cornerPosition.y + regionMarkerI * NUMBER_OF_CELLS_REGION_EACH_DIMESION; - position.z = cornerPosition.z; - - Voxels.setVoxel(regionMarkerX, regionMarkerY, cornerPosition.z, cellScale, regionMarkerColor.r, regionMarkerColor.g, regionMarkerColor.b); - - for (var i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - // create the array to hold this row - currentCells[i] = []; - - // create the array to hold this row in the nextCells array - nextCells[i] = []; - } - - var width = NUMBER_OF_CELLS_REGION_EACH_DIMESION / 2; - setRegionToColor(0, 0, width, width, 0); - setRegionToColor(0, width, width, width, 1); - setRegionToColor(width, width, width, width, 2); - setRegionToColor(width, 0, width, width, 3); -} - -function updateCells() { - var i = 0; - var j = 0; - var cell; - var y = 0; - var x = 0; - - for (i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) { - - cell = currentCells[i][j]; - - var r = Math.floor(Math.random() * 8); - - switch (r){ - case 0: - y = i - 1; - x = j - 1; - break; - case 1: - y = i; - x = j-1; - break; - case 2: - y = i + 1; - x = j - 1; - break; - case 3: - y = i + 1; - x = j; - break; - case 4: - y = i + 1; - x = j + 1; - break; - case 5: - y = i; - x = j + 1; - break; - case 6: - y = i - 1; - x = j + 1; - break; - case 7: - y = i - 1; - x = j; - break; - default: - continue; - - } - - //check the voxel grid instead of local array when on the edge - if (x == -1 || x == NUMBER_OF_CELLS_REGION_EACH_DIMESION || - y == -1 || y == NUMBER_OF_CELLS_REGION_EACH_DIMESION) { - - var voxel = Voxels.getVoxelAt(position.x + x * cellScale, position.y + y * cellScale, position.z, cellScale); - var predatorCellType = ((cell.type + 1) % cellTypes.length); - var predatorCellColor = cellTypes[predatorCellType]; - if (voxel.red == predatorCellColor.r && voxel.green == predatorCellColor.g && voxel.blue == predatorCellColor.b) { - nextCells[i][j].type = predatorCellType; - nextCells[i][j].changed = true; - } - } else { - - if (currentCells[y][x].type == ((cell.type + 1) % cellTypes.length)) { - nextCells[i][j].type = currentCells[y][x].type; - nextCells[i][j].changed = true; - } else { - //indicate no update - nextCells[i][j].changed = false; - } - } - } - } - - for (i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - for (j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) { - if (nextCells[i][j].changed == true) { - // there has been a change to this cell, change the value in the currentCells array - currentCells[i][j].type = nextCells[i][j].type; - currentCells[i][j].changed = true; - } - } - } -} - -function sendNextCells() { - for (var i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) { - for (var j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) { - if (nextCells[i][j].changed == true) { - // there has been a change to the state of this cell, send it - - // find the x and y position for this voxel, z = 0 - var x = j * cellScale; - var y = i * cellScale; - var type = nextCells[i][j].type; - - // queue a packet to add a voxel for the new cell - Voxels.setVoxel(position.x + x, position.y + y, position.z, cellScale, cellTypes[type].r, cellTypes[type].g, cellTypes[type].b); - } - } - } -} - -var sentFirstBoard = false; -var voxelViewerInit = false; - -var UPDATES_PER_SECOND = 6.0; -var frameIndex = 1.0; -var oldFrameIndex = 0; - -var framesToWait = UPDATES_PER_SECOND; - -function step(deltaTime) { - - if (isLocal == false) { - if (voxelViewerInit == false) { - VoxelViewer.setPosition(viewerPosition); - VoxelViewer.setOrientation(orientation); - voxelViewerInit = true; - } - VoxelViewer.queryOctree(); - } - - frameIndex += deltaTime * UPDATES_PER_SECOND; - if (Math.floor(frameIndex) == oldFrameIndex) { - return; - } - oldFrameIndex++; - - if (frameIndex <= framesToWait) { - return; - } - - if (sentFirstBoard) { - // we've already sent the first full board, perform a step in time - updateCells(); - } else { - // this will be our first board send - sentFirstBoard = true; - init(); - } - - if (isLocal == false) { - VoxelViewer.queryOctree(); - } - sendNextCells(); -} - -function scriptEnding() { - Voxels.eraseVoxel(regionMarkerX, regionMarkerY, position.z, cellScale); -} - -Script.scriptEnding.connect(scriptEnding); - -Script.update.connect(step); -Voxels.setPacketsPerSecond(2000); - -// test for local... -Menu.isOptionChecked("Voxels"); -isLocal = true; // will only get here on local client \ No newline at end of file diff --git a/examples/seeingVoxelsExample.js b/examples/seeingVoxelsExample.js deleted file mode 100644 index 35e2f95dd7..0000000000 --- a/examples/seeingVoxelsExample.js +++ /dev/null @@ -1,85 +0,0 @@ -// -// seeingVoxelsExample.js -// examples -// -// Created by Brad Hefta-Gaub on 2/26/14 -// 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 -// - -var count = 0; -var yawDirection = -1; -var yaw = 45; -var yawMax = 70; -var yawMin = 20; -var vantagePoint = {x: 5000, y: 500, z: 5000}; - -var isLocal = false; - -// set up our VoxelViewer with a position and orientation -var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0); - -function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function init() { - if (isLocal) { - MyAvatar.position = vantagePoint; - MyAvatar.orientation = orientation; - } else { - VoxelViewer.setPosition(vantagePoint); - VoxelViewer.setOrientation(orientation); - VoxelViewer.queryOctree(); - Agent.isAvatar = true; - } -} - -function keepLooking(deltaTime) { - //print("count =" + count); - - if (count == 0) { - init(); - } - count++; - if (count % getRandomInt(5, 15) == 0) { - yaw += yawDirection; - orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0); - if (yaw > yawMax || yaw < yawMin) { - yawDirection = yawDirection * -1; - } - - if (count % 10000 == 0) { - print("calling VoxelViewer.queryOctree()... count=" + count + " yaw=" + yaw); - } - - if (isLocal) { - MyAvatar.orientation = orientation; - } else { - VoxelViewer.setOrientation(orientation); - VoxelViewer.queryOctree(); - - if (count % 10000 == 0) { - print("VoxelViewer.getOctreeElementsCount()=" + VoxelViewer.getOctreeElementsCount()); - } - } - - } -} - -function scriptEnding() { - print("SCRIPT ENDNG!!!\n"); -} - -// register the call back so it fires before each data send -Script.update.connect(keepLooking); - -// register our scriptEnding callback -Script.scriptEnding.connect(scriptEnding); - - -// test for local... -Menu.isOptionChecked("Voxels"); -isLocal = true; // will only get here on local client diff --git a/examples/sit.js b/examples/sit.js index c3abe9a908..196a1a1972 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -10,7 +10,7 @@ // -var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; +var buttonImageUrl = "https://s3.amazonaws.com/hifi-public/images/tools/sit.svg"; var windowDimensions = Controller.getViewportDimensions(); diff --git a/examples/testModelOverlaySubMeshes.js b/examples/testModelOverlaySubMeshes.js deleted file mode 100644 index 20ec10ef7c..0000000000 --- a/examples/testModelOverlaySubMeshes.js +++ /dev/null @@ -1,88 +0,0 @@ -var position = Vec3.sum(MyAvatar.position, { x: 0, y: -1, z: 0}); - -var scalingFactor = 0.01; - -var sphereNaturalExtentsMin = { x: -1230, y: -1223, z: -1210 }; -var sphereNaturalExtentsMax = { x: 1230, y: 1229, z: 1223 }; -var panelsNaturalExtentsMin = { x: -1181, y: -326, z: 56 }; -var panelsNaturalExtentsMax = { x: 1181, y: 576, z: 1183 }; - -var sphereNaturalDimensions = Vec3.subtract(sphereNaturalExtentsMax, sphereNaturalExtentsMin); -var panelsNaturalDimensions = Vec3.subtract(panelsNaturalExtentsMax, panelsNaturalExtentsMin); -Vec3.print("sphereNaturalDimensions:", sphereNaturalDimensions); -Vec3.print("panelsNaturalDimensions:", panelsNaturalDimensions); - -var sphereNaturalCenter = Vec3.sum(sphereNaturalExtentsMin, Vec3.multiply(sphereNaturalDimensions, 0.5)); -var panelsNaturalCenter = Vec3.sum(panelsNaturalExtentsMin, Vec3.multiply(panelsNaturalDimensions, 0.5)); -Vec3.print("sphereNaturalCenter:", sphereNaturalCenter); -Vec3.print("panelsNaturalCenter:", panelsNaturalCenter); - -var sphereDimensions = Vec3.multiply(sphereNaturalDimensions, scalingFactor); -var panelsDimensions = Vec3.multiply(panelsNaturalDimensions, scalingFactor); -Vec3.print("sphereDimensions:", sphereDimensions); -Vec3.print("panelsDimensions:", panelsDimensions); - -var sphereCenter = Vec3.multiply(sphereNaturalCenter, scalingFactor); -var panelsCenter = Vec3.multiply(panelsNaturalCenter, scalingFactor); -Vec3.print("sphereCenter:", sphereCenter); -Vec3.print("panelsCenter:", panelsCenter); - -var centerShift = Vec3.subtract(panelsCenter, sphereCenter); -Vec3.print("centerShift:", centerShift); - -var spherePosition = position; -Vec3.print("spherePosition:", spherePosition); -var panelsPosition = Vec3.sum(spherePosition, centerShift); -Vec3.print("panelsPosition:", panelsPosition); - - -var screensOverlay = Overlays.addOverlay("model", { - position: panelsPosition, - dimensions: panelsDimensions, - url: "https://s3.amazonaws.com/hifi-public/models/sets/Lobby/LobbyConcepts/Lobby5_IsolatedPanelsFreezeTransforms.fbx" - }); - - -var structureOverlay = Overlays.addOverlay("model", { - position: spherePosition, - dimensions: sphereDimensions, - url: "https://s3.amazonaws.com/hifi-public/models/sets/Lobby/LobbyConcepts/Lobby5_OrbShellOnly.fbx", - ignoreRayIntersection: true, // we don't want to ray pick against any of this - }); - -var statusText = Overlays.addOverlay("text", { - x: 200, - y: 100, - width: 200, - height: 20, - backgroundColor: { red: 0, green: 0, blue: 0}, - alpha: 1.0, - backgroundAlpha: 1.0, - color: { red: 255, green: 255, blue: 255}, - topMargin: 4, - leftMargin: 4, - text: "", - }); - - -Controller.mouseMoveEvent.connect(function(event){ - var pickRay = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(pickRay); - - if (result.intersects) { - if (result.overlayID == screensOverlay) { - Overlays.editOverlay(statusText, { text: "You are pointing at: " + result.extraInfo }); - } else { - Overlays.editOverlay(statusText, { text: "You are not pointing at a panel..." }); - } - } else { - Overlays.editOverlay(statusText, { text: "You are not pointing at a panel..." }); - } -}); - - -Script.scriptEnding.connect(function(){ - Overlays.deleteOverlay(screensOverlay); - Overlays.deleteOverlay(structureOverlay); - Overlays.deleteOverlay(statusText); -}); diff --git a/examples/testingVoxelViewerRestart.js b/examples/testingVoxelViewerRestart.js deleted file mode 100644 index c4ab67e8ba..0000000000 --- a/examples/testingVoxelViewerRestart.js +++ /dev/null @@ -1,94 +0,0 @@ -// -// testingVoxelSeeingRestart.js -// hifi -// -// Created by Brad Hefta-Gaub on 2/26/14 -// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var count = 0; -var yawDirection = -1; -var yaw = 45; -var yawMax = 70; -var yawMin = 20; -var vantagePoint = {x: 5000, y: 500, z: 5000}; - -var isLocal = false; - -// set up our VoxelViewer with a position and orientation -var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0); - -function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function init() { - if (isLocal) { - MyAvatar.position = vantagePoint; - MyAvatar.orientation = orientation; - } else { - VoxelViewer.setPosition(vantagePoint); - VoxelViewer.setOrientation(orientation); - VoxelViewer.queryOctree(); - Agent.isAvatar = true; - } -} - -function keepLooking(deltaTime) { - //print("count =" + count); - - if (count == 0) { - init(); - } - count++; - if (count % getRandomInt(5, 15) == 0) { - yaw += yawDirection; - orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0); - if (yaw > yawMax || yaw < yawMin) { - yawDirection = yawDirection * -1; - } - - //if (count % 10000 == 0) { - // print("calling VoxelViewer.queryOctree()... count=" + count + " yaw=" + yaw); - //} - - if (isLocal) { - MyAvatar.orientation = orientation; - } else { - VoxelViewer.setOrientation(orientation); - VoxelViewer.queryOctree(); - - //if (count % 10000 == 0) { - // print("VoxelViewer.getOctreeElementsCount()=" + VoxelViewer.getOctreeElementsCount()); - //} - } - } - - // approximately every second, consider stopping - if (count % 60 == 0) { - print("considering stop.... elementCount:" + VoxelViewer.getOctreeElementsCount()); - var stopProbability = 0.05; // 5% chance of stopping - if (Math.random() < stopProbability) { - print("stopping.... elementCount:" + VoxelViewer.getOctreeElementsCount()); - Script.stop(); - } - } -} - -function scriptEnding() { - print("SCRIPT ENDNG!!!\n"); -} - -// register the call back so it fires before each data send -Script.update.connect(keepLooking); - -// register our scriptEnding callback -Script.scriptEnding.connect(scriptEnding); - - -// test for local... -Menu.isOptionChecked("Voxels"); -isLocal = true; // will only get here on local client diff --git a/examples/twoFallingEntities.js b/examples/twoFallingEntities.js deleted file mode 100644 index 0d157b70c3..0000000000 --- a/examples/twoFallingEntities.js +++ /dev/null @@ -1,25 +0,0 @@ -// -// twoFallingEntities.js -// -// Creates a red 0.2 meter diameter ball right in front of your avatar that lives for 60 seconds -// - -var radius = 0.1; -var position = Vec3.sum(MyAvatar.position, Quat.getFront(MyAvatar.orientation)); -var properties = { - type: "Sphere", - position: position, - velocity: { x: 0, y: 0, z: 0}, - gravity: { x: 0, y: -0.05, z: 0}, - radius: radius, - damping: 0.999, - color: { red: 200, green: 0, blue: 0 }, - lifetime: 60 - }; - -var newEntity = Entities.addEntity(properties); -position.x -= radius * 1.0; -properties.position = position; -var newEntityTwo = Entities.addEntity(properties); - -Script.stop(); // no need to run anymore \ No newline at end of file diff --git a/examples/testXMLHttpRequest.js b/examples/utilities/diagnostics/XMLHttpRequest.js similarity index 99% rename from examples/testXMLHttpRequest.js rename to examples/utilities/diagnostics/XMLHttpRequest.js index 79d2842464..fb25cb4fad 100644 --- a/examples/testXMLHttpRequest.js +++ b/examples/utilities/diagnostics/XMLHttpRequest.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("Test.js"); +Script.include("../../libraries/unitTest.js"); test("Test default request values", function(finished) { var req = new XMLHttpRequest(); diff --git a/examples/inWorldTestTone.js b/examples/utilities/diagnostics/inWorldTestTone.js similarity index 82% rename from examples/inWorldTestTone.js rename to examples/utilities/diagnostics/inWorldTestTone.js index 4547309faa..1fc3cbc2c8 100644 --- a/examples/inWorldTestTone.js +++ b/examples/utilities/diagnostics/inWorldTestTone.js @@ -11,15 +11,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/220Sine.wav"); var soundPlaying = false; +var offset = Vec3.normalize(Quat.getFront(MyAvatar.orientation)); +var position = Vec3.sum(MyAvatar.position, offset); + function update(deltaTime) { if (!Audio.isInjectorPlaying(soundPlaying)) { soundPlaying = Audio.playSound(sound, { + position: position, loop: true }); print("Started sound loop"); diff --git a/examples/orbitingSound.js b/examples/utilities/diagnostics/orbitingSound.js similarity index 100% rename from examples/orbitingSound.js rename to examples/utilities/diagnostics/orbitingSound.js diff --git a/examples/playSoundLoop.js b/examples/utilities/diagnostics/playSoundLoop.js similarity index 97% rename from examples/playSoundLoop.js rename to examples/utilities/diagnostics/playSoundLoop.js index f7116cb615..b9d35141d1 100644 --- a/examples/playSoundLoop.js +++ b/examples/utilities/diagnostics/playSoundLoop.js @@ -11,7 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include("../../libraries/globals.js"); // A few sample files you may want to try: diff --git a/examples/playSoundWave.js b/examples/utilities/diagnostics/playSoundWave.js similarity index 100% rename from examples/playSoundWave.js rename to examples/utilities/diagnostics/playSoundWave.js diff --git a/examples/typedArraysUnitTest.js b/examples/utilities/diagnostics/typedArraysUnitTest.js similarity index 99% rename from examples/typedArraysUnitTest.js rename to examples/utilities/diagnostics/typedArraysUnitTest.js index e86a07289d..0688667cc4 100644 --- a/examples/typedArraysUnitTest.js +++ b/examples/utilities/diagnostics/typedArraysUnitTest.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("Test.js"); +Script.include("../../libraries/unitTest.js"); // e.g. extractbits([0xff, 0x80, 0x00, 0x00], 23, 30); inclusive function extractbits(bytes, lo, hi) { diff --git a/examples/Recorder.js b/examples/utilities/record/recorder.js similarity index 100% rename from examples/Recorder.js rename to examples/utilities/record/recorder.js diff --git a/examples/crazylegs.js b/examples/utilities/tools/crazylegs.js similarity index 93% rename from examples/crazylegs.js rename to examples/utilities/tools/crazylegs.js index 7a6fb68520..38ecaba7c0 100644 --- a/examples/crazylegs.js +++ b/examples/utilities/tools/crazylegs.js @@ -4,6 +4,8 @@ // // Created by Andrzej Kapolka on 3/6/14. // Copyright 2014 High Fidelity, Inc. +// +// Outputs the joint index of an avatar, this is useful for avatar procedural animations // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/examples/currentAPI.js b/examples/utilities/tools/currentAPI.js similarity index 100% rename from examples/currentAPI.js rename to examples/utilities/tools/currentAPI.js diff --git a/examples/developerMenuItems.js b/examples/utilities/tools/developerMenuItems.js similarity index 100% rename from examples/developerMenuItems.js rename to examples/utilities/tools/developerMenuItems.js diff --git a/examples/voxelsoundwaves.js b/examples/voxelsoundwaves.js deleted file mode 100644 index 6de46e23cf..0000000000 --- a/examples/voxelsoundwaves.js +++ /dev/null @@ -1,226 +0,0 @@ - - - -var wallX = 8000; -var wallY = 8000; -var wallZ = 8000;//location - - -var VOXELSIZE=12;//size of each voxel - -var FACTOR = 0.75; - -var loud=1.0; -var maxLoud=500; -var minLoud=200;//range of loudness - - - -var maxB={color:225,direction:0,speed:1}; -var minB={color:50,direction:1,speed:1}; -var maxG={color:200,direction:0,speed:1}; -var minG={color:30,direction:1,speed:1}; -var maxR={color:255,direction:0,speed:1}; -var minR={color:150,direction:1,speed:1};//color objects -var addVoxArray=[]; -var removeVoxArray=[]; -var numAddVox=0; -var numRemoveVox=0;//array for voxels removed and added - - -var height; -var wallWidth=34; -var wallHeight=25; -var maxHeight=wallHeight; -var minHeight=0;//properties of wall - - -var heightSamplesArray=[]; -var sampleIndex=0;//declare new array of heights - -var direction=1; - - - - -//initiate and fill array of heights -for(var k=0;k\n#include ") + set(GL_HEADERS "#include ") elseif (UNIX) # include the right GL headers for UNIX - set(GL_HEADERS "#include \n#include \n#include ") + set(GL_HEADERS "#include \n#include ") elseif (WIN32) add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines - set(GL_HEADERS "#include \n#include \n#include \n#include ") + set(GL_HEADERS "#include \n#include \n#include ") endif () # set up the external glm library include_glm() +include_bullet() # create the InterfaceConfig.h file based on GL_HEADERS above configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h") @@ -107,7 +108,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics +link_hifi_libraries(shared octree environment gpu model fbx metavoxels networking entities avatars audio animation script-engine physics render-utils entities-renderer) # find any optional and required libraries @@ -194,11 +195,10 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers find_library(CoreAudio CoreAudio) find_library(CoreFoundation CoreFoundation) - find_library(GLUT GLUT) find_library(OpenGL OpenGL) find_library(AppKit AppKit) - target_link_libraries(${TARGET_NAME} ${CoreAudio} ${CoreFoundation} ${GLUT} ${OpenGL} ${AppKit}) + target_link_libraries(${TARGET_NAME} ${CoreAudio} ${CoreFoundation} ${OpenGL} ${AppKit}) # install command for OS X bundle INSTALL(TARGETS ${TARGET_NAME} @@ -214,15 +214,12 @@ else (APPLE) ) find_package(OpenGL REQUIRED) - find_package(GLUT REQUIRED) - - include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") if (${OPENGL_INCLUDE_DIR}) include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") endif () - target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}" "${GLUT_LIBRARIES}") + target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") # link target to external libraries if (WIN32) @@ -232,7 +229,7 @@ else (APPLE) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" wsock32.lib opengl32.lib) + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} "${NSIGHT_LIBRARIES}" wsock32.lib opengl32.lib Winmm.lib) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) @@ -246,4 +243,4 @@ else (APPLE) endif (APPLE) # link any dependencies bubbled up from our linked dependencies -link_shared_dependencies() +include_dependency_includes() diff --git a/interface/external/rtmidi/readme.txt b/interface/external/rtmidi/readme.txt index d0480fce4a..3b9d6603a9 100644 --- a/interface/external/rtmidi/readme.txt +++ b/interface/external/rtmidi/readme.txt @@ -3,7 +3,7 @@ Instructions for adding the RtMidi library to Interface Stephen Birarda, June 30, 2014 1. Download the RtMidi tarball from High Fidelity S3. - http://highfidelity-public.s3.amazonaws.com/dependencies/rtmidi-2.1.0.tar.gz + http://public.highfidelity.io/dependencies/rtmidi-2.1.0.tar.gz 2. Copy RtMidi.h to externals/rtmidi/include. diff --git a/interface/external/sdl2/readme.txt b/interface/external/sdl2/readme.txt new file mode 100644 index 0000000000..9f3bd40e15 --- /dev/null +++ b/interface/external/sdl2/readme.txt @@ -0,0 +1,13 @@ + +Instructions for adding the SDL library (SDL2) to Interface +David Rowe, 11 Jan 2015 + +You can download the SDL development library from https://www.libsdl.org/. Interface has been tested with version 2.0.3. + +1. Copy the include and lib folders into the interface/externals/sdl2 folder. + This readme.txt should be there as well. + + You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects). + If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'sdl2' that contains the two folders mentioned above. + +2. Clear your build directory, run cmake and build, and you should be all set. diff --git a/interface/interface_en.ts b/interface/interface_en.ts index b85628b104..b011f37317 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -3,11 +3,6 @@ Application - - - Export Voxels - - Sparse Voxel Octree Files (*.svo) @@ -226,45 +221,23 @@ - Voxels - - - - - - Maximum voxels + Octree - Max voxels sent each second + Max packets sent each second QObject - - - - Import Voxels - - Loading ... - - - Place voxels - - - - - <b>Import</b> %1 as voxels - - Cancel diff --git a/interface/resources/shaders/directional_light.frag b/interface/resources/shaders/directional_light.frag deleted file mode 100644 index 906a33ea74..0000000000 --- a/interface/resources/shaders/directional_light.frag +++ /dev/null @@ -1,71 +0,0 @@ -#version 120 - -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/14. -// 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 -// - -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; - -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; - -void main(void) { - float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r; - vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st); - vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st); - - // compute the view space position using the depth - float z = near / (depthVal * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 0.0); - - // get the normal from the map - vec4 normal = normalVal; - if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { - normal.a = 1.0; - normalVal.a = 0.0; - gl_FragColor = vec4(diffuseVal.rgb * specularVal.rgb, 1.0); - } else { - vec3 normalizedNormal = normalize(normal.xyz * 2.0 - vec3(1.0)); - - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz); - float facingLight = step(0.0, diffuse); - vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb + - gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); - - // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)), - normalizedNormal)); - - // add specular contribution - vec4 specularColor = specularVal; - gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); - } -} diff --git a/interface/resources/shaders/directional_light_cascaded_shadow_map.frag b/interface/resources/shaders/directional_light_cascaded_shadow_map.frag deleted file mode 100644 index ac9c784d9a..0000000000 --- a/interface/resources/shaders/directional_light_cascaded_shadow_map.frag +++ /dev/null @@ -1,80 +0,0 @@ -#version 120 - -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/14. -// 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 -// - -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; - -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the distances to the cascade sections -uniform vec3 shadowDistances; - -// the inverse of the size of the shadow map -uniform float shadowScale; - -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; - -void main(void) { - // compute the view space position using the depth - float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); - - // compute the index of the cascade to use and the corresponding texture coordinates - int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[shadowIndex], position), dot(gl_EyePlaneT[shadowIndex], position), - dot(gl_EyePlaneR[shadowIndex], position)); - - // get the normal from the map - vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); - - // average values from the shadow map - float diffuse = dot(normalizedNormal, gl_LightSource[0].position); - float facingLight = step(0.0, diffuse) * 0.25 * - (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); - - // compute the base color based on OpenGL lighting model - vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + - gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - - // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), - normalizedNormal)); - - // add specular contribution - vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); - gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); -} diff --git a/interface/resources/shaders/directional_light_shadow_map.frag b/interface/resources/shaders/directional_light_shadow_map.frag deleted file mode 100644 index f1eaa20826..0000000000 --- a/interface/resources/shaders/directional_light_shadow_map.frag +++ /dev/null @@ -1,75 +0,0 @@ -#version 120 - -// -// directional_light.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/3/14. -// 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 -// - -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; - -// the shadow texture -uniform sampler2DShadow shadowMap; - -// the inverse of the size of the shadow map -uniform float shadowScale; - -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; - -void main(void) { - // compute the view space position using the depth - float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); - - // compute the corresponding texture coordinates - vec3 shadowTexCoord = vec3(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position)); - - // get the normal from the map - vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); - - // average values from the shadow map - float diffuse = dot(normalizedNormal, gl_LightSource[0].position); - float facingLight = step(0.0, diffuse) * 0.25 * - (shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(-shadowScale, shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, -shadowScale, 0.0)).r + - shadow2D(shadowMap, shadowTexCoord + vec3(shadowScale, shadowScale, 0.0)).r); - - // compute the base color based on OpenGL lighting model - vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightModelProduct.sceneColor + - gl_FrontLightProduct[0].ambient + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); - - // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), - normalizedNormal)); - - // add specular contribution - vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); - gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normal.a); -} diff --git a/interface/resources/shaders/grid.frag b/interface/resources/shaders/grid.frag index 17ad0fed5c..935a258492 100644 --- a/interface/resources/shaders/grid.frag +++ b/interface/resources/shaders/grid.frag @@ -5,14 +5,23 @@ // fragment shader // // Created by Andrzej Kapolka on 1/21/14. +// Update by Ryan Huffman on 12/30/14. // Copyright 2013 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 // +varying vec2 modelCoords; + +// Squared distance from center of 1x1 square to an edge along a single axis (0.5 * 0.5) +const float SQUARED_DISTANCE_TO_EDGE = 0.25; + void main(void) { - // use the standard exponential fog calculation - const float FOG_DENSITY = 0.5; - gl_FragColor = vec4(gl_Color.rgb, exp(-FOG_DENSITY / gl_FragCoord.w)); + // Squared distance from grid center - this assumes the grid lines are from + // 0.0 ... 1.0 in model space. + float sqDist = pow(modelCoords.x - 0.5, 2) + pow(modelCoords.y - 0.5, 2); + float alpha = max(0, SQUARED_DISTANCE_TO_EDGE - sqDist) / SQUARED_DISTANCE_TO_EDGE; + alpha *= gl_Color.a; + gl_FragColor = vec4(gl_Color.rgb, alpha); } diff --git a/interface/resources/shaders/grid.vert b/interface/resources/shaders/grid.vert new file mode 100644 index 0000000000..dcb7422090 --- /dev/null +++ b/interface/resources/shaders/grid.vert @@ -0,0 +1,20 @@ +#version 120 + +// +// grid.vert +// vertex shader +// +// Created by Ryan Huffman on 12/30/14 +// 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 +// + +varying vec2 modelCoords; + +void main(void) { + modelCoords = gl_Vertex.xy; + gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xy, 0, 1); + gl_FrontColor = gl_Color; +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6b8f08c78b..e4207807cf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include @@ -71,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +84,10 @@ #include "ModelUploader.h" #include "Util.h" +#include "audio/AudioToolBox.h" +#include "audio/AudioIOStatsRenderer.h" +#include "audio/AudioScope.h" + #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/Leapmotion.h" @@ -131,7 +135,7 @@ static QTimer* idleTimer = NULL; const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; -const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js"; +const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js"; void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); @@ -141,8 +145,42 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt } } +bool setupEssentials(int& argc, char** argv) { + unsigned int listenPort = 0; // bind to an ephemeral port by default + const char** constArgv = const_cast(argv); + const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); + if (portStr) { + listenPort = atoi(portStr); + } + + DependencyManager::registerInheritance(); + + // Set dependencies + auto glCanvas = DependencyManager::set(); + auto addressManager = DependencyManager::set(); + auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); + auto geometryCache = DependencyManager::set(); + auto glowEffect = DependencyManager::set(); + auto faceshift = DependencyManager::set(); + auto audio = DependencyManager::set