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 a0d463b766..367fb88a26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,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 88b2b62bd9..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 ) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index bd55a4a3e0..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,7 +45,6 @@ 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); } @@ -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 ) { @@ -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); @@ -168,7 +154,6 @@ void Agent::run() { nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::VoxelServer << NodeType::EntityServer ); @@ -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/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 6218ae7f9d..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; @@ -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); 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.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/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index 18988a919c..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); } 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 2e13b43799..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(); @@ -240,7 +240,7 @@ 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); DependencyManager::get()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; @@ -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); @@ -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 c123dd4349..019574c05c 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -358,7 +358,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 +373,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 +712,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", diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 4999594a98..a467a8a650 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); 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/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.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/IncludeDependencyIncludes.cmake b/cmake/macros/IncludeDependencyIncludes.cmake index a375404164..4474bdc53a 100644 --- a/cmake/macros/IncludeDependencyIncludes.cmake +++ b/cmake/macros/IncludeDependencyIncludes.cmake @@ -15,8 +15,8 @@ macro(INCLUDE_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}") + + # 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/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index ae6f116537..3435f49b71 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -410,99 +410,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 ffbf58024d..ddd184d6a2 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -552,7 +552,8 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet(static_cast(defaultedType) + 1)) { if (!excludedTypes.contains(defaultedType) - && defaultedType != Assignment::UNUSED + && 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 @@ -563,7 +564,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSetrespond(HTTPConnection::StatusCode302, QByteArray(), HTTPConnection::DefaultContentType, cookieHeaders); + delete tokenReply; + delete profileReply; + // we've redirected the user back to our homepage return true; @@ -1989,7 +1993,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()); } 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/grenadeLauncher.js b/examples/controllers/hydra/gun.js similarity index 81% rename from examples/grenadeLauncher.js rename to examples/controllers/hydra/gun.js index 3907e41ea6..de18317335 100644 --- a/examples/grenadeLauncher.js +++ b/examples/controllers/hydra/gun.js @@ -1,20 +1,20 @@ // -// grenadeLauncher.js +// gun.js // examples -// Created by Ben Arnold on 7/11/14. -// This is a modified version of gun.js by Brad Hefta-Gaub. // +// Created by Brad Hefta-Gaub on 12/31/13. +// Modified by Philip on 3/3/14 // 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. +// When entities collide with voxels they blow little 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"); +Script.include("../../libraries/globals.js"); function getRandomFloat(min, max) { return Math.random() * (max - min) + min; @@ -26,10 +26,9 @@ var yawFromMouse = 0; var pitchFromMouse = 0; var isMouseDown = false; -var BULLET_VELOCITY = 3.0; +var BULLET_VELOCITY = 5.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; @@ -44,7 +43,7 @@ var targetLaunchSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%2 var gunModel = "http://public.highfidelity.io/models/attachments/HaloGun.fst"; -var audioOptions { +var audioOptions = { volume: 0.9 } @@ -89,24 +88,24 @@ if (showScore) { }); } + + 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 + var BULLET_SIZE = 0.01; + var BULLET_LIFETIME = 20.0; + var BULLET_GRAVITY = -0.02; Entities.addEntity( { type: "Sphere", position: position, - collisionsWillMove: true, - dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, + dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, color: { red: 10, green: 10, blue: 10 }, velocity: velocity, + lifetime: BULLET_LIFETIME, gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, - lifetime: 10.0, damping: 0 }); // Play firing sounds @@ -121,6 +120,7 @@ function shootBullet(position, velocity) { function shootTarget() { var TARGET_SIZE = 0.25; var TARGET_GRAVITY = -0.6; + var TARGET_LIFETIME = 300.0; var TARGET_UP_VELOCITY = 3.0; var TARGET_FWD_VELOCITY = 5.0; var DISTANCE_TO_LAUNCH_FROM = 3.0; @@ -139,13 +139,12 @@ function shootTarget() { Entities.addEntity( { type: "Sphere", position: newPosition, - collisionsWillMove: true, - dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, + 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 }); + lifetime: TARGET_LIFETIME, + damping: 0.0001 }); // Record start time shotTime = new Date(); @@ -157,48 +156,13 @@ function shootTarget() { -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 } ); } + + // Sort out which entity is which // Record shot time var endTime = new Date(); @@ -230,21 +194,20 @@ function playLoadSound() { 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); +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: -.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 + // 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; yawFromMouse = 0; - // apply pitch from controller or mouse + // apply pitch from mouse var newPitch = MyAvatar.headPitch + pitchFromMouse; MyAvatar.headPitch = newPitch; pitchFromMouse = 0; @@ -270,7 +233,6 @@ function update(deltaTime) { 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) { @@ -284,8 +246,8 @@ function update(deltaTime) { } } + if (shootABullet) { - var palmController = t * controllersPerTrigger; var palmPosition = Controller.getSpatialControlPosition(palmController); @@ -337,8 +299,7 @@ function mouseReleaseEvent(event) { } function mouseMoveEvent(event) { - //Move the camera if LEFT_BUTTON_1 is pressed - if (Controller.isButtonPressed(LEFT_BUTTON_1)) { + if (isMouseDown) { var MOUSE_YAW_SCALE = -0.25; var MOUSE_PITCH_SCALE = -12.5; var FIXED_MOUSE_TIMESTEP = 0.016; @@ -355,7 +316,6 @@ function scriptEnding() { MyAvatar.detachOne(gunModel); } -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/laserPointer.js b/examples/controllers/hydra/laserPointer.js similarity index 100% rename from examples/laserPointer.js rename to examples/controllers/hydra/laserPointer.js 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/editEntities.js b/examples/editEntities.js index 0b5c089c07..2462c30854 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); @@ -1066,6 +1077,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/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/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/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/gun.js b/examples/gun.js index 2386e61539..c5b7b17052 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -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,93 @@ 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(); +} + +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: -.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) { + 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 +313,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 +328,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 +351,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 +364,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 +400,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/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..d7f097966a 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -84,6 +84,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"); @@ -419,6 +421,13 @@ action: "resetToNaturalDimensions", })); }); + elRescaleDimensionsButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "rescaleDimensions", + percentage: parseInt(elRescaleDimensionsPct.value), + })); + }); var resizing = false; @@ -537,6 +546,12 @@
+
+ % +
+ + + @@ -618,7 +633,7 @@ Script URL - + @@ -637,13 +652,13 @@ Model URL - + Animation URL - + 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..2f43b1c356 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -96,6 +96,10 @@ input { background-color: #eee; } +input.url { + width: 100%; +} + table#entity-table { border-collapse: collapse; font-family: Sans-Serif; @@ -171,7 +175,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/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/entityCameraTool.js b/examples/libraries/entityCameraTool.js index 803a58f48e..b6a86e7a4d 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 = {}; @@ -92,8 +105,6 @@ CameraManager = function() { Camera.mode = "independent"; that.updateCamera(); - - cameraTool.setVisible(false); } that.disable = function(ignoreCamera) { @@ -104,7 +115,6 @@ CameraManager = function() { if (!ignoreCamera) { Camera.mode = that.previousCameraMode; } - cameraTool.setVisible(false); } that.focus = function(position, dimensions, easeOrientation) { @@ -140,6 +150,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 +243,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 +266,7 @@ CameraManager = function() { return true; } - return cameraTool.mousePressEvent(event); + return false; } that.mouseReleaseEvent = function(event) { @@ -271,7 +290,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 +312,8 @@ CameraManager = function() { } Camera.setOrientation(q); + + // cameraTool.update(); } function normalizeDegrees(degrees) { @@ -301,6 +325,7 @@ CameraManager = function() { // Ease the position and orbit of the camera that.update = function(dt) { if (Camera.mode != "independent") { + that.updateCamera(); return; } @@ -358,321 +383,215 @@ CameraManager = function() { Controller.wheelEvent.connect(that.wheelEvent); - var cameraTool = new CameraTool(that); + // var cameraTool = new CameraTool(that); 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 ORIENTATION_OVERLAY_SIZE = 20; + var ORIENTATION_OVERLAY_HALF_SIZE = ORIENTATION_OVERLAY_SIZE / 2; + var ORIENTATION_OVERLAY_CUBE_SIZE = 8, + + var ORIENTATION_OVERLAY_OFFSET = { + x: 96, + y: 30, + } + + var UI_URL = HIFI_PUBLIC_BUCKET + "images/tools/camera-controls.svg"; + + var UI_WIDTH = 128; + var UI_HEIGHT = 61; + var UI_PADDING = 10; + + var UI_BUTTON_WIDTH = 64; + var UI_BUTTON_HEIGHT = 30; + + var UI_SUBIMAGE_FIRST_PERSON = { + x: 0, + y: 0, + width: UI_WIDTH, + height: UI_HEIGHT + }, + var UI_SUBIMAGE_THIRD_PERSON = { + x: 0, + y: UI_HEIGHT, + width: UI_WIDTH, + height: UI_HEIGHT + }, + var UI_SUBIMAGE_OTHER = { + x: 0, + y: UI_HEIGHT * 2, + width: UI_WIDTH, + height: UI_HEIGHT + }, + + var lastKnownWidth = Window.innerWidth; + + var uiPosition = { + x: lastKnownWidth - UI_WIDTH - UI_PADDING, + y: UI_PADDING, + }; + + var ui = Overlays.addOverlay("image", { + imageURL: UI_URL, + x: uiPosition.x, + y: uiPosition.y, + subImage: { + x: 0, + y: 0, + width: UI_WIDTH, + height: UI_HEIGHT + }, + width: UI_WIDTH, + height: UI_HEIGHT, + alpha: 1.0, + visible: true }); - 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 }); }, - }); - 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: true, + drawOnHUD: true, + }; + + var orientationOverlay = OverlayGroup({ + position: { + x: uiPosition.x + ORIENTATION_OVERLAY_OFFSET.x, + y: uiPosition.y + ORIENTATION_OVERLAY_OFFSET.y, + } }); + 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(ui); }); + 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, + }; + Overlays.editOverlay(ui, { + x: uiPosition.x, + y: uiPosition.y + }); + orientationOverlay.setProperties({ + position: { + x: uiPosition.x + ORIENTATION_OVERLAY_OFFSET.x, + y: uiPosition.y + ORIENTATION_OVERLAY_OFFSET.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; + } else if (clickedOverlay == ui) { + var x = event.x - uiPosition.x; + var y = event.y - uiPosition.y; + + // Did we hit a button? + if (x < UI_BUTTON_WIDTH) { + if (y < UI_BUTTON_HEIGHT) { + Camera.mode = "first person"; + } else { + Camera.mode = "third person"; + } + } + return true; + } }; + function updateMode() { + var mode = Camera.mode; + + var subImage = UI_SUBIMAGE_OTHER; + if (mode == "first person") { + subImage = UI_SUBIMAGE_FIRST_PERSON; + } else if (mode == "third person") { + subImage = UI_SUBIMAGE_THIRD_PERSON; + } + + Overlays.editOverlay(ui, { subImage: subImage }); + } + + Camera.modeUpdated.connect(updateMode); + updateMode(); + that.setVisible = function(visible) { - orbitTool.setVisible(visible); - panTool.setVisible(visible); - zoomTool.setVisible(visible); }; - Script.update.connect(function() { - cameraManager.getZoomPercentage(); - zoomTool.setZoomPercentage(cameraManager.getZoomPercentage()); - }); - - that.setVisible(false); - return that; }; diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 8aff9c32ed..2b83d7740d 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -590,7 +590,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: "https://public.highfidelity.io/images/rotate-arrow-west-north.png", position: { x:0, y: 0, z: 0}, color: rotateHandleColor, alpha: rotateHandleAlpha, @@ -603,7 +603,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: "https://public.highfidelity.io/images/rotate-arrow-west-north.png", position: { x:0, y: 0, z: 0}, color: rotateHandleColor, alpha: rotateHandleAlpha, @@ -616,7 +616,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: "https://public.highfidelity.io/images/rotate-arrow-west-north.png", position: { x:0, y: 0, z: 0}, color: rotateHandleColor, alpha: rotateHandleAlpha, @@ -835,8 +835,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: "https://public.highfidelity.io/images/rotate-arrow-west-south.png" }); + Overlays.editOverlay(rollHandle, { url: "https://public.highfidelity.io/images/rotate-arrow-west-south.png" }); } else { @@ -867,8 +867,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: "https://public.highfidelity.io/images/rotate-arrow-west-north.png" }); + Overlays.editOverlay(rollHandle, { url: "https://public.highfidelity.io/images/rotate-arrow-west-north.png" }); } } else { @@ -899,8 +899,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: "https://public.highfidelity.io/images/rotate-arrow-west-north.png" }); + Overlays.editOverlay(rollHandle, { url: "https://public.highfidelity.io/images/rotate-arrow-west-north.png" }); } else { @@ -928,8 +928,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: "https://public.highfidelity.io/images/rotate-arrow-west-north.png" }); + Overlays.editOverlay(rollHandle, { url: "https://public.highfidelity.io/images/rotate-arrow-west-north.png" }); } } 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..7623bfbb30 --- /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 = 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/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..71d909d1e7 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://public.highfidelity.io/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 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_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 684563ac30..11b28fc503 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,8 @@ #include "ModelUploader.h" #include "Util.h" +#include "audio/AudioToolBox.h" + #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/Leapmotion.h" @@ -151,15 +153,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _frameCount(0), _fps(60.0f), _justStarted(true), - _voxelImportDialog(NULL), - _voxelImporter(), - _importSucceded(false), - _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), +#ifdef USE_BULLET_PHYSICS + _physicsEngine(glm::vec3(0.0f)), +#endif // USE_BULLET_PHYSICS _entities(true, this, this), _entityCollisionSystem(), _entityClipboardRenderer(false, this, this), _entityClipboard(), - _wantToKillLocalVoxels(false), _viewFrustum(), _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), @@ -174,10 +174,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), - _audio(), - _enableProcessVoxelsThread(true), + _enableProcessOctreeThread(true), _octreeProcessor(), - _voxelHideShowThread(&_voxels), _packetsPerSecond(0), _bytesPerSecond(0), _nodeBoundsDisplay(this), @@ -250,9 +248,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // put the audio processing on a separate thread QThread* audioThread = new QThread(this); - - _audio.moveToThread(audioThread); - connect(audioThread, SIGNAL(started()), &_audio, SLOT(start())); + + auto audioIO = DependencyManager::get