mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 01:33:35 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
aae168dd46
113 changed files with 2183 additions and 817 deletions
assignment-client/src
examples
airGuitar.jsaudioBall.jsavatarCollision.jsbirdSongs.jsbot.jsbotProceduralWayPoints.jsbot_procedural.jsclap.jsdrumStick.jseditModels.jseditVoxels.jsentityBirds.js
entityScripts
frisbee.jsgrenadeLauncher.jsgun.jsheadMove.jshtml
inWorldTestTone.jsleapHands.jslibraries
lobby.jsnewEditEntities.jsoverlaysExample.jsplaySound.jsplaySoundLoop.jsplaySoundOrbit.jsplaySoundWave.jsradio.jsspaceInvadersExample.jstoyball.jsinterface/src
Application.cppApplication.hFileLogger.cppMenu.cppMenu.h
devices
gpu
renderer
scripting
ui
ToolWindow.cppToolWindow.h
overlays
Base3DOverlay.cppBase3DOverlay.hBillboardOverlay.cppBillboardOverlay.hCircle3DOverlay.cppCircle3DOverlay.hGrid3DOverlay.cppGrid3DOverlay.hImageOverlay.cppImageOverlay.hLine3DOverlay.cppLine3DOverlay.hLocalVoxelsOverlay.cppLocalVoxelsOverlay.hModelOverlay.cppModelOverlay.hOverlay.cppOverlay.hOverlay2D.cppOverlay2D.hOverlays.cppOverlays.hPlanar3DOverlay.cppPlanar3DOverlay.hText3DOverlay.cppText3DOverlay.hTextOverlay.cppTextOverlay.hVolume3DOverlay.cppVolume3DOverlay.h
libraries
audio/src
AudioInjector.cppAudioInjector.hAudioScriptingInterface.cppSound.cppSound.hSoundCache.cppSoundCache.h
avatars/src
entities/src
|
@ -23,6 +23,7 @@
|
|||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <SoundCache.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
|
@ -217,6 +218,8 @@ void Agent::run() {
|
|||
_scriptEngine.registerGlobalObject("Agent", this);
|
||||
|
||||
_scriptEngine.init(); // must be done before we set up the viewers
|
||||
|
||||
_scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance());
|
||||
|
||||
_scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer);
|
||||
// connect the VoxelViewer and the VoxelScriptingInterface to each other
|
||||
|
|
|
@ -774,7 +774,8 @@ void AudioMixer::run() {
|
|||
nodeData->checkBuffersBeforeFrameSend();
|
||||
|
||||
// if the stream should be muted, send mute packet
|
||||
if (shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) {
|
||||
if (nodeData->getAvatarAudioStream()
|
||||
&& shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) {
|
||||
static const int TIME_BETWEEN_MUTES = 5; // in secs
|
||||
if (usecTimestampNow() - nodeData->getAvatarAudioStream()->getLastMuted() >
|
||||
TIME_BETWEEN_MUTES * USECS_PER_SECOND) {
|
||||
|
|
|
@ -34,22 +34,22 @@ var guitarModel = HIFI_PUBLIC_BUCKET + "models/attachments/guitar.fst";
|
|||
|
||||
var chords = new Array();
|
||||
// Nylon string guitar
|
||||
chords[1] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+A.raw");
|
||||
chords[2] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+B.raw");
|
||||
chords[3] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+E.raw");
|
||||
chords[4] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+G.raw");
|
||||
chords[1] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+A.raw");
|
||||
chords[2] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+B.raw");
|
||||
chords[3] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+E.raw");
|
||||
chords[4] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+G.raw");
|
||||
|
||||
// Electric guitar
|
||||
chords[5] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+A+short.raw");
|
||||
chords[6] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+B+short.raw");
|
||||
chords[7] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+E+short.raw");
|
||||
chords[8] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+G+short.raw");
|
||||
chords[5] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+A+short.raw");
|
||||
chords[6] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+B+short.raw");
|
||||
chords[7] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+E+short.raw");
|
||||
chords[8] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Metal+G+short.raw");
|
||||
|
||||
// Steel Guitar
|
||||
chords[9] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+A.raw");
|
||||
chords[10] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+B.raw");
|
||||
chords[11] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+E.raw");
|
||||
chords[12] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+G.raw");
|
||||
chords[9] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+A.raw");
|
||||
chords[10] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+B.raw");
|
||||
chords[11] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+E.raw");
|
||||
chords[12] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Steel+G.raw");
|
||||
|
||||
var NUM_CHORDS = 4;
|
||||
var NUM_GUITARS = 3;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
Script.include("libraries/globals.js");
|
||||
|
||||
var sound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/mexicanWhipoorwill.raw");
|
||||
var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/mexicanWhipoorwill.raw");
|
||||
var CHANCE_OF_PLAYING_SOUND = 0.01;
|
||||
|
||||
var FACTOR = 0.05;
|
||||
|
|
|
@ -24,28 +24,28 @@ var audioOptions = {
|
|||
}
|
||||
|
||||
var hitSounds = new Array();
|
||||
hitSounds[0] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit1.raw");
|
||||
hitSounds[1] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit2.raw");
|
||||
hitSounds[2] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit3.raw");
|
||||
hitSounds[3] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit4.raw");
|
||||
hitSounds[4] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit5.raw");
|
||||
hitSounds[5] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit6.raw");
|
||||
hitSounds[6] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit7.raw");
|
||||
hitSounds[7] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit8.raw");
|
||||
hitSounds[8] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit9.raw");
|
||||
hitSounds[9] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit10.raw");
|
||||
hitSounds[10] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit11.raw");
|
||||
hitSounds[11] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit12.raw");
|
||||
hitSounds[12] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit13.raw");
|
||||
hitSounds[13] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit14.raw");
|
||||
hitSounds[14] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit15.raw");
|
||||
hitSounds[15] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit16.raw");
|
||||
hitSounds[16] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit17.raw");
|
||||
hitSounds[17] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit18.raw");
|
||||
hitSounds[18] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit19.raw");
|
||||
hitSounds[19] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit20.raw");
|
||||
hitSounds[20] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit21.raw");
|
||||
hitSounds[21] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/Hit22.raw");
|
||||
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();
|
||||
|
|
|
@ -67,7 +67,7 @@ function maybePlaySound(deltaTime) {
|
|||
lifetime: 10
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
playing.push({ audioId: Audio.playSound(birds[whichBird].sound, options), entityId: entityId, lightId: lightId, color: birds[whichBird].color });
|
||||
}
|
||||
if (playing.length != numPlaying) {
|
||||
|
@ -159,8 +159,9 @@ function loadBirds() {
|
|||
var SOUND_BASE_URL = "http://public.highfidelity.io/sounds/Animals/";
|
||||
|
||||
for (var i = 0; i < sound_filenames.length; i++) {
|
||||
birds.push({ sound: new Sound(SOUND_BASE_URL + sound_filenames[i]),
|
||||
color: colors[i]
|
||||
} );
|
||||
birds.push({
|
||||
sound: SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]),
|
||||
color: colors[i]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -228,6 +228,6 @@ function loadSounds() {
|
|||
var SOUND_BASE_URL = HIFI_PUBLIC_BUCKET + "sounds/Cocktail+Party+Snippets/Raws/";
|
||||
|
||||
for (var i = 0; i < sound_filenames.length; i++) {
|
||||
sounds.push(new Sound(SOUND_BASE_URL + sound_filenames[i]));
|
||||
sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,11 +151,11 @@ function loadSounds() {
|
|||
var FOOTSTEP_BASE_URL = HIFI_PUBLIC_BUCKET + "sounds/Footsteps/";
|
||||
|
||||
for (var i = 0; i < sound_filenames.length; i++) {
|
||||
sounds.push(new Sound(SOUND_BASE_URL + sound_filenames[i]));
|
||||
sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));
|
||||
}
|
||||
|
||||
for (var i = 0; i < footstep_filenames.length; i++) {
|
||||
footstepSounds.push(new Sound(FOOTSTEP_BASE_URL + footstep_filenames[i]));
|
||||
footstepSounds.push(SoundCache.getSound(FOOTSTEP_BASE_URL + footstep_filenames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,11 +113,11 @@ function loadSounds() {
|
|||
var FOOTSTEP_BASE_URL = HIFI_PUBLIC_BUCKET + "sounds/Footsteps/";
|
||||
|
||||
for (var i = 0; i < sound_filenames.length; i++) {
|
||||
sounds.push(new Sound(SOUND_BASE_URL + sound_filenames[i]));
|
||||
sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));
|
||||
}
|
||||
|
||||
for (var i = 0; i < footstep_filenames.length; i++) {
|
||||
footstepSounds.push(new Sound(FOOTSTEP_BASE_URL + footstep_filenames[i]));
|
||||
footstepSounds.push(SoundCache.getSound(FOOTSTEP_BASE_URL + footstep_filenames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,16 +28,16 @@ var lastClapFrame = 0;
|
|||
var lastAnimFrame = 0;
|
||||
|
||||
var claps = [];
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap1Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap2Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap3Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap4Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap5Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap6Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap7Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap8Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap9Rvb.wav"));
|
||||
claps.push(new Sound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap10Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap1Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap2Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap3Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap4Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap5Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap6Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap7Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap8Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap9Rvb.wav"));
|
||||
claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap10Rvb.wav"));
|
||||
var numberOfSounds = claps.length;
|
||||
|
||||
var clappingNow = false;
|
||||
|
|
|
@ -28,8 +28,8 @@ function vMinus(a, b) {
|
|||
|
||||
// First, load two percussion sounds to be used on the sticks
|
||||
|
||||
var drum1 = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Drums/RackTomHi.raw");
|
||||
var drum2 = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Drums/RackTomLo.raw");
|
||||
var drum1 = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Drums/RackTomHi.raw");
|
||||
var drum2 = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Drums/RackTomLo.raw");
|
||||
|
||||
// State Machine:
|
||||
// 0 = not triggered
|
||||
|
|
|
@ -1125,12 +1125,12 @@ var toolBar = (function () {
|
|||
browseModelsButton,
|
||||
loadURLMenuItem,
|
||||
loadFileMenuItem,
|
||||
menuItemWidth = 125,
|
||||
menuItemWidth,
|
||||
menuItemOffset,
|
||||
menuItemHeight,
|
||||
menuItemMargin = 5,
|
||||
menuTextColor = { red: 255, green: 255, blue: 255 },
|
||||
menuBackgoundColor = { red: 18, green: 66, blue: 66 };
|
||||
menuBackgroundColor = { red: 18, green: 66, blue: 66 };
|
||||
|
||||
function initialize() {
|
||||
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL);
|
||||
|
@ -1167,9 +1167,8 @@ var toolBar = (function () {
|
|||
loadURLMenuItem = Overlays.addOverlay("text", {
|
||||
x: newModelButton.x - menuItemWidth,
|
||||
y: newModelButton.y + menuItemOffset,
|
||||
width: menuItemWidth,
|
||||
height: menuItemHeight,
|
||||
backgroundColor: menuBackgoundColor,
|
||||
backgroundColor: menuBackgroundColor,
|
||||
topMargin: menuItemMargin,
|
||||
text: "Model URL",
|
||||
alpha: 0.9,
|
||||
|
@ -1179,15 +1178,19 @@ var toolBar = (function () {
|
|||
loadFileMenuItem = Overlays.addOverlay("text", {
|
||||
x: newModelButton.x - menuItemWidth,
|
||||
y: newModelButton.y + menuItemOffset + menuItemHeight,
|
||||
width: menuItemWidth,
|
||||
height: menuItemHeight,
|
||||
backgroundColor: menuBackgoundColor,
|
||||
backgroundColor: menuBackgroundColor,
|
||||
topMargin: menuItemMargin,
|
||||
text: "Model File",
|
||||
alpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
menuItemWidth = Math.max(Overlays.textWidth(loadURLMenuItem, "Model URL"),
|
||||
Overlays.textWidth(loadFileMenuItem, "Model File")) + 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 },
|
||||
|
|
|
@ -78,7 +78,7 @@ function SoundArray() {
|
|||
this.audioOptions = audioOptions
|
||||
this.sounds = new Array();
|
||||
this.addSound = function (soundURL) {
|
||||
this.sounds[this.sounds.length] = new Sound(soundURL);
|
||||
this.sounds[this.sounds.length] = SoundCache.getSound(soundURL);
|
||||
}
|
||||
this.play = function (index) {
|
||||
if (0 <= index && index < this.sounds.length) {
|
||||
|
@ -319,7 +319,7 @@ function ScaleSelector() {
|
|||
width: this.SECOND_PART, height: this.height,
|
||||
topMargin: 13,
|
||||
text: this.scale.toString(),
|
||||
alpha: 0.0,
|
||||
alpha: 0.9,
|
||||
visible: editToolsOn
|
||||
});
|
||||
this.powerOverlay = Overlays.addOverlay("text", {
|
||||
|
|
|
@ -70,23 +70,23 @@ function addBird()
|
|||
var size;
|
||||
var which = Math.random();
|
||||
if (which < 0.2) {
|
||||
tweet = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/bushtit_1.raw");
|
||||
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 = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/rosyfacedlovebird.raw");
|
||||
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 = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/saysphoebe.raw");
|
||||
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 = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/mexicanWhipoorwill.raw");
|
||||
tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/mexicanWhipoorwill.raw");
|
||||
color = { red: 23, green: 197, blue: 230 };
|
||||
size = 0.12;
|
||||
} else {
|
||||
tweet = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/westernscreechowl.raw");
|
||||
tweet = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/westernscreechowl.raw");
|
||||
color = { red: 50, green: 67, blue: 144 };
|
||||
size = 0.15;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
this.preload = function(entityID) {
|
||||
print("preload("+entityID.id+")");
|
||||
bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw");
|
||||
bird = SoundCache.getSound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw");
|
||||
};
|
||||
|
||||
this.clickDownOnEntity = function(entityID, mouseEvent) {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
this.preload = function(entityID) {
|
||||
print("preload("+entityID.id+")");
|
||||
bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw");
|
||||
bird = SoundCache.getSound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw");
|
||||
};
|
||||
|
||||
this.enterEntity = function(entityID) {
|
||||
|
|
|
@ -160,9 +160,9 @@ var rightMouseControl = new MouseControl("RIGHT");
|
|||
var mouseControls = [leftMouseControl, middleMouseControl, rightMouseControl];
|
||||
var currentMouseControl = false;
|
||||
|
||||
var newSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
|
||||
var catchSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
|
||||
var throwSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Switches%20and%20sliders/slider%20-%20whoosh1.raw");
|
||||
var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
|
||||
var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
|
||||
var throwSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Switches%20and%20sliders/slider%20-%20whoosh1.raw");
|
||||
|
||||
var simulatedFrisbees = [];
|
||||
|
||||
|
|
|
@ -36,11 +36,11 @@ var RELOAD_INTERVAL = 5;
|
|||
var showScore = false;
|
||||
|
||||
// Load some sound to use for loading and firing
|
||||
var fireSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw");
|
||||
var loadSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw");
|
||||
var impactSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guns/BulletImpact2.raw");
|
||||
var targetHitSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw");
|
||||
var targetLaunchSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw");
|
||||
var fireSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw");
|
||||
var loadSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw");
|
||||
var impactSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/BulletImpact2.raw");
|
||||
var targetHitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw");
|
||||
var targetLaunchSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw");
|
||||
|
||||
var gunModel = "http://public.highfidelity.io/models/attachments/HaloGun.fst";
|
||||
|
||||
|
|
|
@ -35,11 +35,11 @@ var RELOAD_INTERVAL = 5;
|
|||
var showScore = false;
|
||||
|
||||
// Load some sound to use for loading and firing
|
||||
var fireSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw");
|
||||
var loadSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw");
|
||||
var impactSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guns/BulletImpact2.raw");
|
||||
var targetHitSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw");
|
||||
var targetLaunchSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw");
|
||||
var fireSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw");
|
||||
var loadSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw");
|
||||
var impactSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/BulletImpact2.raw");
|
||||
var targetHitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw");
|
||||
var targetLaunchSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw");
|
||||
|
||||
var gunModel = "http://public.highfidelity.io/models/attachments/HaloGun.fst";
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ function activateWarp() {
|
|||
|
||||
var WATCH_AVATAR_DISTANCE = 2.5;
|
||||
|
||||
var sound = new Sound("http://public.highfidelity.io/sounds/Footsteps/FootstepW2Right-12db.wav");
|
||||
var sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW2Right-12db.wav");
|
||||
function playSound() {
|
||||
Audio.playSound(sound, {
|
||||
position: MyAvatar.position
|
||||
|
|
561
examples/html/entityProperties.html
Normal file
561
examples/html/entityProperties.html
Normal file
|
@ -0,0 +1,561 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script>
|
||||
function enableChildren(el, selector) {
|
||||
els = el.querySelectorAll(selector);
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
els[i].removeAttribute('disabled');
|
||||
}
|
||||
}
|
||||
function disableChildren(el, selector) {
|
||||
els = el.querySelectorAll(selector);
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
els[i].setAttribute('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
|
||||
function createEmitCheckedPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
function createEmitNumberPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":' + this.value + '}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
function createEmitTextPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":"' + this.value + '"}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) {
|
||||
return function() {
|
||||
var data = {
|
||||
type: "update",
|
||||
properties: {
|
||||
}
|
||||
};
|
||||
data.properties[property] = {
|
||||
x: elX.value,
|
||||
y: elY.value,
|
||||
z: elZ.value,
|
||||
};
|
||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) {
|
||||
return function() {
|
||||
var data = {
|
||||
type: "update",
|
||||
properties: {
|
||||
}
|
||||
};
|
||||
data.properties[property] = {
|
||||
red: elRed.value,
|
||||
green: elGreen.value,
|
||||
blue: elBlue.value,
|
||||
};
|
||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
function loaded() {
|
||||
var elType = document.getElementById("property-type");
|
||||
var elLocked = document.getElementById("property-locked");
|
||||
var elVisible = document.getElementById("property-visible");
|
||||
var elPositionX = document.getElementById("property-pos-x");
|
||||
var elPositionY = document.getElementById("property-pos-y");
|
||||
var elPositionZ = document.getElementById("property-pos-z");
|
||||
|
||||
var elDimensionsX = document.getElementById("property-dim-x");
|
||||
var elDimensionsY = document.getElementById("property-dim-y");
|
||||
var elDimensionsZ = document.getElementById("property-dim-z");
|
||||
|
||||
var elRegistrationX = document.getElementById("property-reg-x");
|
||||
var elRegistrationY = document.getElementById("property-reg-y");
|
||||
var elRegistrationZ = document.getElementById("property-reg-z");
|
||||
|
||||
var elLinearVelocityX = document.getElementById("property-lvel-x");
|
||||
var elLinearVelocityY = document.getElementById("property-lvel-y");
|
||||
var elLinearVelocityZ = document.getElementById("property-lvel-z");
|
||||
var elLinearDamping = document.getElementById("property-ldamping");
|
||||
|
||||
var elAngularVelocityX = document.getElementById("property-avel-x");
|
||||
var elAngularVelocityY = document.getElementById("property-avel-y");
|
||||
var elAngularVelocityZ = document.getElementById("property-avel-z");
|
||||
var elAngularDamping = document.getElementById("property-adamping");
|
||||
|
||||
var elGravityX = document.getElementById("property-grav-x");
|
||||
var elGravityY = document.getElementById("property-grav-y");
|
||||
var elGravityZ = document.getElementById("property-grav-z");
|
||||
|
||||
var elMass = document.getElementById("property-mass");
|
||||
var elIgnoreForCollisions = document.getElementById("property-ignore-for-collisions");
|
||||
var elCollisionsWillMove = document.getElementById("property-collisions-will-move");
|
||||
var elLifetime = document.getElementById("property-lifetime");
|
||||
|
||||
var elBoxSection = document.getElementById("box-section");
|
||||
var elBoxColorRed = document.getElementById("property-box-red");
|
||||
var elBoxColorGreen = document.getElementById("property-box-green");
|
||||
var elBoxColorBlue = document.getElementById("property-box-blue");
|
||||
|
||||
var elLightSection = document.getElementById('light-section');
|
||||
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
||||
var elLightDiffuseRed = document.getElementById("property-light-diffuse-red");
|
||||
var elLightDiffuseGreen = document.getElementById("property-light-diffuse-green");
|
||||
var elLightDiffuseBlue = document.getElementById("property-light-diffuse-blue");
|
||||
|
||||
var elLightAmbientRed = document.getElementById("property-light-ambient-red");
|
||||
var elLightAmbientGreen = document.getElementById("property-light-ambient-green");
|
||||
var elLightAmbientBlue = document.getElementById("property-light-ambient-blue");
|
||||
|
||||
var elLightSpecularRed = document.getElementById("property-light-specular-red");
|
||||
var elLightSpecularGreen = document.getElementById("property-light-specular-green");
|
||||
var elLightSpecularBlue = document.getElementById("property-light-specular-blue");
|
||||
|
||||
var elLightConstantAttenuation = document.getElementById("property-light-constant-attenuation");
|
||||
var elLightLinearAttenuation = document.getElementById("property-light-linear-attenuation");
|
||||
var elLightQuadraticAttenuation = document.getElementById("property-light-quadratic-attenuation");
|
||||
var elLightExponent = document.getElementById("property-light-exponent");
|
||||
var elLightCutoff = document.getElementById("property-light-cutoff");
|
||||
|
||||
var elModelSection = document.getElementById("model-section");
|
||||
var elModelURL = document.getElementById("property-model-url");
|
||||
var elModelAnimationURL = document.getElementById("property-model-animation-url");
|
||||
var elModelAnimationPlaying = document.getElementById("property-model-animation-playing");
|
||||
var elModelAnimationFPS = document.getElementById("property-model-animation-fps");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.type == "update") {
|
||||
if (data.properties === undefined) {
|
||||
disableChildren(document.getElementById("properties"), 'input');
|
||||
} else {
|
||||
var properties = data.properties;
|
||||
|
||||
elType.innerHTML = properties.type;
|
||||
|
||||
elLocked.checked = properties.locked;
|
||||
|
||||
if (properties.locked) {
|
||||
disableChildren(document.getElementById("properties"), 'input');
|
||||
elLocked.removeAttribute('disabled');
|
||||
} else {
|
||||
enableChildren(document.getElementById("properties"), 'input');
|
||||
|
||||
elVisible.checked = properties.visible;
|
||||
|
||||
elPositionX.value = properties.position.x.toFixed(2);
|
||||
elPositionY.value = properties.position.y.toFixed(2);
|
||||
elPositionZ.value = properties.position.z.toFixed(2);
|
||||
|
||||
elDimensionsX.value = properties.dimensions.x.toFixed(2);
|
||||
elDimensionsY.value = properties.dimensions.y.toFixed(2);
|
||||
elDimensionsZ.value = properties.dimensions.z.toFixed(2);
|
||||
|
||||
elRegistrationX.value = properties.registrationPoint.x.toFixed(2);
|
||||
elRegistrationY.value = properties.registrationPoint.y.toFixed(2);
|
||||
elRegistrationZ.value = properties.registrationPoint.z.toFixed(2);
|
||||
|
||||
elLinearVelocityX.value = properties.velocity.x.toFixed(2);
|
||||
elLinearVelocityY.value = properties.velocity.y.toFixed(2);
|
||||
elLinearVelocityZ.value = properties.velocity.z.toFixed(2);
|
||||
elLinearDamping.value = properties.damping.toFixed(2);
|
||||
|
||||
elAngularVelocityX.value = properties.angularVelocity.x.toFixed(2);
|
||||
elAngularVelocityY.value = properties.angularVelocity.y.toFixed(2);
|
||||
elAngularVelocityZ.value = properties.angularVelocity.z.toFixed(2);
|
||||
elAngularDamping.value = properties.angularDamping.toFixed(2);
|
||||
|
||||
elGravityX.value = properties.gravity.x.toFixed(2);
|
||||
elGravityY.value = properties.gravity.y.toFixed(2);
|
||||
elGravityZ.value = properties.gravity.z.toFixed(2);
|
||||
|
||||
elMass.value = properties.mass.toFixed(2);
|
||||
elIgnoreForCollisions.checked = properties.ignoreForCollisions;
|
||||
elCollisionsWillMove.checked = properties.collisionsWillMove;
|
||||
elLifetime.value = properties.lifetime;
|
||||
|
||||
if (properties.type != "Box") {
|
||||
elBoxSection.style.display = 'none';
|
||||
} else {
|
||||
elBoxSection.style.display = 'block';
|
||||
|
||||
elBoxColorRed.value = properties.color.red;
|
||||
elBoxColorGreen.value = properties.color.green;
|
||||
elBoxColorBlue.value = properties.color.blue;
|
||||
}
|
||||
|
||||
if (properties.type != "Model") {
|
||||
elModelSection.style.display = 'none';
|
||||
} else {
|
||||
elModelSection.style.display = 'block';
|
||||
|
||||
elModelURL.value = properties.modelURL;
|
||||
elModelAnimationURL.value = properties.animationURL;
|
||||
elModelAnimationPlaying.checked = properties.animationPlaying;
|
||||
elModelAnimationFPS.value = properties.animationFPS;
|
||||
}
|
||||
|
||||
if (properties.type != "Light") {
|
||||
elLightSection.style.display = 'none';
|
||||
} else {
|
||||
elLightSection.style.display = 'block';
|
||||
|
||||
elLightDiffuseRed.value = properties.diffuseColor.red;
|
||||
elLightDiffuseGreen.value = properties.diffuseColor.green;
|
||||
elLightDiffuseBlue.value = properties.diffuseColor.blue;
|
||||
|
||||
elLightAmbientRed.value = properties.ambientColor.red;
|
||||
elLightAmbientGreen.value = properties.ambientColor.green;
|
||||
elLightAmbientBlue.value = properties.ambientColor.blue;
|
||||
|
||||
elLightSpecularRed.value = properties.specularColor.red;
|
||||
elLightSpecularGreen.value = properties.specularColor.green;
|
||||
elLightSpecularBlue.value = properties.specularColor.blue;
|
||||
|
||||
elLightConstantAttenuation.value = properties.constantAttenuation;
|
||||
elLightLinearAttenuation.value = properties.linearAttenuation;
|
||||
elLightQuadraticAttenuation.value = properties.quadraticAttenuation;
|
||||
elLightExponent.value = properties.exponent;
|
||||
elLightCutoff.value = properties.cutoff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked'));
|
||||
elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible'));
|
||||
|
||||
var positionChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'position', elPositionX, elPositionY, elPositionZ);
|
||||
elPositionX.addEventListener('change', positionChangeFunction);
|
||||
elPositionY.addEventListener('change', positionChangeFunction);
|
||||
elPositionZ.addEventListener('change', positionChangeFunction);
|
||||
|
||||
var dimensionsChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'dimensions', elDimensionsX, elDimensionsY, elDimensionsZ);
|
||||
elDimensionsX.addEventListener('change', dimensionsChangeFunction);
|
||||
elDimensionsY.addEventListener('change', dimensionsChangeFunction);
|
||||
elDimensionsZ.addEventListener('change', dimensionsChangeFunction);
|
||||
|
||||
var registrationChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ);
|
||||
elRegistrationX.addEventListener('change', registrationChangeFunction);
|
||||
elRegistrationY.addEventListener('change', registrationChangeFunction);
|
||||
elRegistrationZ.addEventListener('change', registrationChangeFunction);
|
||||
|
||||
var velocityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ);
|
||||
elLinearVelocityX.addEventListener('change', velocityChangeFunction);
|
||||
elLinearVelocityY.addEventListener('change', velocityChangeFunction);
|
||||
elLinearVelocityZ.addEventListener('change', velocityChangeFunction);
|
||||
elLinearDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('damping'));
|
||||
|
||||
var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ);
|
||||
elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping'))
|
||||
|
||||
var gravityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'gravity', elGravityX, elGravityY, elGravityZ);
|
||||
elGravityX.addEventListener('change', gravityChangeFunction);
|
||||
elGravityY.addEventListener('change', gravityChangeFunction);
|
||||
elGravityZ.addEventListener('change', gravityChangeFunction);
|
||||
|
||||
elMass.addEventListener('change', createEmitNumberPropertyUpdateFunction('mass'));
|
||||
elIgnoreForCollisions.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ignoreForCollisions'));
|
||||
elCollisionsWillMove.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionsWillMove'));
|
||||
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
|
||||
|
||||
var boxColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'color', elBoxColorRed, elBoxColorGreen, elBoxColorBlue);
|
||||
elBoxColorRed.addEventListener('change', boxColorChangeFunction);
|
||||
elBoxColorGreen.addEventListener('change', boxColorChangeFunction);
|
||||
elBoxColorBlue.addEventListener('change', boxColorChangeFunction);
|
||||
|
||||
elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight'));
|
||||
|
||||
var lightDiffuseChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'diffuseColor', elLightDiffuseRed, elLightDiffuseGreen, elLightDiffuseBlue);
|
||||
elLightDiffuseRed.addEventListener('change', lightDiffuseChangeFunction);
|
||||
elLightDiffuseGreen.addEventListener('change', lightDiffuseChangeFunction);
|
||||
elLightDiffuseBlue.addEventListener('change', lightDiffuseChangeFunction);
|
||||
|
||||
var lightAmbientChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'ambientColor', elLightAmbientRed, elLightAmbientGreen, elLightAmbientBlue);
|
||||
elLightAmbientRed.addEventListener('change', lightAmbientChangeFunction);
|
||||
elLightAmbientGreen.addEventListener('change', lightAmbientChangeFunction);
|
||||
elLightAmbientBlue.addEventListener('change', lightAmbientChangeFunction);
|
||||
|
||||
var lightSpecularChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'specularColor', elLightSpecularRed, elLightSpecularGreen, elLightSpecularBlue);
|
||||
elLightSpecularRed.addEventListener('change', lightSpecularChangeFunction);
|
||||
elLightSpecularGreen.addEventListener('change', lightSpecularChangeFunction);
|
||||
elLightSpecularBlue.addEventListener('change', lightSpecularChangeFunction);
|
||||
|
||||
elLightConstantAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('constantAttenuation'));
|
||||
elLightLinearAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('linearAttenuation'));
|
||||
elLightQuadraticAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('quadraticAttenuation'));
|
||||
elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent'));
|
||||
elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff'));
|
||||
|
||||
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
|
||||
elModelAnimationURL.addEventListener('change', createEmitTextPropertyUpdateFunction('animationURL'));
|
||||
elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying'));
|
||||
elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS'));
|
||||
elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex'));
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div class="section-header">
|
||||
<label>Entity Properties</label>
|
||||
</div>
|
||||
<div id="properties" class="grid-section">
|
||||
<div class="property-section">
|
||||
<label>Type</label>
|
||||
<span>
|
||||
<label id="property-type"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Locked</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-locked">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Visible</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-visible">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Position</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-pos-x"></input>
|
||||
Y <input class="coord" type='number' id="property-pos-y"></input>
|
||||
Z <input class="coord" type='number' id="property-pos-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Registration</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-reg-x"></input>
|
||||
Y <input class="coord" type='number' id="property-reg-y"></input>
|
||||
Z <input class="coord" type='number' id="property-reg-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Width</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-dim-x"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Height</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-dim-y"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Depth</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-dim-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Linear</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-lvel-x"></input>
|
||||
Y <input class="coord" type='number' id="property-lvel-y"></input>
|
||||
Z <input class="coord" type='number' id="property-lvel-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Linear Damping</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-ldamping"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Angular</label>
|
||||
<span>
|
||||
Pitch <input class="coord" type='number' id="property-avel-x"></input>
|
||||
Roll <input class="coord" type='number' id="property-avel-z"></input>
|
||||
Yaw <input class="coord" type='number' id="property-avel-y"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Angular Damping</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-adamping"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Gravity</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-grav-x"></input>
|
||||
Y <input class="coord" type='number' id="property-grav-y"></input>
|
||||
Z <input class="coord" type='number' id="property-grav-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Mass</label>
|
||||
<span>
|
||||
<input type='number' id="property-mass"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Ignore For Collisions</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-ignore-for-collisions"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Collisions Will Move</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-collisions-will-move"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Lifetime</label>
|
||||
<span>
|
||||
<input type='number' id="property-lifetime"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="box-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Color</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-box-red"></input>
|
||||
Green <input class="coord" type='number' id="property-box-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-box-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="model-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Model URL</label>
|
||||
<span>
|
||||
<input type="text" id="property-model-url"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation URL</label>
|
||||
<span>
|
||||
<input type="text" id="property-model-animation-url"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation Playing</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-model-animation-playing">
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation FPS</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-model-animation-fps"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="light-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Spot Light</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-light-spot-light">
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Diffuse</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-light-diffuse-red"></input>
|
||||
Green <input class="coord" type='number' id="property-light-diffuse-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-light-diffuse-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Ambient</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-light-ambient-red"></input>
|
||||
Green <input class="coord" type='number' id="property-light-ambient-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-light-ambient-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Specular</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-light-specular-red"></input>
|
||||
Green <input class="coord" type='number' id="property-light-specular-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-light-specular-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Constant Attenuation</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-constant-attenuation"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Linear Attenuation</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-linear-attenuation"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Quadratic Attenuation</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-quadratic-attenuation"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Exponent</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-exponent"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Cutoff (degrees)</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-cutoff"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script>
|
||||
function loaded() {
|
||||
var gridColor = { red: 0, green: 0, blue: 0 };
|
||||
|
@ -17,13 +18,14 @@
|
|||
gridOn = document.getElementById("grid-on");
|
||||
snapToGrid = document.getElementById("snap-to-grid");
|
||||
hGridVisible = document.getElementById("horiz-grid-visible");
|
||||
|
||||
bMoveToSelection = document.getElementById("move-to-selection");
|
||||
bMoveToAvatar = document.getElementById("move-to-avatar");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.origin) {
|
||||
|
||||
if (data.origin) {
|
||||
var origin = data.origin;
|
||||
posY.value = origin.y;
|
||||
}
|
||||
|
@ -69,6 +71,19 @@
|
|||
hGridVisible.addEventListener("change", emitUpdate);
|
||||
snapToGrid.addEventListener("change", emitUpdate);
|
||||
|
||||
bMoveToAvatar.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToAvatar",
|
||||
}));
|
||||
});
|
||||
bMoveToSelection.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToSelection",
|
||||
}));
|
||||
});
|
||||
|
||||
var gridColorBox = document.getElementById('grid-color');
|
||||
|
||||
for (var i = 0; i < gridColors.length; i++) {
|
||||
|
@ -88,105 +103,63 @@
|
|||
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
* {
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
background: #DDD;
|
||||
font-family: Sans-Serif;
|
||||
font-size: 12px;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
input {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.input-left {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid black;
|
||||
background: blue;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.color-box.highlight {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: #AAA;
|
||||
border-bottom: 1px solid #CCC;
|
||||
}
|
||||
|
||||
.section-header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.grid-section {
|
||||
border-top: 1px solid #DDD;
|
||||
padding: 4px 0px 4px 20px;
|
||||
background: #DDD;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div class="section-header">
|
||||
<input type='checkbox' id="horiz-grid-visible">
|
||||
<label>Horizontal Grid</label>
|
||||
</div>
|
||||
|
||||
<div class="grid-section">
|
||||
|
||||
<label>Snap to grid</label>
|
||||
<div>
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='checkbox' id="snap-to-grid">
|
||||
<div class="property-section">
|
||||
<label>Visible</label>
|
||||
<span>
|
||||
<input type='checkbox' id="horiz-grid-visible">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Position (Y Axis)</label>
|
||||
<div id="horizontal-position">
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='number' id="horiz-y" class="number" value="0.0" step="0.1"></input>
|
||||
<div class="property-section">
|
||||
<label>Snap to grid</label>
|
||||
<span>
|
||||
<input type='checkbox' id="snap-to-grid">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Minor Grid Size</label>
|
||||
<div>
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='number' id="minor-spacing" min="0" step="0.01", ></input>
|
||||
<div id="horizontal-position" class="property-section">
|
||||
<label>Position (Y Axis)</label>
|
||||
<span>
|
||||
<input type='number' id="horiz-y" class="number" value="0.0" step="0.1"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Major Grid Every</label>
|
||||
<div>
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='number' id="major-spacing" min="2" step="1", ></input>
|
||||
<div class="property-section">
|
||||
<label>Minor Grid Size</label>
|
||||
<span>
|
||||
<input type='number' id="minor-spacing" min="0" step="0.01", ></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Grid Color</label>
|
||||
<div id="grid-colors">
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Major Grid Every</label>
|
||||
<span>
|
||||
<input type='number' id="major-spacing" min="2" step="1", ></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Grid Color</label>
|
||||
<span id="grid-colors"></span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<span>
|
||||
<input type="button" id="move-to-selection" value="Move to Selection">
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<span>
|
||||
<input type="button" id="move-to-avatar" value="Move to Avatar">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
95
examples/html/style.css
Normal file
95
examples/html/style.css
Normal file
|
@ -0,0 +1,95 @@
|
|||
* {
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
background-color: #efefef;
|
||||
font-family: Sans-Serif;
|
||||
font-size: 12px;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
input {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.input-left {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid black;
|
||||
margin: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.color-box.highlight {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: #AAA;
|
||||
border-bottom: 1px solid #CCC;
|
||||
background-color: #333333;
|
||||
color: #999;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.section-header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.multi-property-section {
|
||||
}
|
||||
.property-section {
|
||||
display: block;
|
||||
margin: 10 10;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.property-section label {
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.property-section span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.grid-section {
|
||||
border-top: 1px solid #DDD;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
cursor: pointer;
|
||||
background-color: #608e96;
|
||||
border-color: #608e96;
|
||||
border-radius: 5px;
|
||||
padding: 5px 10px;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin: 0 2px;
|
||||
margin-top: 5px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
input.coord {
|
||||
width: 6em;
|
||||
height: 2em;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
Script.include("libraries/globals.js");
|
||||
|
||||
var sound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/220Sine.wav");
|
||||
var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/220Sine.wav");
|
||||
|
||||
var soundPlaying = false;
|
||||
|
||||
|
|
|
@ -17,12 +17,16 @@ var leapHands = (function () {
|
|||
LEAP_ON_HMD_MENU_ITEM = "Leap Motion on HMD",
|
||||
LEAP_OFFSET = 0.019, // Thickness of Leap Motion plus HMD clip
|
||||
HMD_OFFSET = 0.070, // Eyeballs to front surface of Oculus DK2 TODO: Confirm and make depend on device and eye relief
|
||||
hasHandAndWristJoints,
|
||||
handToWristOffset = [], // For avatars without a wrist joint we control an estimate of a proper hand joint position
|
||||
HAND_OFFSET = 0.4, // Relative distance of wrist to hand versus wrist to index finger knuckle
|
||||
hands,
|
||||
wrists,
|
||||
NUM_HANDS = 2, // 0 = left; 1 = right
|
||||
fingers,
|
||||
NUM_FINGERS = 5, // 0 = thumb; ...; 4 = pinky
|
||||
THUMB = 0,
|
||||
MIDDLE_FINGER = 2,
|
||||
NUM_FINGER_JOINTS = 3, // 0 = metacarpal(hand)-proximal(finger) joint; ...; 2 = intermediate-distal joint
|
||||
MAX_HAND_INACTIVE_COUNT = 20,
|
||||
calibrationStatus,
|
||||
|
@ -123,30 +127,41 @@ var leapHands = (function () {
|
|||
|
||||
function finishCalibration() {
|
||||
var avatarPosition,
|
||||
avatarOrientation,
|
||||
avatarHandPosition,
|
||||
handPosition,
|
||||
middleFingerPosition,
|
||||
leapHandHeight,
|
||||
h;
|
||||
|
||||
if (hands[0].controller.isActive() && hands[1].controller.isActive()) {
|
||||
leapHandHeight = (hands[0].controller.getAbsTranslation().y + hands[1].controller.getAbsTranslation().y) / 2.0;
|
||||
} else {
|
||||
calibrationStatus = UNCALIBRATED;
|
||||
return;
|
||||
if (!isOnHMD) {
|
||||
if (hands[0].controller.isActive() && hands[1].controller.isActive()) {
|
||||
leapHandHeight = (hands[0].controller.getAbsTranslation().y + hands[1].controller.getAbsTranslation().y) / 2.0;
|
||||
} else {
|
||||
calibrationStatus = UNCALIBRATED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
avatarPosition = MyAvatar.position;
|
||||
avatarOrientation = MyAvatar.orientation;
|
||||
|
||||
for (h = 0; h < NUM_HANDS; h += 1) {
|
||||
avatarHandPosition = MyAvatar.getJointPosition(hands[h].jointName);
|
||||
hands[h].zeroPosition = {
|
||||
x: avatarHandPosition.x - avatarPosition.x,
|
||||
y: avatarHandPosition.y - avatarPosition.y,
|
||||
z: avatarPosition.z - avatarHandPosition.z
|
||||
};
|
||||
hands[h].zeroPosition = Vec3.multiplyQbyV(MyAvatar.orientation, hands[h].zeroPosition);
|
||||
hands[h].zeroPosition.y = hands[h].zeroPosition.y - leapHandHeight;
|
||||
handPosition = MyAvatar.getJointPosition(hands[h].jointName);
|
||||
if (!hasHandAndWristJoints) {
|
||||
middleFingerPosition = MyAvatar.getJointPosition(fingers[h][MIDDLE_FINGER][0].jointName);
|
||||
handToWristOffset[h] = Vec3.multiply(Vec3.subtract(handPosition, middleFingerPosition), 1.0 - HAND_OFFSET);
|
||||
}
|
||||
|
||||
if (isOnHMD) {
|
||||
// Offset of Leap Motion origin from physical eye position
|
||||
hands[h].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET };
|
||||
} else {
|
||||
hands[h].zeroPosition = {
|
||||
x: handPosition.x - avatarPosition.x,
|
||||
y: handPosition.y - avatarPosition.y,
|
||||
z: avatarPosition.z - handPosition.z
|
||||
};
|
||||
hands[h].zeroPosition = Vec3.multiplyQbyV(MyAvatar.orientation, hands[h].zeroPosition);
|
||||
hands[h].zeroPosition.y = hands[h].zeroPosition.y - leapHandHeight;
|
||||
}
|
||||
}
|
||||
|
||||
MyAvatar.clearJointData("LeftHand");
|
||||
|
@ -161,6 +176,8 @@ var leapHands = (function () {
|
|||
}
|
||||
|
||||
function calibrate() {
|
||||
var jointNames,
|
||||
i;
|
||||
|
||||
calibrationStatus = CALIBRATING;
|
||||
|
||||
|
@ -168,6 +185,13 @@ var leapHands = (function () {
|
|||
avatarFaceModelURL = MyAvatar.faceModelURL;
|
||||
avatarSkeletonModelURL = MyAvatar.skeletonModelURL;
|
||||
|
||||
// Does this skeleton have both wrist and hand joints?
|
||||
hasHandAndWristJoints = false;
|
||||
jointNames = MyAvatar.getJointNames();
|
||||
for (i = 0; i < jointNames.length; i += 1) {
|
||||
hasHandAndWristJoints = hasHandAndWristJoints || jointNames[i].toLowerCase() === "leftwrist";
|
||||
}
|
||||
|
||||
// Set avatar arms vertical, forearms horizontal, as "zero" position for calibration
|
||||
MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, -90.0));
|
||||
MyAvatar.setJointData("LeftForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0));
|
||||
|
@ -176,6 +200,7 @@ var leapHands = (function () {
|
|||
MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0));
|
||||
MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0));
|
||||
|
||||
|
||||
// Wait for arms to assume their positions before calculating
|
||||
Script.setTimeout(finishCalibration, CALIBRATION_TIME);
|
||||
}
|
||||
|
@ -195,37 +220,34 @@ var leapHands = (function () {
|
|||
|
||||
function setIsOnHMD() {
|
||||
isOnHMD = Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM);
|
||||
if (isOnHMD) {
|
||||
print("Leap Motion: Is on HMD");
|
||||
|
||||
// Offset of Leap Motion origin from physical eye position
|
||||
hands[0].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET };
|
||||
hands[1].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET };
|
||||
|
||||
calibrationStatus = CALIBRATED;
|
||||
} else {
|
||||
print("Leap Motion: Is on desk");
|
||||
calibrationStatus = UNCALIBRATED;
|
||||
}
|
||||
print("Leap Motion: " + (isOnHMD ? "Is on HMD" : "Is on desk"));
|
||||
}
|
||||
|
||||
function checkSettings() {
|
||||
// There is no "scale changed" event so we need check periodically.
|
||||
if (!isOnHMD && calibrationStatus > UNCALIBRATED && (MyAvatar.scale !== avatarScale
|
||||
if (calibrationStatus > UNCALIBRATED && (MyAvatar.scale !== avatarScale
|
||||
|| MyAvatar.faceModelURL !== avatarFaceModelURL
|
||||
|| MyAvatar.skeletonModelURL !== avatarSkeletonModelURL)) {
|
||||
print("Leap Motion: Recalibrate because avatar body or scale changed");
|
||||
|| MyAvatar.skeletonModelURL !== avatarSkeletonModelURL
|
||||
|| Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM) !== isOnHMD)) {
|
||||
print("Leap Motion: Recalibrate...");
|
||||
calibrationStatus = UNCALIBRATED;
|
||||
}
|
||||
|
||||
// There is a "menu changed" event but we may as well check here.
|
||||
if (isOnHMD !== Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM)) {
|
||||
setIsOnHMD();
|
||||
}
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
|
||||
wrists = [
|
||||
{
|
||||
jointName: "LeftWrist",
|
||||
controller: Controller.createInputController("Spatial", "joint_L_wrist")
|
||||
},
|
||||
{
|
||||
jointName: "RightWrist",
|
||||
controller: Controller.createInputController("Spatial", "joint_R_wrist")
|
||||
}
|
||||
];
|
||||
|
||||
hands = [
|
||||
{
|
||||
jointName: "LeftHand",
|
||||
|
@ -239,11 +261,6 @@ var leapHands = (function () {
|
|||
}
|
||||
];
|
||||
|
||||
wrists = [
|
||||
{ controller: Controller.createInputController("Spatial", "joint_L_wrist") },
|
||||
{ controller: Controller.createInputController("Spatial", "joint_R_wrist") }
|
||||
];
|
||||
|
||||
// The Leap controller's first joint is the hand-metacarpal joint but this joint's data is not used because it's too
|
||||
// dependent on the model skeleton exactly matching the Leap skeleton; using just the second and subsequent joints
|
||||
// seems to work better over all.
|
||||
|
@ -306,6 +323,8 @@ var leapHands = (function () {
|
|||
setIsOnHMD();
|
||||
|
||||
settingsTimer = Script.setInterval(checkSettings, 2000);
|
||||
|
||||
calibrationStatus = UNCALIBRATED;
|
||||
}
|
||||
|
||||
function moveHands() {
|
||||
|
@ -314,6 +333,7 @@ var leapHands = (function () {
|
|||
j,
|
||||
side,
|
||||
handOffset,
|
||||
wristOffset,
|
||||
handRotation,
|
||||
locRotation,
|
||||
cameraOrientation,
|
||||
|
@ -330,10 +350,18 @@ var leapHands = (function () {
|
|||
}
|
||||
|
||||
// Hand position ...
|
||||
handOffset = hands[h].controller.getAbsTranslation();
|
||||
handRotation = hands[h].controller.getAbsRotation();
|
||||
|
||||
if (isOnHMD) {
|
||||
|
||||
// Adjust to control wrist position if "hand" joint is at wrist ...
|
||||
if (!hasHandAndWristJoints) {
|
||||
wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]);
|
||||
handOffset = Vec3.sum(handOffset, wristOffset);
|
||||
}
|
||||
|
||||
// Hand offset in camera coordinates ...
|
||||
handOffset = hands[h].controller.getAbsTranslation();
|
||||
handOffset = {
|
||||
x: hands[h].zeroPosition.x - handOffset.x,
|
||||
y: hands[h].zeroPosition.y - handOffset.z,
|
||||
|
@ -353,7 +381,6 @@ var leapHands = (function () {
|
|||
handOffset.x = -handOffset.x;
|
||||
|
||||
// Hand rotation in camera coordinates ...
|
||||
handRotation = wrists[h].controller.getAbsRotation();
|
||||
handRotation = {
|
||||
x: handRotation.z,
|
||||
y: handRotation.y,
|
||||
|
@ -361,6 +388,7 @@ var leapHands = (function () {
|
|||
w: handRotation.w
|
||||
};
|
||||
|
||||
// Hand rotation in avatar coordinates ...
|
||||
if (h === 0) {
|
||||
handRotation.x = -handRotation.x;
|
||||
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation);
|
||||
|
@ -371,7 +399,6 @@ var leapHands = (function () {
|
|||
handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 0, z: 1 }), handRotation);
|
||||
}
|
||||
|
||||
// Hand rotation in avatar coordinates ...
|
||||
cameraOrientation.x = -cameraOrientation.x;
|
||||
cameraOrientation.z = -cameraOrientation.z;
|
||||
handRotation = Quat.multiply(cameraOrientation, handRotation);
|
||||
|
@ -379,14 +406,20 @@ var leapHands = (function () {
|
|||
|
||||
} else {
|
||||
|
||||
handOffset = hands[h].controller.getAbsTranslation();
|
||||
// Adjust to control wrist position if "hand" joint is at wrist ...
|
||||
if (!hasHandAndWristJoints) {
|
||||
wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]);
|
||||
handOffset = Vec3.sum(handOffset, wristOffset);
|
||||
}
|
||||
|
||||
// Hand offset in camera coordinates ...
|
||||
handOffset = {
|
||||
x: -handOffset.x,
|
||||
y: hands[h].zeroPosition.y + handOffset.y,
|
||||
z: hands[h].zeroPosition.z - handOffset.z
|
||||
};
|
||||
|
||||
handRotation = wrists[h].controller.getAbsRotation();
|
||||
// Hand rotation in camera coordinates ...
|
||||
handRotation = {
|
||||
x: handRotation.z,
|
||||
y: handRotation.y,
|
||||
|
@ -394,6 +427,7 @@ var leapHands = (function () {
|
|||
w: handRotation.w
|
||||
};
|
||||
|
||||
// Hand rotation in avatar coordinates ...
|
||||
if (h === 0) {
|
||||
handRotation.x = -handRotation.x;
|
||||
handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }),
|
||||
|
@ -405,9 +439,10 @@ var leapHands = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
// Set hand position and orientation ...
|
||||
MyAvatar.setJointModelPositionAndOrientation(hands[h].jointName, handOffset, handRotation, true);
|
||||
|
||||
// Finger joints ...
|
||||
// Set finger joints ...
|
||||
for (i = 0; i < NUM_FINGERS; i += 1) {
|
||||
for (j = 0; j < NUM_FINGER_JOINTS; j += 1) {
|
||||
if (fingers[h][i][j].controller !== null) {
|
||||
|
|
|
@ -23,12 +23,13 @@ SelectionManager = (function() {
|
|||
|
||||
that.savedProperties = {};
|
||||
|
||||
that.eventListener = null;
|
||||
that.selections = [];
|
||||
// These are selections that don't have a known ID yet
|
||||
that.pendingSelections = [];
|
||||
var pendingSelectionTimer = null;
|
||||
|
||||
var listeners = [];
|
||||
|
||||
that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||
that.localPosition = { x: 0, y: 0, z: 0 };
|
||||
that.localDimensions = { x: 0, y: 0, z: 0 };
|
||||
|
@ -46,8 +47,8 @@ SelectionManager = (function() {
|
|||
}
|
||||
};
|
||||
|
||||
that.setEventListener = function(func) {
|
||||
that.eventListener = func;
|
||||
that.addEventListener = function(func) {
|
||||
listeners.push(func);
|
||||
};
|
||||
|
||||
that.hasSelection = function() {
|
||||
|
@ -187,8 +188,12 @@ SelectionManager = (function() {
|
|||
SelectionDisplay.setSpaceMode(SPACE_WORLD);
|
||||
}
|
||||
|
||||
if (that.eventListener) {
|
||||
that.eventListener();
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
try {
|
||||
listeners[i]();
|
||||
} catch (e) {
|
||||
print("got exception");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ Grid = function(opts) {
|
|||
that.getMajorIncrement = function() { return minorGridSpacing * majorGridEvery; };
|
||||
|
||||
that.visible = false;
|
||||
that.enabled = false;
|
||||
|
||||
that.getOrigin = function() {
|
||||
return origin;
|
||||
|
@ -38,6 +39,11 @@ Grid = function(opts) {
|
|||
|
||||
that.getSnapToGrid = function() { return snapToGrid; };
|
||||
|
||||
that.setEnabled = function(enabled) {
|
||||
that.enabled = enabled;
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
that.setVisible = function(visible, noUpdate) {
|
||||
that.visible = visible;
|
||||
updateGrid();
|
||||
|
@ -127,7 +133,7 @@ Grid = function(opts) {
|
|||
function updateGrid() {
|
||||
Overlays.editOverlay(gridOverlay, {
|
||||
position: { x: origin.y, y: origin.y, z: -origin.y },
|
||||
visible: that.visible,
|
||||
visible: that.visible && that.enabled,
|
||||
minorGridWidth: minorGridSpacing,
|
||||
majorGridEvery: majorGridEvery,
|
||||
color: gridColor,
|
||||
|
@ -159,7 +165,7 @@ GridTool = function(opts) {
|
|||
var listeners = [];
|
||||
|
||||
var url = Script.resolvePath('html/gridControls.html');
|
||||
var webView = new WebWindow(url, 200, 280);
|
||||
var webView = new WebWindow('Grid', url, 200, 280);
|
||||
|
||||
horizontalGrid.addListener(function(data) {
|
||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||
|
@ -174,6 +180,15 @@ GridTool = function(opts) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -335,12 +335,12 @@ walkAssets = (function () {
|
|||
|
||||
// read in the sounds
|
||||
var _footsteps = [];
|
||||
_footsteps.push(new Sound(_pathToSounds+"FootstepW2Left-12db.wav"));
|
||||
_footsteps.push(new Sound(_pathToSounds+"FootstepW2Right-12db.wav"));
|
||||
_footsteps.push(new Sound(_pathToSounds+"FootstepW3Left-12db.wav"));
|
||||
_footsteps.push(new Sound(_pathToSounds+"FootstepW3Right-12db.wav"));
|
||||
_footsteps.push(new Sound(_pathToSounds+"FootstepW5Left-12db.wav"));
|
||||
_footsteps.push(new Sound(_pathToSounds+"FootstepW5Right-12db.wav"));
|
||||
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Left-12db.wav"));
|
||||
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Right-12db.wav"));
|
||||
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Left-12db.wav"));
|
||||
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Right-12db.wav"));
|
||||
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Left-12db.wav"));
|
||||
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Right-12db.wav"));
|
||||
|
||||
// load the animation datafiles
|
||||
Script.include(pathToAssets+"animations/dd-female-standard-walk-animation.js");
|
||||
|
|
|
@ -39,11 +39,11 @@ var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8};
|
|||
|
||||
var HELMET_ATTACHMENT_URL = HIFI_PUBLIC_BUCKET + "models/attachments/IronManMaskOnly.fbx"
|
||||
|
||||
var droneSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.raw")
|
||||
var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.raw")
|
||||
var currentDrone = null;
|
||||
|
||||
var latinSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.raw")
|
||||
var elevatorSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.raw")
|
||||
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.raw")
|
||||
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.raw")
|
||||
var currentMusak = null;
|
||||
|
||||
function reticlePosition() {
|
||||
|
|
|
@ -39,7 +39,7 @@ Script.include("libraries/gridTool.js");
|
|||
var grid = Grid();
|
||||
gridTool = GridTool({ horizontalGrid: grid });
|
||||
|
||||
selectionManager.setEventListener(selectionDisplay.updateHandles);
|
||||
selectionManager.addEventListener(selectionDisplay.updateHandles);
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||
|
@ -55,13 +55,11 @@ var wantEntityGlow = false;
|
|||
var SPAWN_DISTANCE = 1;
|
||||
var DEFAULT_DIMENSION = 0.20;
|
||||
|
||||
var MENU_GRID_TOOL_ENABLED = 'Grid Tool';
|
||||
var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool";
|
||||
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
|
||||
|
||||
var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled";
|
||||
var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
|
||||
var SETTING_GRID_TOOL_ENABLED = 'GridToolEnabled';
|
||||
|
||||
var modelURLs = [
|
||||
HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx",
|
||||
|
@ -89,12 +87,12 @@ var toolBar = (function () {
|
|||
browseModelsButton,
|
||||
loadURLMenuItem,
|
||||
loadFileMenuItem,
|
||||
menuItemWidth = 125,
|
||||
menuItemWidth,
|
||||
menuItemOffset,
|
||||
menuItemHeight,
|
||||
menuItemMargin = 5,
|
||||
menuTextColor = { red: 255, green: 255, blue: 255 },
|
||||
menuBackgoundColor = { red: 18, green: 66, blue: 66 };
|
||||
menuBackgroundColor = { red: 18, green: 66, blue: 66 };
|
||||
|
||||
function initialize() {
|
||||
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL);
|
||||
|
@ -131,9 +129,8 @@ var toolBar = (function () {
|
|||
loadURLMenuItem = Overlays.addOverlay("text", {
|
||||
x: newModelButton.x - menuItemWidth,
|
||||
y: newModelButton.y + menuItemOffset,
|
||||
width: menuItemWidth,
|
||||
height: menuItemHeight,
|
||||
backgroundColor: menuBackgoundColor,
|
||||
backgroundColor: menuBackgroundColor,
|
||||
topMargin: menuItemMargin,
|
||||
text: "Model URL",
|
||||
alpha: 0.9,
|
||||
|
@ -143,15 +140,19 @@ var toolBar = (function () {
|
|||
loadFileMenuItem = Overlays.addOverlay("text", {
|
||||
x: newModelButton.x - menuItemWidth,
|
||||
y: newModelButton.y + menuItemOffset + menuItemHeight,
|
||||
width: menuItemWidth,
|
||||
height: menuItemHeight,
|
||||
backgroundColor: menuBackgoundColor,
|
||||
backgroundColor: menuBackgroundColor,
|
||||
topMargin: menuItemMargin,
|
||||
text: "Model File",
|
||||
alpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
menuItemWidth = Math.max(Overlays.textWidth(loadURLMenuItem, "Model URL"),
|
||||
Overlays.textWidth(loadFileMenuItem, "Model File")) + 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 },
|
||||
|
@ -269,11 +270,15 @@ var toolBar = (function () {
|
|||
isActive = !isActive;
|
||||
if (!isActive) {
|
||||
gridTool.setVisible(false);
|
||||
grid.setEnabled(false);
|
||||
propertiesTool.setVisible(false);
|
||||
selectionManager.clearSelections();
|
||||
cameraManager.disable();
|
||||
} else {
|
||||
cameraManager.enable();
|
||||
gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED));
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -605,10 +610,6 @@ function setupModelMenus() {
|
|||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" });
|
||||
Menu.addMenuItem({ menuName: "Developer", menuItemName: "Debug Ryans Rotation Problems", isCheckable: true });
|
||||
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_GRID_TOOL_ENABLED, afterItem: "Edit Entities Help...", isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_GRID_TOOL_ENABLED) == 'true'});
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_INSPECT_TOOL_ENABLED, afterItem: MENU_GRID_TOOL_ENABLED,
|
||||
isCheckable: true, isChecked: Settings.getValue(SETTING_INSPECT_TOOL_ENABLED) == "true" });
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED,
|
||||
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
|
||||
}
|
||||
|
@ -633,8 +634,6 @@ function cleanupModelMenus() {
|
|||
Menu.removeMenuItem("File", "Import Models");
|
||||
Menu.removeMenuItem("Developer", "Debug Ryans Rotation Problems");
|
||||
|
||||
Settings.setValue(SETTING_GRID_TOOL_ENABLED, Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED));
|
||||
Menu.removeMenuItem("View", MENU_GRID_TOOL_ENABLED);
|
||||
Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED);
|
||||
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
|
||||
}
|
||||
|
@ -746,10 +745,6 @@ function handeMenuEvent(menuItem) {
|
|||
}
|
||||
} else if (menuItem == "Import Models") {
|
||||
modelImporter.doImport();
|
||||
} else if (menuItem == MENU_GRID_TOOL_ENABLED) {
|
||||
if (isActive) {
|
||||
gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED));
|
||||
}
|
||||
}
|
||||
tooltip.show(false);
|
||||
}
|
||||
|
@ -908,3 +903,43 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
|
|||
}
|
||||
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
|
||||
}
|
||||
|
||||
PropertiesTool = function(opts) {
|
||||
var that = {};
|
||||
|
||||
var url = Script.resolvePath('html/entityProperties.html');
|
||||
var webView = new WebWindow('Entity Properties', url, 200, 280);
|
||||
|
||||
var visible = false;
|
||||
|
||||
webView.setVisible(visible);
|
||||
|
||||
that.setVisible = function(newVisible) {
|
||||
visible = newVisible;
|
||||
webView.setVisible(visible);
|
||||
};
|
||||
|
||||
selectionManager.addEventListener(function() {
|
||||
data = {
|
||||
type: 'update',
|
||||
};
|
||||
if (selectionManager.hasSelection()) {
|
||||
data.properties = Entities.getEntityProperties(selectionManager.selections[0]);
|
||||
}
|
||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||
});
|
||||
|
||||
webView.eventBridge.webEventReceived.connect(function(data) {
|
||||
print(data);
|
||||
data = JSON.parse(data);
|
||||
if (data.type == "update") {
|
||||
Entities.editEntity(selectionManager.selections[0], data.properties);
|
||||
selectionManager._update();
|
||||
}
|
||||
});
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
propertiesTool = PropertiesTool();
|
||||
|
||||
|
|
|
@ -167,6 +167,51 @@ var clipboardPreview = Overlays.addOverlay("clipboard", {
|
|||
visible: true
|
||||
});
|
||||
|
||||
// Demonstrate retrieving overlay properties
|
||||
print("Text overlay text property value =\n" + Overlays.getProperty(text, "text"));
|
||||
print("Text overlay alpha =\n" + Overlays.getProperty(text, "alpha"));
|
||||
print("Text overlay visible =\n" + Overlays.getProperty(text, "visible"));
|
||||
print("Text overlay font size =\n" + Overlays.getProperty(text, "font").size);
|
||||
print("Text overlay anchor =\n" + Overlays.getProperty(text, "anchor"));
|
||||
print("Text overlay unknown property value =\n" + Overlays.getProperty(text, "unknown")); // value = undefined
|
||||
var sliderBounds = Overlays.getProperty(slider, "bounds");
|
||||
print("Slider overlay bounds =\n"
|
||||
+ "x: " + sliderBounds.x + "\n"
|
||||
+ "y: " + sliderBounds.y + "\n"
|
||||
+ "width: " + sliderBounds.width + "\n"
|
||||
+ "height: " + sliderBounds.height
|
||||
);
|
||||
|
||||
var cubePosition = Overlays.getProperty(cube, "position");
|
||||
print("Cube overlay position =\n"
|
||||
+ "x: " + cubePosition.x + "\n"
|
||||
+ "y: " + cubePosition.y + "\n"
|
||||
+ "z: " + cubePosition.z
|
||||
);
|
||||
var cubeColor = Overlays.getProperty(cube, "color");
|
||||
print("Cube overlay color =\n"
|
||||
+ "red: " + cubeColor.red + "\n"
|
||||
+ "green: " + cubeColor.green + "\n"
|
||||
+ "blue: " + cubeColor.blue
|
||||
);
|
||||
|
||||
// This model overlay example causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL()
|
||||
//var modelOverlayProperties = {
|
||||
// textures: {
|
||||
// filename1: HIFI_PUBLIC_BUCKET + "images/testing-swatches.svg",
|
||||
// filename2: HIFI_PUBLIC_BUCKET + "images/hifi-interface-tools.svg"
|
||||
// }
|
||||
//}
|
||||
//var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties);
|
||||
//var textures = Overlays.getProperty(modelOverlay, "textures");
|
||||
//var textureValues = "";
|
||||
//for (key in textures) {
|
||||
// textureValues += "\n" + key + ": " + textures[key];
|
||||
//}
|
||||
//print("Model overlay textures =" + textureValues);
|
||||
//Overlays.deleteOverlay(modelOverlay);
|
||||
|
||||
print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined
|
||||
|
||||
// When our script shuts down, we should clean up all of our overlays
|
||||
function scriptEnding() {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
Script.include("libraries/globals.js");
|
||||
|
||||
// First, load a sample sound from a URL
|
||||
var bird = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Animals/bushtit_1.raw");
|
||||
var bird = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Animals/bushtit_1.raw");
|
||||
|
||||
function maybePlaySound(deltaTime) {
|
||||
if (Math.random() < 0.01) {
|
||||
|
|
|
@ -15,9 +15,9 @@ Script.include("libraries/globals.js");
|
|||
|
||||
// A few sample files you may want to try:
|
||||
|
||||
var sound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+A.raw");
|
||||
//var sound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/220Sine.wav");
|
||||
//var sound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Cocktail+Party+Snippets/Bandcamp.wav");
|
||||
var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guitars/Guitar+-+Nylon+A.raw");
|
||||
//var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/220Sine.wav");
|
||||
//var sound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Cocktail+Party+Snippets/Bandcamp.wav");
|
||||
|
||||
var soundPlaying = false;
|
||||
var options = {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
Script.include("libraries/globals.js");
|
||||
|
||||
var soundClip = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Voxels/voxel create 3.raw");
|
||||
var soundClip = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Voxels/voxel create 3.raw");
|
||||
|
||||
var currentTime = 1.570079; // pi/2
|
||||
var deltaTime = 0.05;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
Script.include("libraries/globals.js");
|
||||
|
||||
var soundClip = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Cocktail%20Party%20Snippets/Walken1.wav");
|
||||
var soundClip = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Cocktail%20Party%20Snippets/Walken1.wav");
|
||||
|
||||
function playSound() {
|
||||
Audio.playSound(soundClip, {
|
||||
|
|
|
@ -23,7 +23,7 @@ var audioOptions = {
|
|||
|
||||
var injector = null;
|
||||
|
||||
var sound = new Sound(soundURL, audioOptions.isStereo);
|
||||
var sound = SoundCache.getSound(soundURL, audioOptions.isStereo);
|
||||
|
||||
var entity = null;
|
||||
var properties = null;
|
||||
|
|
|
@ -84,13 +84,13 @@ var missileFired = false;
|
|||
var myMissile;
|
||||
|
||||
// sounds
|
||||
var hitSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw");
|
||||
var shootSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw");
|
||||
var hitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw");
|
||||
var shootSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw");
|
||||
var moveSounds = new Array();
|
||||
moveSounds[0] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo1.raw");
|
||||
moveSounds[1] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo2.raw");
|
||||
moveSounds[2] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo3.raw");
|
||||
moveSounds[3] = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo4.raw");
|
||||
moveSounds[0] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo1.raw");
|
||||
moveSounds[1] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo2.raw");
|
||||
moveSounds[2] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo3.raw");
|
||||
moveSounds[3] = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/Lo4.raw");
|
||||
var currentMoveSound = 0;
|
||||
var numberOfSounds = 4;
|
||||
var stepsPerSound = invaderStepsPerCycle / numberOfSounds;
|
||||
|
|
|
@ -39,9 +39,9 @@ var rightBallAlreadyInHand = false;
|
|||
var leftHandEntity;
|
||||
var rightHandEntity;
|
||||
|
||||
var newSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
|
||||
var catchSound = new Sound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
|
||||
var throwSound = new Sound(HIFI_PUBLIC_BUCKET + "sounds/Switches%20and%20sliders/slider%20-%20whoosh1.raw");
|
||||
var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
|
||||
var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
|
||||
var throwSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Switches%20and%20sliders/slider%20-%20whoosh1.raw");
|
||||
var targetRadius = 1.0;
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <SoundCache.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <UUID.h>
|
||||
|
||||
|
@ -123,7 +124,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message);
|
||||
|
||||
if (!logMessage.isEmpty()) {
|
||||
Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage));
|
||||
Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage + "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +161,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_lastQueriedViewFrustum(),
|
||||
_lastQueriedTime(usecTimestampNow()),
|
||||
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
||||
_viewTransform(new gpu::Transform()),
|
||||
_viewTransform(),
|
||||
_scaleMirror(1.0f),
|
||||
_rotateMirror(0.0f),
|
||||
_raiseMirror(0.0f),
|
||||
|
@ -372,6 +373,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
// enable mouse tracking; otherwise, we only get drag events
|
||||
_glWidget->setMouseTracking(true);
|
||||
|
||||
_toolWindow = new ToolWindow();
|
||||
_toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint);
|
||||
_toolWindow->setWindowTitle("Tools");
|
||||
|
||||
// initialization continues in initializeGL when OpenGL context is ready
|
||||
|
||||
// Tell our voxel edit sender about our known jurisdictions
|
||||
|
@ -2911,13 +2916,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
// Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation
|
||||
// the viewTransofmr object is updatded with the correct values and saved,
|
||||
// this is what is used for rendering the Entities and avatars
|
||||
gpu::Transform viewTransform;
|
||||
Transform viewTransform;
|
||||
viewTransform.setTranslation(whichCamera.getPosition());
|
||||
viewTransform.setRotation(rotation);
|
||||
viewTransform.postTranslate(eyeOffsetPos);
|
||||
viewTransform.postRotate(eyeOffsetOrient);
|
||||
if (whichCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
viewTransform.setScale(gpu::Transform::Vec3(-1.0f, 1.0f, 1.0f));
|
||||
viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
setViewTransform(viewTransform);
|
||||
|
||||
|
@ -3117,8 +3122,8 @@ void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTransl
|
|||
_viewMatrixTranslation = viewMatrixTranslation;
|
||||
}
|
||||
|
||||
void Application::setViewTransform(const gpu::Transform& view) {
|
||||
(*_viewTransform) = view;
|
||||
void Application::setViewTransform(const Transform& view) {
|
||||
_viewTransform = view;
|
||||
}
|
||||
|
||||
void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {
|
||||
|
@ -3901,7 +3906,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool)));
|
||||
|
||||
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
||||
qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue);
|
||||
qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue);
|
||||
qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue,
|
||||
RayToOverlayIntersectionResultFromScriptValue);
|
||||
|
||||
QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance());
|
||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
|
@ -3916,6 +3923,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);
|
||||
scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector);
|
||||
scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels);
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#include "ui/overlays/Overlays.h"
|
||||
#include "ui/ApplicationOverlay.h"
|
||||
#include "ui/RunningScriptsWidget.h"
|
||||
#include "ui/ToolWindow.h"
|
||||
#include "ui/VoxelImportDialog.h"
|
||||
#include "voxels/VoxelFade.h"
|
||||
#include "voxels/VoxelHideShowThread.h"
|
||||
|
@ -232,8 +233,8 @@ public:
|
|||
const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; }
|
||||
void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; }
|
||||
|
||||
const gpu::TransformPointer& getViewTransform() const { return _viewTransform; }
|
||||
void setViewTransform(const gpu::Transform& view);
|
||||
const Transform& getViewTransform() const { return _viewTransform; }
|
||||
void setViewTransform(const Transform& view);
|
||||
|
||||
/// if you need to access the application settings, use lockSettings()/unlockSettings()
|
||||
QSettings* lockSettings() { _settingsMutex.lock(); return _settings; }
|
||||
|
@ -246,6 +247,8 @@ public:
|
|||
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
||||
void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
|
||||
|
||||
ToolWindow* getToolWindow() { return _toolWindow ; }
|
||||
|
||||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||
AnimationCache* getAnimationCache() { return &_animationCache; }
|
||||
TextureCache* getTextureCache() { return &_textureCache; }
|
||||
|
@ -459,6 +462,8 @@ private:
|
|||
MainWindow* _window;
|
||||
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
||||
|
||||
ToolWindow* _toolWindow;
|
||||
|
||||
BandwidthMeter _bandwidthMeter;
|
||||
|
||||
QThread* _nodeThread;
|
||||
|
@ -526,7 +531,7 @@ private:
|
|||
QRect _mirrorViewRect;
|
||||
RearMirrorTools* _rearMirrorTools;
|
||||
|
||||
gpu::TransformPointer _viewTransform;
|
||||
Transform _viewTransform;
|
||||
glm::mat4 _untranslatedViewMatrix;
|
||||
glm::vec3 _viewMatrixTranslation;
|
||||
glm::mat4 _projectionMatrix;
|
||||
|
|
|
@ -41,7 +41,7 @@ void FileLogger::addMessage(QString message) {
|
|||
QFile file(_fileName);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
|
||||
QTextStream out(&file);
|
||||
out << message << "\n";
|
||||
out << message;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,6 +247,12 @@ Menu::Menu() :
|
|||
_chatWindow = new ChatWindow(Application::getInstance()->getWindow());
|
||||
#endif
|
||||
|
||||
addActionToQMenuAndActionHash(toolsMenu,
|
||||
MenuOption::ToolWindow,
|
||||
Qt::CTRL | Qt::ALT | Qt::Key_T,
|
||||
this,
|
||||
SLOT(toggleToolWindow()));
|
||||
|
||||
addActionToQMenuAndActionHash(toolsMenu,
|
||||
MenuOption::Console,
|
||||
Qt::CTRL | Qt::ALT | Qt::Key_J,
|
||||
|
@ -1464,6 +1470,11 @@ void Menu::toggleConsole() {
|
|||
_jsConsole->setVisible(!_jsConsole->isVisible());
|
||||
}
|
||||
|
||||
void Menu::toggleToolWindow() {
|
||||
QMainWindow* toolWindow = Application::getInstance()->getToolWindow();
|
||||
toolWindow->setVisible(!toolWindow->isVisible());
|
||||
}
|
||||
|
||||
void Menu::audioMuteToggled() {
|
||||
QAction *muteAction = _actionHash.value(MenuOption::MuteAudio);
|
||||
if (muteAction) {
|
||||
|
|
|
@ -224,6 +224,7 @@ private slots:
|
|||
void showScriptEditor();
|
||||
void showChat();
|
||||
void toggleConsole();
|
||||
void toggleToolWindow();
|
||||
void toggleChat();
|
||||
void audioMuteToggled();
|
||||
void displayNameLocationResponse(const QString& errorString);
|
||||
|
@ -490,6 +491,7 @@ namespace MenuOption {
|
|||
const QString StringHair = "String Hair";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
const QString TestPing = "Test Ping";
|
||||
const QString ToolWindow = "Tool Window";
|
||||
const QString TransmitterDrive = "Transmitter Drive";
|
||||
const QString TurnWithHead = "Turn using Head";
|
||||
const QString UploadAttachment = "Upload Attachment Model";
|
||||
|
|
|
@ -70,8 +70,8 @@ Leapmotion::Leapmotion() :
|
|||
|
||||
std::vector< Semantic > rootBones;
|
||||
rootBones.push_back("elbow");
|
||||
rootBones.push_back("hand");
|
||||
rootBones.push_back("wrist");
|
||||
rootBones.push_back("hand");
|
||||
|
||||
std::vector< Semantic > fingers;
|
||||
fingers.push_back("thumb");
|
||||
|
|
|
@ -135,19 +135,19 @@ void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset
|
|||
_params.push_back(type);
|
||||
}
|
||||
|
||||
void Batch::setModelTransform(const TransformPointer& model) {
|
||||
void Batch::setModelTransform(const Transform& model) {
|
||||
ADD_COMMAND(setModelTransform);
|
||||
|
||||
_params.push_back(_transforms.cache(model));
|
||||
}
|
||||
|
||||
void Batch::setViewTransform(const TransformPointer& view) {
|
||||
void Batch::setViewTransform(const Transform& view) {
|
||||
ADD_COMMAND(setViewTransform);
|
||||
|
||||
_params.push_back(_transforms.cache(view));
|
||||
}
|
||||
|
||||
void Batch::setProjectionTransform(const TransformPointer& proj) {
|
||||
void Batch::setProjectionTransform(const Transform& proj) {
|
||||
ADD_COMMAND(setProjectionTransform);
|
||||
|
||||
_params.push_back(_transforms.cache(proj));
|
||||
|
|
|
@ -50,10 +50,6 @@ enum Primitive {
|
|||
NUM_PRIMITIVES,
|
||||
};
|
||||
|
||||
typedef ::Transform Transform;
|
||||
typedef QSharedPointer< ::gpu::Transform > TransformPointer;
|
||||
typedef std::vector< TransformPointer > Transforms;
|
||||
|
||||
class Batch {
|
||||
public:
|
||||
typedef Stream::Slot Slot;
|
||||
|
@ -87,9 +83,9 @@ public:
|
|||
// finaly projected into the clip space by the projection transform
|
||||
// WARNING: ViewTransform transform from eye space to world space, its inverse is composed
|
||||
// with the ModelTransformu to create the equivalent of the glModelViewMatrix
|
||||
void setModelTransform(const TransformPointer& model);
|
||||
void setViewTransform(const TransformPointer& view);
|
||||
void setProjectionTransform(const TransformPointer& proj);
|
||||
void setModelTransform(const Transform& model);
|
||||
void setViewTransform(const Transform& view);
|
||||
void setProjectionTransform(const Transform& proj);
|
||||
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
|
@ -258,35 +254,35 @@ public:
|
|||
template <typename T>
|
||||
class Cache {
|
||||
public:
|
||||
typedef QSharedPointer<T> Pointer;
|
||||
Pointer _pointer;
|
||||
Cache<T>(const Pointer& pointer) : _pointer(pointer) {}
|
||||
typedef T Data;
|
||||
Data _data;
|
||||
Cache<T>(const Data& data) : _data(data) {}
|
||||
|
||||
class Vector {
|
||||
public:
|
||||
std::vector< Cache<T> > _pointers;
|
||||
std::vector< Cache<T> > _items;
|
||||
|
||||
uint32 cache(const Pointer& pointer) {
|
||||
uint32 offset = _pointers.size();
|
||||
_pointers.push_back(Cache<T>(pointer));
|
||||
uint32 cache(const Data& data) {
|
||||
uint32 offset = _items.size();
|
||||
_items.push_back(Cache<T>(data));
|
||||
return offset;
|
||||
}
|
||||
|
||||
Pointer get(uint32 offset) {
|
||||
if (offset >= _pointers.size()) {
|
||||
return Pointer();
|
||||
Data get(uint32 offset) {
|
||||
if (offset >= _items.size()) {
|
||||
return Data();
|
||||
}
|
||||
return (_pointers.data() + offset)->_pointer;
|
||||
return (_items.data() + offset)->_data;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_pointers.clear();
|
||||
_items.clear();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
typedef Cache<Buffer>::Vector BufferCaches;
|
||||
typedef Cache<Stream::Format>::Vector StreamFormatCaches;
|
||||
|
||||
typedef Cache<BufferPointer>::Vector BufferCaches;
|
||||
typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
|
||||
typedef Cache<Transform>::Vector TransformCaches;
|
||||
|
||||
typedef unsigned char Byte;
|
||||
|
|
|
@ -113,15 +113,7 @@ static const GLenum _elementTypeToGLType[NUM_TYPES]= {
|
|||
|
||||
|
||||
GLBackend::GLBackend() :
|
||||
_needInputFormatUpdate(true),
|
||||
_inputFormat(0),
|
||||
_inputBuffersState(0),
|
||||
_inputBuffers(_inputBuffersState.size(), BufferPointer(0)),
|
||||
_inputBufferOffsets(_inputBuffersState.size(), 0),
|
||||
_inputBufferStrides(_inputBuffersState.size(), 0),
|
||||
_indexBuffer(0),
|
||||
_indexBufferOffset(0),
|
||||
_inputAttributeActivation(0),
|
||||
_input(),
|
||||
_transform()
|
||||
{
|
||||
|
||||
|
@ -203,9 +195,9 @@ void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) {
|
|||
uint32 numIndices = batch._params[paramOffset + 1]._uint;
|
||||
uint32 startIndex = batch._params[paramOffset + 0]._uint;
|
||||
|
||||
GLenum glType = _elementTypeToGLType[_indexBufferType];
|
||||
GLenum glType = _elementTypeToGLType[_input._indexBufferType];
|
||||
|
||||
glDrawElements(mode, numIndices, glType, reinterpret_cast<GLvoid*>(startIndex + _indexBufferOffset));
|
||||
glDrawElements(mode, numIndices, glType, reinterpret_cast<GLvoid*>(startIndex + _input._indexBufferOffset));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
@ -220,9 +212,9 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) {
|
|||
void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) {
|
||||
Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint);
|
||||
|
||||
if (format != _inputFormat) {
|
||||
_inputFormat = format;
|
||||
_needInputFormatUpdate = true;
|
||||
if (format != _input._format) {
|
||||
_input._format = format;
|
||||
_input._invalidFormat = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,10 +225,10 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) {
|
|||
uint32 channel = batch._params[paramOffset + 3]._uint;
|
||||
|
||||
if (channel < getNumInputBuffers()) {
|
||||
_inputBuffers[channel] = buffer;
|
||||
_inputBufferOffsets[channel] = offset;
|
||||
_inputBufferStrides[channel] = stride;
|
||||
_inputBuffersState.set(channel);
|
||||
_input._buffers[channel] = buffer;
|
||||
_input._bufferOffsets[channel] = offset;
|
||||
_input._bufferStrides[channel] = stride;
|
||||
_input._buffersState.set(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,14 +244,14 @@ static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = {
|
|||
#endif
|
||||
|
||||
void GLBackend::updateInput() {
|
||||
if (_needInputFormatUpdate || _inputBuffersState.any()) {
|
||||
if (_input._invalidFormat || _input._buffersState.any()) {
|
||||
|
||||
if (_needInputFormatUpdate) {
|
||||
InputActivationCache newActivation;
|
||||
if (_input._invalidFormat) {
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
// Check expected activation
|
||||
if (_inputFormat) {
|
||||
const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes();
|
||||
if (_input._format) {
|
||||
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||
for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {
|
||||
const Stream::Attribute& attrib = (*it).second;
|
||||
newActivation.set(attrib._slot);
|
||||
|
@ -269,7 +261,7 @@ void GLBackend::updateInput() {
|
|||
// Manage Activation what was and what is expected now
|
||||
for (unsigned int i = 0; i < newActivation.size(); i++) {
|
||||
bool newState = newActivation[i];
|
||||
if (newState != _inputAttributeActivation[i]) {
|
||||
if (newState != _input._attributeActivation[i]) {
|
||||
#if defined(SUPPORT_LEGACY_OPENGL)
|
||||
if (i < NUM_CLASSIC_ATTRIBS) {
|
||||
if (newState) {
|
||||
|
@ -290,31 +282,31 @@ void GLBackend::updateInput() {
|
|||
}
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
_inputAttributeActivation.flip(i);
|
||||
_input._attributeActivation.flip(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we need to bind the buffers and assign the attrib pointers
|
||||
if (_inputFormat) {
|
||||
const Buffers& buffers = _inputBuffers;
|
||||
const Offsets& offsets = _inputBufferOffsets;
|
||||
const Offsets& strides = _inputBufferStrides;
|
||||
if (_input._format) {
|
||||
const Buffers& buffers = _input._buffers;
|
||||
const Offsets& offsets = _input._bufferOffsets;
|
||||
const Offsets& strides = _input._bufferStrides;
|
||||
|
||||
const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes();
|
||||
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||
|
||||
for (Stream::Format::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin();
|
||||
channelIt != _inputFormat->getChannels().end();
|
||||
for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin();
|
||||
channelIt != _input._format->getChannels().end();
|
||||
channelIt++) {
|
||||
const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second;
|
||||
if ((*channelIt).first < buffers.size()) {
|
||||
int bufferNum = (*channelIt).first;
|
||||
|
||||
if (_inputBuffersState.test(bufferNum) || _needInputFormatUpdate) {
|
||||
if (_input._buffersState.test(bufferNum) || _input._invalidFormat) {
|
||||
GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum]));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
CHECK_GL_ERROR();
|
||||
_inputBuffersState[bufferNum] = false;
|
||||
_input._buffersState[bufferNum] = false;
|
||||
|
||||
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
||||
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
||||
|
@ -354,7 +346,7 @@ void GLBackend::updateInput() {
|
|||
}
|
||||
}
|
||||
// everything format related should be in sync now
|
||||
_needInputFormatUpdate = false;
|
||||
_input._invalidFormat = false;
|
||||
}
|
||||
|
||||
/* TODO: Fancy version GL4.4
|
||||
|
@ -415,10 +407,10 @@ void GLBackend::updateInput() {
|
|||
|
||||
|
||||
void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) {
|
||||
_indexBufferType = (Type) batch._params[paramOffset + 2]._uint;
|
||||
_input._indexBufferType = (Type) batch._params[paramOffset + 2]._uint;
|
||||
BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint);
|
||||
_indexBufferOffset = batch._params[paramOffset + 0]._uint;
|
||||
_indexBuffer = indexBuffer;
|
||||
_input._indexBufferOffset = batch._params[paramOffset + 0]._uint;
|
||||
_input._indexBuffer = indexBuffer;
|
||||
if (indexBuffer) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer));
|
||||
} else {
|
||||
|
@ -430,30 +422,18 @@ void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) {
|
|||
// Transform Stage
|
||||
|
||||
void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) {
|
||||
TransformPointer modelTransform = batch._transforms.get(batch._params[paramOffset]._uint);
|
||||
|
||||
if (_transform._model.isNull() || (modelTransform != _transform._model)) {
|
||||
_transform._model = modelTransform;
|
||||
_transform._invalidModel = true;
|
||||
}
|
||||
_transform._model = batch._transforms.get(batch._params[paramOffset]._uint);
|
||||
_transform._invalidModel = true;
|
||||
}
|
||||
|
||||
void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) {
|
||||
TransformPointer viewTransform = batch._transforms.get(batch._params[paramOffset]._uint);
|
||||
|
||||
if (_transform._view.isNull() || (viewTransform != _transform._view)) {
|
||||
_transform._view = viewTransform;
|
||||
_transform._invalidView = true;
|
||||
}
|
||||
_transform._view = batch._transforms.get(batch._params[paramOffset]._uint);
|
||||
_transform._invalidView = true;
|
||||
}
|
||||
|
||||
void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) {
|
||||
TransformPointer projectionTransform = batch._transforms.get(batch._params[paramOffset]._uint);
|
||||
|
||||
if (_transform._projection.isNull() || (projectionTransform != _transform._projection)) {
|
||||
_transform._projection = projectionTransform;
|
||||
_transform._invalidProj = true;
|
||||
}
|
||||
_transform._projection = batch._transforms.get(batch._params[paramOffset]._uint);
|
||||
_transform._invalidProj = true;
|
||||
}
|
||||
|
||||
void GLBackend::updateTransform() {
|
||||
|
@ -468,28 +448,28 @@ void GLBackend::updateTransform() {
|
|||
}
|
||||
|
||||
if (_transform._invalidModel || _transform._invalidView) {
|
||||
if (!_transform._model.isNull()) {
|
||||
if (!_transform._model.isIdentity()) {
|
||||
if (_transform._lastMode != GL_MODELVIEW) {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
_transform._lastMode = GL_MODELVIEW;
|
||||
}
|
||||
Transform::Mat4 modelView;
|
||||
if (!_transform._view.isNull()) {
|
||||
if (!_transform._view.isIdentity()) {
|
||||
Transform mvx;
|
||||
Transform::inverseMult(mvx, (*_transform._view), (*_transform._model));
|
||||
Transform::inverseMult(mvx, _transform._view, _transform._model);
|
||||
mvx.getMatrix(modelView);
|
||||
} else {
|
||||
_transform._model->getMatrix(modelView);
|
||||
_transform._model.getMatrix(modelView);
|
||||
}
|
||||
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
|
||||
} else {
|
||||
if (!_transform._view.isNull()) {
|
||||
if (!_transform._view.isIdentity()) {
|
||||
if (_transform._lastMode != GL_MODELVIEW) {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
_transform._lastMode = GL_MODELVIEW;
|
||||
}
|
||||
Transform::Mat4 modelView;
|
||||
_transform._view->getInverseMatrix(modelView);
|
||||
_transform._view.getInverseMatrix(modelView);
|
||||
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
|
||||
} else {
|
||||
// TODO: eventually do something about the matrix when neither view nor model is specified?
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
|
||||
static const int MAX_NUM_INPUT_BUFFERS = 16;
|
||||
|
||||
uint32 getNumInputBuffers() const { return _inputBuffersState.size(); }
|
||||
uint32 getNumInputBuffers() const { return _input._buffersState.size(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -62,22 +62,39 @@ protected:
|
|||
void do_setInputFormat(Batch& batch, uint32 paramOffset);
|
||||
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
|
||||
void do_setIndexBuffer(Batch& batch, uint32 paramOffset);
|
||||
|
||||
void updateInput();
|
||||
bool _needInputFormatUpdate;
|
||||
Stream::FormatPointer _inputFormat;
|
||||
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> InputBuffersState;
|
||||
InputBuffersState _inputBuffersState;
|
||||
struct InputStageState {
|
||||
bool _invalidFormat;
|
||||
Stream::FormatPointer _format;
|
||||
|
||||
Buffers _inputBuffers;
|
||||
Offsets _inputBufferOffsets;
|
||||
Offsets _inputBufferStrides;
|
||||
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
|
||||
BuffersState _buffersState;
|
||||
|
||||
BufferPointer _indexBuffer;
|
||||
Offset _indexBufferOffset;
|
||||
Type _indexBufferType;
|
||||
Buffers _buffers;
|
||||
Offsets _bufferOffsets;
|
||||
Offsets _bufferStrides;
|
||||
|
||||
typedef std::bitset<MAX_NUM_ATTRIBUTES> InputActivationCache;
|
||||
InputActivationCache _inputAttributeActivation;
|
||||
BufferPointer _indexBuffer;
|
||||
Offset _indexBufferOffset;
|
||||
Type _indexBufferType;
|
||||
|
||||
typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
|
||||
ActivationCache _attributeActivation;
|
||||
|
||||
InputStageState() :
|
||||
_invalidFormat(true),
|
||||
_format(0),
|
||||
_buffersState(0),
|
||||
_buffers(_buffersState.size(), BufferPointer(0)),
|
||||
_bufferOffsets(_buffersState.size(), 0),
|
||||
_bufferStrides(_buffersState.size(), 0),
|
||||
_indexBuffer(0),
|
||||
_indexBufferOffset(0),
|
||||
_indexBufferType(UINT32),
|
||||
_attributeActivation(0)
|
||||
{}
|
||||
} _input;
|
||||
|
||||
// Transform Stage
|
||||
void do_setModelTransform(Batch& batch, uint32 paramOffset);
|
||||
|
@ -86,9 +103,9 @@ protected:
|
|||
|
||||
void updateTransform();
|
||||
struct TransformStageState {
|
||||
TransformPointer _model;
|
||||
TransformPointer _view;
|
||||
TransformPointer _projection;
|
||||
Transform _model;
|
||||
Transform _view;
|
||||
Transform _projection;
|
||||
bool _invalidModel;
|
||||
bool _invalidView;
|
||||
bool _invalidProj;
|
||||
|
@ -96,9 +113,9 @@ protected:
|
|||
GLenum _lastMode;
|
||||
|
||||
TransformStageState() :
|
||||
_model(0),
|
||||
_view(0),
|
||||
_projection(0),
|
||||
_model(),
|
||||
_view(),
|
||||
_projection(),
|
||||
_invalidModel(true),
|
||||
_invalidView(true),
|
||||
_invalidProj(true),
|
||||
|
|
|
@ -537,7 +537,7 @@ void Model::renderSetup(RenderArgs* args) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!_meshGroupsKnown) {
|
||||
if (!_meshGroupsKnown && isLoadedWithTextures()) {
|
||||
segregateMeshGroups();
|
||||
}
|
||||
}
|
||||
|
@ -567,11 +567,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
|||
|
||||
// Capture the view matrix once for the rendering of this model
|
||||
if (_transforms.empty()) {
|
||||
_transforms.push_back(gpu::TransformPointer(new gpu::Transform()));
|
||||
_transforms.push_back(Transform());
|
||||
}
|
||||
(*_transforms[0]) = gpu::Transform((*Application::getInstance()->getViewTransform()));
|
||||
_transforms[0] = Application::getInstance()->getViewTransform();
|
||||
// apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space)
|
||||
_transforms[0]->preTranslate(-_translation);
|
||||
_transforms[0].preTranslate(-_translation);
|
||||
|
||||
batch.setViewTransform(_transforms[0]);
|
||||
|
||||
|
@ -628,7 +628,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
|||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
|
@ -649,7 +649,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
|||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args);
|
||||
|
||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||
GLBATCH(glEnable)(GL_BLEND);
|
||||
|
@ -673,7 +673,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
|||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args);
|
||||
}
|
||||
|
||||
GLBATCH(glDepthMask)(true);
|
||||
|
@ -1493,10 +1493,10 @@ void Model::setupBatchTransform(gpu::Batch& batch) {
|
|||
|
||||
// Capture the view matrix once for the rendering of this model
|
||||
if (_transforms.empty()) {
|
||||
_transforms.push_back(gpu::TransformPointer(new gpu::Transform()));
|
||||
_transforms.push_back(Transform());
|
||||
}
|
||||
(*_transforms[0]) = gpu::Transform((*Application::getInstance()->getViewTransform()));
|
||||
_transforms[0]->preTranslate(-_translation);
|
||||
_transforms[0] = Application::getInstance()->getViewTransform();
|
||||
_transforms[0].preTranslate(-_translation);
|
||||
batch.setViewTransform(_transforms[0]);
|
||||
}
|
||||
|
||||
|
@ -1553,46 +1553,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
|||
int opaqueMeshPartsRendered = 0;
|
||||
|
||||
// now, for each model in the scene, render the mesh portions
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
|
@ -1606,46 +1574,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
|||
|
||||
int translucentParts = 0;
|
||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args);
|
||||
|
||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||
GLBATCH(glEnable)(GL_BLEND);
|
||||
|
@ -1662,46 +1598,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
|||
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
model->setupBatchTransform(batch);
|
||||
translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args);
|
||||
}
|
||||
|
||||
GLBATCH(glDepthMask)(true);
|
||||
|
@ -1981,19 +1885,8 @@ void Model::segregateMeshGroups() {
|
|||
_meshGroupsKnown = true;
|
||||
}
|
||||
|
||||
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
||||
|
||||
QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
|
||||
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
|
||||
bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches);
|
||||
|
||||
QString lastMaterialID;
|
||||
int meshPartsRendered = 0;
|
||||
updateVisibleJointStates();
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||
|
||||
// depending on which parameters we were called with, pick the correct mesh group to render
|
||||
QVector<int>* whichList = NULL;
|
||||
|
@ -2032,23 +1925,18 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
|||
} else {
|
||||
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
|
||||
}
|
||||
|
||||
if (!whichList) {
|
||||
qDebug() << "unexpected!!! we don't know which list of meshes to render...";
|
||||
return 0;
|
||||
}
|
||||
QVector<int>& list = *whichList;
|
||||
|
||||
// If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs
|
||||
if (list.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return whichList;
|
||||
}
|
||||
|
||||
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||
SkinLocations*& skinLocations, GLenum& specularTextureUnit) {
|
||||
|
||||
ProgramObject* program = &_program;
|
||||
Locations* locations = &_locations;
|
||||
ProgramObject* skinProgram = &_skinProgram;
|
||||
SkinLocations* skinLocations = &_skinLocations;
|
||||
GLenum specularTextureUnit = 0;
|
||||
skinLocations = &_skinLocations;
|
||||
specularTextureUnit = 0;
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
program = &_shadowProgram;
|
||||
skinProgram = &_skinShadowProgram;
|
||||
|
@ -2091,8 +1979,84 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
|||
if (!activeProgram->isLinked()) {
|
||||
activeProgram->link();
|
||||
}
|
||||
|
||||
GLBATCH(glUseProgram)(activeProgram->programId());
|
||||
GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold);
|
||||
}
|
||||
|
||||
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
||||
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
int meshPartsRendered = 0;
|
||||
|
||||
bool pickProgramsNeeded = true;
|
||||
SkinLocations* skinLocations;
|
||||
GLenum specularTextureUnit;
|
||||
|
||||
foreach(Model* model, _modelsInScene) {
|
||||
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned);
|
||||
if (whichList) {
|
||||
QVector<int>& list = *whichList;
|
||||
if (list.size() > 0) {
|
||||
if (pickProgramsNeeded) {
|
||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit);
|
||||
pickProgramsNeeded = false;
|
||||
}
|
||||
model->setupBatchTransform(batch);
|
||||
meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit);
|
||||
GLBATCH(glPopMatrix)();
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we selected a program, then unselect it
|
||||
if (!pickProgramsNeeded) {
|
||||
GLBATCH(glUseProgram)(0);
|
||||
}
|
||||
return meshPartsRendered;
|
||||
}
|
||||
|
||||
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
||||
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
int meshPartsRendered = 0;
|
||||
|
||||
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned);
|
||||
|
||||
if (!whichList) {
|
||||
qDebug() << "unexpected!!! we don't know which list of meshes to render...";
|
||||
return 0;
|
||||
}
|
||||
QVector<int>& list = *whichList;
|
||||
|
||||
// If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs
|
||||
if (list.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SkinLocations* skinLocations;
|
||||
GLenum specularTextureUnit;
|
||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit);
|
||||
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit);
|
||||
GLBATCH(glUseProgram)(0);
|
||||
|
||||
return meshPartsRendered;
|
||||
}
|
||||
|
||||
|
||||
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args,
|
||||
SkinLocations* skinLocations, GLenum specularTextureUnit) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
|
||||
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
|
||||
bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches);
|
||||
|
||||
QString lastMaterialID;
|
||||
int meshPartsRendered = 0;
|
||||
updateVisibleJointStates();
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||
|
||||
// i is the "index" from the original networkMeshes QVector...
|
||||
foreach (int i, list) {
|
||||
|
@ -2149,10 +2113,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
|||
if (state.clusterMatrices.size() > 1) {
|
||||
GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||
(const float*)state.clusterMatrices.constData());
|
||||
batch.setModelTransform(gpu::TransformPointer());
|
||||
batch.setModelTransform(Transform());
|
||||
} else {
|
||||
gpu::TransformPointer modelTransform(new gpu::Transform(state.clusterMatrices[0]));
|
||||
batch.setModelTransform(modelTransform);
|
||||
batch.setModelTransform(Transform(state.clusterMatrices[0]));
|
||||
}
|
||||
|
||||
if (mesh.blendshapes.isEmpty()) {
|
||||
|
@ -2268,7 +2231,5 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
|||
|
||||
}
|
||||
|
||||
GLBATCH(glUseProgram)(0);
|
||||
|
||||
return meshPartsRendered;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ private:
|
|||
QUrl _url;
|
||||
|
||||
gpu::Buffers _blendedVertexBuffers;
|
||||
gpu::Transforms _transforms;
|
||||
std::vector<Transform> _transforms;
|
||||
gpu::Batch _renderBatch;
|
||||
|
||||
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;
|
||||
|
@ -409,6 +409,18 @@ private:
|
|||
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL);
|
||||
void setupBatchTransform(gpu::Batch& batch);
|
||||
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned);
|
||||
|
||||
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit);
|
||||
|
||||
static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||
SkinLocations*& skinLocations, GLenum& specularTextureUnit);
|
||||
|
||||
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
|
||||
#include <QVBoxLayout>
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QDockWidget>
|
||||
#include <QWebFrame>
|
||||
#include <QWebView>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "WindowScriptingInterface.h"
|
||||
#include "WebWindowClass.h"
|
||||
|
||||
|
@ -28,29 +32,34 @@ void ScriptEventBridge::emitScriptEvent(const QString& data) {
|
|||
emit scriptEventReceived(data);
|
||||
}
|
||||
|
||||
WebWindowClass::WebWindowClass(const QString& url, int width, int height)
|
||||
|
||||
WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height)
|
||||
: QObject(NULL),
|
||||
_window(new QWidget(NULL, Qt::Tool)),
|
||||
_eventBridge(new ScriptEventBridge(this)) {
|
||||
|
||||
QWebView* webView = new QWebView(_window);
|
||||
ToolWindow* toolWindow = Application::getInstance()->getToolWindow();
|
||||
|
||||
_dockWidget = new QDockWidget(title, toolWindow);
|
||||
_dockWidget->setFeatures(QDockWidget::DockWidgetMovable);
|
||||
QWebView* webView = new QWebView(_dockWidget);
|
||||
webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge);
|
||||
webView->setUrl(url);
|
||||
QVBoxLayout* layout = new QVBoxLayout(_window);
|
||||
_window->setLayout(layout);
|
||||
layout->addWidget(webView);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
_window->setGeometry(0, 0, width, height);
|
||||
_dockWidget->setWidget(webView);
|
||||
|
||||
connect(this, &WebWindowClass::destroyed, _window, &QWidget::deleteLater);
|
||||
toolWindow->addDockWidget(Qt::RightDockWidgetArea, _dockWidget);
|
||||
|
||||
connect(this, &WebWindowClass::destroyed, _dockWidget, &QWidget::deleteLater);
|
||||
}
|
||||
|
||||
WebWindowClass::~WebWindowClass() {
|
||||
}
|
||||
|
||||
void WebWindowClass::setVisible(bool visible) {
|
||||
QMetaObject::invokeMethod(_window, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
|
||||
if (visible) {
|
||||
QMetaObject::invokeMethod(
|
||||
Application::getInstance()->getToolWindow(), "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
|
||||
}
|
||||
QMetaObject::invokeMethod(_dockWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
|
||||
}
|
||||
|
||||
QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) {
|
||||
|
@ -59,8 +68,9 @@ QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine*
|
|||
QMetaObject::invokeMethod(WindowScriptingInterface::getInstance(), "doCreateWebWindow", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(WebWindowClass*, retVal),
|
||||
Q_ARG(const QString&, file),
|
||||
Q_ARG(int, context->argument(1).toInteger()),
|
||||
Q_ARG(int, context->argument(2).toInteger()));
|
||||
Q_ARG(QString, context->argument(1).toString()),
|
||||
Q_ARG(int, context->argument(2).toInteger()),
|
||||
Q_ARG(int, context->argument(3).toInteger()));
|
||||
|
||||
connect(engine, &QScriptEngine::destroyed, retVal, &WebWindowClass::deleteLater);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class WebWindowClass : public QObject {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(QObject* eventBridge READ getEventBridge)
|
||||
public:
|
||||
WebWindowClass(const QString& url, int width, int height);
|
||||
WebWindowClass(const QString& title, const QString& url, int width, int height);
|
||||
~WebWindowClass();
|
||||
|
||||
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
|
||||
|
@ -44,7 +44,7 @@ public slots:
|
|||
ScriptEventBridge* getEventBridge() const { return _eventBridge; }
|
||||
|
||||
private:
|
||||
QWidget* _window;
|
||||
QDockWidget* _dockWidget;
|
||||
ScriptEventBridge* _eventBridge;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@ WindowScriptingInterface::WindowScriptingInterface() :
|
|||
{
|
||||
}
|
||||
|
||||
WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& url, int width, int height) {
|
||||
return new WebWindowClass(url, width, height);
|
||||
WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) {
|
||||
return new WebWindowClass(title, url, width, height);
|
||||
}
|
||||
|
||||
QScriptValue WindowScriptingInterface::hasFocus() {
|
||||
|
|
|
@ -78,7 +78,7 @@ private slots:
|
|||
void nonBlockingFormAccepted() { _nonBlockingFormActive = false; _formResult = QDialog::Accepted; emit nonBlockingFormClosed(); }
|
||||
void nonBlockingFormRejected() { _nonBlockingFormActive = false; _formResult = QDialog::Rejected; emit nonBlockingFormClosed(); }
|
||||
|
||||
WebWindowClass* doCreateWebWindow(const QString& url, int width, int height);
|
||||
WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height);
|
||||
|
||||
private:
|
||||
WindowScriptingInterface();
|
||||
|
|
82
interface/src/ui/ToolWindow.cpp
Normal file
82
interface/src/ui/ToolWindow.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// ToolWindow.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Ryan Huffman on 11/13/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
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "ToolWindow.h"
|
||||
#include "UIUtil.h"
|
||||
|
||||
const int DEFAULT_WIDTH = 300;
|
||||
|
||||
ToolWindow::ToolWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
_hasShown(false),
|
||||
_lastGeometry() {
|
||||
}
|
||||
|
||||
bool ToolWindow::event(QEvent* event) {
|
||||
QEvent::Type type = event->type();
|
||||
if (type == QEvent::Show) {
|
||||
if (!_hasShown) {
|
||||
_hasShown = true;
|
||||
|
||||
QMainWindow* mainWindow = Application::getInstance()->getWindow();
|
||||
QRect mainGeometry = mainWindow->geometry();
|
||||
|
||||
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
|
||||
int menuBarHeight = Menu::getInstance()->geometry().height();
|
||||
int topMargin = titleBarHeight + menuBarHeight;
|
||||
|
||||
_lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin,
|
||||
DEFAULT_WIDTH, mainGeometry.height() - topMargin);
|
||||
}
|
||||
setGeometry(_lastGeometry);
|
||||
return true;
|
||||
} else if (type == QEvent::Hide) {
|
||||
_lastGeometry = geometry();
|
||||
return true;
|
||||
}
|
||||
|
||||
return QMainWindow::event(event);
|
||||
}
|
||||
|
||||
void ToolWindow::onChildVisibilityUpdated(bool visible) {
|
||||
if (visible) {
|
||||
setVisible(true);
|
||||
} else {
|
||||
bool hasVisible = false;
|
||||
QList<QDockWidget*> dockWidgets = findChildren<QDockWidget*>();
|
||||
for (int i = 0; i < dockWidgets.count(); i++) {
|
||||
if (dockWidgets[i]->isVisible()) {
|
||||
hasVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setVisible(hasVisible);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget) {
|
||||
QMainWindow::addDockWidget(area, dockWidget);
|
||||
|
||||
connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated);
|
||||
}
|
||||
|
||||
void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation) {
|
||||
QMainWindow::addDockWidget(area, dockWidget, orientation);
|
||||
|
||||
connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated);
|
||||
}
|
||||
|
||||
void ToolWindow::removeDockWidget(QDockWidget* dockWidget) {
|
||||
QMainWindow::removeDockWidget(dockWidget);
|
||||
|
||||
disconnect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated);
|
||||
}
|
40
interface/src/ui/ToolWindow.h
Normal file
40
interface/src/ui/ToolWindow.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ToolWindow.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Ryan Huffman on 11/13/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
|
||||
//
|
||||
|
||||
#ifndef hifi_ToolWindow_h
|
||||
#define hifi_ToolWindow_h
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QEvent>
|
||||
#include <QMainWindow>
|
||||
#include <QRect>
|
||||
#include <QWidget>
|
||||
|
||||
class ToolWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ToolWindow(QWidget* parent = NULL);
|
||||
|
||||
virtual bool event(QEvent* event);
|
||||
virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget);
|
||||
virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation);
|
||||
virtual void removeDockWidget(QDockWidget* dockWidget);
|
||||
|
||||
public slots:
|
||||
void onChildVisibilityUpdated(bool visible);
|
||||
|
||||
|
||||
private:
|
||||
bool _hasShown;
|
||||
QRect _lastGeometry;
|
||||
};
|
||||
|
||||
#endif // hifi_ToolWindow_h
|
|
@ -118,6 +118,32 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue Base3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "position" || property == "start" || property == "p1" || property == "point") {
|
||||
return vec3toScriptValue(_scriptEngine, _position);
|
||||
}
|
||||
if (property == "lineWidth") {
|
||||
return _lineWidth;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, _rotation);
|
||||
}
|
||||
if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") {
|
||||
return _isSolid;
|
||||
}
|
||||
if (property == "isWire" || property == "wire") {
|
||||
return !_isSolid;
|
||||
}
|
||||
if (property == "isDashedLine" || property == "dashed") {
|
||||
return _isDashedLine;
|
||||
}
|
||||
if (property == "ignoreRayIntersection") {
|
||||
return _ignoreRayIntersection;
|
||||
}
|
||||
|
||||
return Overlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) const {
|
||||
return false;
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
|
|
|
@ -157,6 +157,23 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue BillboardOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url;
|
||||
}
|
||||
if (property == "subImage") {
|
||||
return qRectToScriptValue(_scriptEngine, _fromImage);
|
||||
}
|
||||
if (property == "scale") {
|
||||
return _scale;
|
||||
}
|
||||
if (property == "isFacingAvatar") {
|
||||
return _isFacingAvatar;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
void BillboardOverlay::setURL(const QString& url) {
|
||||
setBillboardURL(url);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
|
|
|
@ -299,6 +299,45 @@ void Circle3DOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue Circle3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "startAt") {
|
||||
return _startAt;
|
||||
}
|
||||
if (property == "endAt") {
|
||||
return _endAt;
|
||||
}
|
||||
if (property == "outerRadius") {
|
||||
return _outerRadius;
|
||||
}
|
||||
if (property == "innerRadius") {
|
||||
return _innerRadius;
|
||||
}
|
||||
if (property == "hasTickMarks") {
|
||||
return _hasTickMarks;
|
||||
}
|
||||
if (property == "majorTickMarksAngle") {
|
||||
return _majorTickMarksAngle;
|
||||
}
|
||||
if (property == "minorTickMarksAngle") {
|
||||
return _minorTickMarksAngle;
|
||||
}
|
||||
if (property == "majorTickMarksLength") {
|
||||
return _majorTickMarksLength;
|
||||
}
|
||||
if (property == "minorTickMarksLength") {
|
||||
return _minorTickMarksLength;
|
||||
}
|
||||
if (property == "majorTickMarksColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _majorTickMarksColor);
|
||||
}
|
||||
if (property == "minorTickMarksColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _minorTickMarksColor);
|
||||
}
|
||||
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
|
||||
bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin,
|
||||
const glm::vec3& direction, float& distance, BoxFace& face) const {
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
~Circle3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
float getStartAt() const { return _startAt; }
|
||||
float getEndAt() const { return _endAt; }
|
||||
|
|
|
@ -116,3 +116,14 @@ void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
_majorGridEvery = properties.property("majorGridEvery").toVariant().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Grid3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "minorGridWidth") {
|
||||
return _minorGridWidth;
|
||||
}
|
||||
if (property == "majorGridEvery") {
|
||||
return _majorGridEvery;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
private:
|
||||
float _minorGridWidth;
|
||||
|
|
|
@ -151,4 +151,13 @@ void ImageOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue ImageOverlay::getProperty(const QString& property) {
|
||||
if (property == "subImage") {
|
||||
return qRectToScriptValue(_scriptEngine, _fromImage);
|
||||
}
|
||||
if (property == "imageURL") {
|
||||
return _imageURL.toString();
|
||||
}
|
||||
|
||||
return Overlay2D::getProperty(property);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; _wantClipFromImage = true; }
|
||||
void setImageURL(const QUrl& url);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
private slots:
|
||||
void replyFinished(); // we actually want to hide this...
|
||||
|
|
|
@ -79,3 +79,11 @@ void Line3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Line3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "end" || property == "endPoint" || property == "p2") {
|
||||
return vec3toScriptValue(_scriptEngine, _end);
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
void setEnd(const glm::vec3& end) { _end = end; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
protected:
|
||||
glm::vec3 _end;
|
||||
|
|
|
@ -103,3 +103,14 @@ void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue LocalVoxelsOverlay::getProperty(const QString& property) {
|
||||
if (property == "scale") {
|
||||
return vec3toScriptValue(_scriptEngine, getDimensions());
|
||||
}
|
||||
if (property == "name") {
|
||||
return _treeName;
|
||||
}
|
||||
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ public:
|
|||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
private:
|
||||
static QMap<QString, WeakVoxelSystemPointer> _voxelSystemMap; // treeName/voxelSystem
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
ModelOverlay::ModelOverlay()
|
||||
: _model(),
|
||||
_modelTextures(QVariantMap()),
|
||||
_scale(1.0f),
|
||||
_updateModel(false)
|
||||
{
|
||||
|
@ -114,6 +115,8 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
QMetaObject::invokeMethod(&_model, "setTextureWithNameToURL", Qt::AutoConnection,
|
||||
Q_ARG(const QString&, key),
|
||||
Q_ARG(const QUrl&, newTextureURL));
|
||||
|
||||
_modelTextures[key] = newTextureURL; // Keep local track of textures for getProperty()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +125,34 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue ModelOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url.toString();
|
||||
}
|
||||
if (property == "scale") {
|
||||
return _scale;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, _rotation);
|
||||
}
|
||||
if (property == "dimensions") {
|
||||
return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions());
|
||||
}
|
||||
if (property == "textures") {
|
||||
if (_modelTextures.size() > 0) {
|
||||
QScriptValue textures = _scriptEngine->newObject();
|
||||
foreach(const QString& key, _modelTextures.keys()) {
|
||||
textures.setProperty(key, _modelTextures[key].toString());
|
||||
}
|
||||
return textures;
|
||||
} else {
|
||||
return QScriptValue();
|
||||
}
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) const {
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const;
|
||||
|
@ -31,6 +32,7 @@ public:
|
|||
private:
|
||||
|
||||
Model _model;
|
||||
QVariantMap _modelTextures;
|
||||
|
||||
QUrl _url;
|
||||
glm::quat _rotation;
|
||||
|
|
|
@ -39,8 +39,9 @@ Overlay::Overlay() :
|
|||
{
|
||||
}
|
||||
|
||||
void Overlay::init(QGLWidget* parent) {
|
||||
void Overlay::init(QGLWidget* parent, QScriptEngine* scriptEngine) {
|
||||
_parent = parent;
|
||||
_scriptEngine = scriptEngine;
|
||||
}
|
||||
|
||||
|
||||
|
@ -104,6 +105,44 @@ void Overlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue Overlay::getProperty(const QString& property) {
|
||||
if (property == "color") {
|
||||
return xColorToScriptValue(_scriptEngine, _color);
|
||||
}
|
||||
if (property == "alpha") {
|
||||
return _alpha;
|
||||
}
|
||||
if (property == "glowLevel") {
|
||||
return _glowLevel;
|
||||
}
|
||||
if (property == "pulseMax") {
|
||||
return _pulseMax;
|
||||
}
|
||||
if (property == "pulseMin") {
|
||||
return _pulseMin;
|
||||
}
|
||||
if (property == "pulsePeriod") {
|
||||
return _pulsePeriod;
|
||||
}
|
||||
if (property == "glowLevelPulse") {
|
||||
return _glowLevelPulse;
|
||||
}
|
||||
if (property == "alphaPulse") {
|
||||
return _alphaPulse;
|
||||
}
|
||||
if (property == "colorPulse") {
|
||||
return _colorPulse;
|
||||
}
|
||||
if (property == "visible") {
|
||||
return _visible;
|
||||
}
|
||||
if (property == "anchor") {
|
||||
return _anchor == MY_AVATAR ? "MyAvatar" : "";
|
||||
}
|
||||
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
xColor Overlay::getColor() {
|
||||
if (_colorPulse == 0.0f) {
|
||||
return _color;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // for xColor
|
||||
#include <RenderArgs.h>
|
||||
|
||||
|
@ -36,7 +37,7 @@ public:
|
|||
|
||||
Overlay();
|
||||
~Overlay();
|
||||
void init(QGLWidget* parent);
|
||||
void init(QGLWidget* parent, QScriptEngine* scriptEngine);
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render(RenderArgs* args) = 0;
|
||||
|
||||
|
@ -77,6 +78,7 @@ public:
|
|||
void setAlphaPulse(float value) { _alphaPulse = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
protected:
|
||||
float updatePulse();
|
||||
|
@ -100,6 +102,8 @@ protected:
|
|||
xColor _color;
|
||||
bool _visible; // should the overlay be drawn at all
|
||||
Anchor _anchor;
|
||||
|
||||
QScriptEngine* _scriptEngine;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -64,3 +64,23 @@ void Overlay2D::setProperties(const QScriptValue& properties) {
|
|||
//qDebug() << "set bounds to " << getBounds();
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Overlay2D::getProperty(const QString& property) {
|
||||
if (property == "bounds") {
|
||||
return qRectToScriptValue(_scriptEngine, _bounds);
|
||||
}
|
||||
if (property == "x") {
|
||||
return _bounds.x();
|
||||
}
|
||||
if (property == "y") {
|
||||
return _bounds.y();
|
||||
}
|
||||
if (property == "width") {
|
||||
return _bounds.width();
|
||||
}
|
||||
if (property == "height") {
|
||||
return _bounds.height();
|
||||
}
|
||||
|
||||
return Overlay::getProperty(property);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
void setBounds(const QRect& bounds) { _bounds = bounds; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
protected:
|
||||
QRect _bounds; // where on the screen to draw
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
//
|
||||
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
#include <Application.h>
|
||||
#include <Menu.h>
|
||||
#include <QScriptValueIterator>
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
#include "Circle3DOverlay.h"
|
||||
|
@ -55,6 +57,7 @@ Overlays::~Overlays() {
|
|||
|
||||
void Overlays::init(QGLWidget* parent) {
|
||||
_parent = parent;
|
||||
_scriptEngine = new QScriptEngine();
|
||||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
|
@ -179,7 +182,7 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
|
|||
}
|
||||
|
||||
unsigned int Overlays::addOverlay(Overlay* overlay) {
|
||||
overlay->init(_parent);
|
||||
overlay->init(_parent, _scriptEngine);
|
||||
|
||||
QWriteLocker lock(&_lock);
|
||||
unsigned int thisID = _nextOverlayID;
|
||||
|
@ -241,6 +244,51 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
|||
return 0; // not found
|
||||
}
|
||||
|
||||
OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& property) {
|
||||
OverlayPropertyResult result;
|
||||
Overlay* thisOverlay = NULL;
|
||||
QReadLocker lock(&_lock);
|
||||
if (_overlays2D.contains(id)) {
|
||||
thisOverlay = _overlays2D[id];
|
||||
} else if (_overlays3D.contains(id)) {
|
||||
thisOverlay = _overlays3D[id];
|
||||
}
|
||||
if (thisOverlay) {
|
||||
result.value = thisOverlay->getProperty(property);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
OverlayPropertyResult::OverlayPropertyResult() :
|
||||
value(QScriptValue())
|
||||
{
|
||||
}
|
||||
|
||||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& result)
|
||||
{
|
||||
if (!result.value.isValid()) {
|
||||
return QScriptValue::UndefinedValue;
|
||||
}
|
||||
|
||||
QScriptValue object = engine->newObject();
|
||||
if (result.value.isObject()) {
|
||||
QScriptValueIterator it(result.value);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
object.setProperty(it.name(), QScriptValue(it.value().toString()));
|
||||
}
|
||||
|
||||
} else {
|
||||
object = result.value;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayPropertyResult& result)
|
||||
{
|
||||
result.value = value;
|
||||
}
|
||||
|
||||
RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) {
|
||||
float bestDistance = std::numeric_limits<float>::max();
|
||||
RayToOverlayIntersectionResult result;
|
||||
|
@ -360,3 +408,19 @@ bool Overlays::isLoaded(unsigned int id) {
|
|||
return overlay->isLoaded();
|
||||
}
|
||||
|
||||
float Overlays::textWidth(unsigned int id, const QString& text) const {
|
||||
Overlay* thisOverlay = _overlays2D[id];
|
||||
if (thisOverlay) {
|
||||
if (typeid(*thisOverlay) == typeid(TextOverlay)) {
|
||||
return static_cast<TextOverlay*>(thisOverlay)->textWidth(text);
|
||||
}
|
||||
} else {
|
||||
thisOverlay = _overlays3D[id];
|
||||
if (thisOverlay) {
|
||||
if (typeid(*thisOverlay) == typeid(Text3DOverlay)) {
|
||||
return static_cast<Text3DOverlay*>(thisOverlay)->textWidth(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,17 @@
|
|||
|
||||
#include "Overlay.h"
|
||||
|
||||
class OverlayPropertyResult {
|
||||
public:
|
||||
OverlayPropertyResult();
|
||||
QScriptValue value;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(OverlayPropertyResult);
|
||||
|
||||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value);
|
||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value);
|
||||
|
||||
class RayToOverlayIntersectionResult {
|
||||
public:
|
||||
RayToOverlayIntersectionResult();
|
||||
|
@ -27,6 +38,7 @@ public:
|
|||
QString extraInfo;
|
||||
};
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(RayToOverlayIntersectionResult);
|
||||
|
||||
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value);
|
||||
|
@ -59,12 +71,19 @@ public slots:
|
|||
/// returns the top most 2D overlay at the screen point, or 0 if not overlay at that point
|
||||
unsigned int getOverlayAtPoint(const glm::vec2& point);
|
||||
|
||||
/// returns the value of specified property, or null if there is no such property
|
||||
OverlayPropertyResult getProperty(unsigned int id, const QString& property);
|
||||
|
||||
/// returns details about the closest 3D Overlay hit by the pick ray
|
||||
RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray);
|
||||
|
||||
/// returns whether the overlay's assets are loaded or not
|
||||
bool isLoaded(unsigned int id);
|
||||
|
||||
/// returns the width of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text
|
||||
/// overlay; in meters if it is a 3D text overlay
|
||||
float textWidth(unsigned int id, const QString& text) const;
|
||||
|
||||
private:
|
||||
QMap<unsigned int, Overlay*> _overlays2D;
|
||||
QMap<unsigned int, Overlay*> _overlays3D;
|
||||
|
@ -73,6 +92,7 @@ private:
|
|||
QGLWidget* _parent;
|
||||
QReadWriteLock _lock;
|
||||
QReadWriteLock _deleteLock;
|
||||
QScriptEngine* _scriptEngine;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -77,6 +77,14 @@ void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec2toScriptValue(_scriptEngine, _dimensions);
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) const {
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
void setDimensions(const glm::vec2& value) { _dimensions = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||
const float DEFAULT_MARGIN = 0.1f;
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const float LINE_SCALE_RATIO = 1.2f;
|
||||
|
||||
Text3DOverlay::Text3DOverlay() :
|
||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||
|
@ -87,11 +89,10 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glEnd();
|
||||
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation
|
||||
|
||||
// Same font properties as textWidth()
|
||||
TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
float LINE_SCALE_RATIO = 1.2f;
|
||||
float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
@ -179,4 +180,38 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
}
|
||||
|
||||
QScriptValue Text3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "text") {
|
||||
return _text;
|
||||
}
|
||||
if (property == "backgroundColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
||||
}
|
||||
if (property == "lineHeight") {
|
||||
return _lineHeight;
|
||||
}
|
||||
if (property == "leftMargin") {
|
||||
return _leftMargin;
|
||||
}
|
||||
if (property == "topMargin") {
|
||||
return _topMargin;
|
||||
}
|
||||
if (property == "rightMargin") {
|
||||
return _rightMargin;
|
||||
}
|
||||
if (property == "bottomMargin") {
|
||||
return _bottomMargin;
|
||||
}
|
||||
if (property == "isFacingAvatar") {
|
||||
return _isFacingAvatar;
|
||||
}
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
float Text3DOverlay::textWidth(const QString& text) const {
|
||||
QFont font(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); // Same font properties as render()
|
||||
QFontMetrics fontMetrics(font);
|
||||
float scaleFactor = _lineHeight * LINE_SCALE_RATIO / (float)FIXED_FONT_POINT_SIZE;
|
||||
return scaleFactor * (float)fontMetrics.width(qPrintable(text));
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ public:
|
|||
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
float textWidth(const QString& text) const; // Meters
|
||||
|
||||
private:
|
||||
void enableClipPlane(GLenum plane, float x, float y, float z, float w);
|
||||
|
|
|
@ -66,9 +66,8 @@ void TextOverlay::render(RenderArgs* args) {
|
|||
glVertex2f(_bounds.left(), _bounds.bottom());
|
||||
glEnd();
|
||||
|
||||
//TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false,
|
||||
// EffectType effect = NO_EFFECT, int effectThickness = 1);
|
||||
TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, 50);
|
||||
// Same font properties as textWidth()
|
||||
TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT);
|
||||
|
||||
const int leftAdjust = -1; // required to make text render relative to left edge of bounds
|
||||
const int topAdjust = -2; // required to make text render relative to top edge of bounds
|
||||
|
@ -125,4 +124,31 @@ void TextOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue TextOverlay::getProperty(const QString& property) {
|
||||
if (property == "font") {
|
||||
QScriptValue font = _scriptEngine->newObject();
|
||||
font.setProperty("size", _fontSize);
|
||||
return font;
|
||||
}
|
||||
if (property == "text") {
|
||||
return _text;
|
||||
}
|
||||
if (property == "backgroundColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
||||
}
|
||||
if (property == "leftMargin") {
|
||||
return _leftMargin;
|
||||
}
|
||||
if (property == "topMargin") {
|
||||
return _topMargin;
|
||||
}
|
||||
|
||||
return Overlay2D::getProperty(property);
|
||||
}
|
||||
|
||||
|
||||
float TextOverlay::textWidth(const QString& text) const {
|
||||
QFont font(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); // Same font properties as render()
|
||||
QFontMetrics fontMetrics(font);
|
||||
return fontMetrics.width(qPrintable(text));
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||
const int DEFAULT_MARGIN = 10;
|
||||
const int DEFAULT_FONTSIZE = 11;
|
||||
const int DEFAULT_FONT_WEIGHT = 50;
|
||||
|
||||
class TextOverlay : public Overlay2D {
|
||||
Q_OBJECT
|
||||
|
@ -52,6 +53,9 @@ public:
|
|||
void setFontSize(int fontSize) { _fontSize = fontSize; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
float textWidth(const QString& text) const; // Pixels
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -85,6 +85,14 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec3toScriptValue(_scriptEngine, _dimensions);
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) const {
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
void setDimensions(const glm::vec3& value) { _dimensions = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ void injectorFromScriptValue(const QScriptValue& object, AudioInjector*& out) {
|
|||
|
||||
AudioInjector::AudioInjector(QObject* parent) :
|
||||
QObject(parent),
|
||||
_sound(NULL),
|
||||
_options(),
|
||||
_shouldStop(false),
|
||||
_loudness(0.0f),
|
||||
|
@ -42,7 +41,7 @@ AudioInjector::AudioInjector(QObject* parent) :
|
|||
}
|
||||
|
||||
AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) :
|
||||
_sound(sound),
|
||||
_audioData(sound->getByteArray()),
|
||||
_options(injectorOptions),
|
||||
_shouldStop(false),
|
||||
_loudness(0.0f),
|
||||
|
@ -52,6 +51,18 @@ AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorO
|
|||
{
|
||||
}
|
||||
|
||||
AudioInjector::AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions) :
|
||||
_audioData(audioData),
|
||||
_options(injectorOptions),
|
||||
_shouldStop(false),
|
||||
_loudness(0.0f),
|
||||
_isFinished(false),
|
||||
_currentSendPosition(0),
|
||||
_localBuffer(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AudioInjector::~AudioInjector() {
|
||||
if (_localBuffer) {
|
||||
_localBuffer->stop();
|
||||
|
@ -76,11 +87,9 @@ void AudioInjector::injectAudio() {
|
|||
|
||||
void AudioInjector::injectLocally() {
|
||||
bool success = false;
|
||||
if (_localAudioInterface) {
|
||||
const QByteArray& soundByteArray = _sound->getByteArray();
|
||||
|
||||
if (soundByteArray.size() > 0) {
|
||||
_localBuffer = new AudioInjectorLocalBuffer(_sound->getByteArray(), this);
|
||||
if (_localAudioInterface) {
|
||||
if (_audioData.size() > 0) {
|
||||
_localBuffer = new AudioInjectorLocalBuffer(_audioData, this);
|
||||
_localBuffer->open(QIODevice::ReadOnly);
|
||||
_localBuffer->setShouldLoop(_options.loop);
|
||||
|
||||
|
@ -114,15 +123,13 @@ void AudioInjector::injectLocally() {
|
|||
const uchar MAX_INJECTOR_VOLUME = 0xFF;
|
||||
|
||||
void AudioInjector::injectToMixer() {
|
||||
QByteArray soundByteArray = _sound->getByteArray();
|
||||
|
||||
if (_currentSendPosition < 0 ||
|
||||
_currentSendPosition >= soundByteArray.size()) {
|
||||
_currentSendPosition >= _audioData.size()) {
|
||||
_currentSendPosition = 0;
|
||||
}
|
||||
|
||||
// make sure we actually have samples downloaded to inject
|
||||
if (soundByteArray.size()) {
|
||||
if (_audioData.size()) {
|
||||
|
||||
// setup the packet for injected audio
|
||||
QByteArray injectAudioPacket = byteArrayWithPopulatedHeader(PacketTypeInjectAudio);
|
||||
|
@ -172,15 +179,15 @@ void AudioInjector::injectToMixer() {
|
|||
|
||||
// loop to send off our audio in NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL byte chunks
|
||||
quint16 outgoingInjectedAudioSequenceNumber = 0;
|
||||
while (_currentSendPosition < soundByteArray.size() && !_shouldStop) {
|
||||
while (_currentSendPosition < _audioData.size() && !_shouldStop) {
|
||||
|
||||
int bytesToCopy = std::min(((_options.stereo) ? 2 : 1) * NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL,
|
||||
soundByteArray.size() - _currentSendPosition);
|
||||
_audioData.size() - _currentSendPosition);
|
||||
|
||||
// Measure the loudness of this frame
|
||||
_loudness = 0.0f;
|
||||
for (int i = 0; i < bytesToCopy; i += sizeof(int16_t)) {
|
||||
_loudness += abs(*reinterpret_cast<int16_t*>(soundByteArray.data() + _currentSendPosition + i)) /
|
||||
_loudness += abs(*reinterpret_cast<int16_t*>(_audioData.data() + _currentSendPosition + i)) /
|
||||
(MAX_SAMPLE_VALUE / 2.0f);
|
||||
}
|
||||
_loudness /= (float)(bytesToCopy / sizeof(int16_t));
|
||||
|
@ -203,7 +210,7 @@ void AudioInjector::injectToMixer() {
|
|||
|
||||
// copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet
|
||||
memcpy(injectAudioPacket.data() + numPreAudioDataBytes,
|
||||
soundByteArray.data() + _currentSendPosition, bytesToCopy);
|
||||
_audioData.data() + _currentSendPosition, bytesToCopy);
|
||||
|
||||
// grab our audio mixer from the NodeList, if it exists
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
@ -217,7 +224,7 @@ void AudioInjector::injectToMixer() {
|
|||
|
||||
// send two packets before the first sleep so the mixer can start playback right away
|
||||
|
||||
if (_currentSendPosition != bytesToCopy && _currentSendPosition < soundByteArray.size()) {
|
||||
if (_currentSendPosition != bytesToCopy && _currentSendPosition < _audioData.size()) {
|
||||
// not the first packet and not done
|
||||
// sleep for the appropriate time
|
||||
int usecToSleep = (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - timer.nsecsElapsed() / 1000;
|
||||
|
@ -227,7 +234,7 @@ void AudioInjector::injectToMixer() {
|
|||
}
|
||||
}
|
||||
|
||||
if (shouldLoop && _currentSendPosition >= soundByteArray.size()) {
|
||||
if (shouldLoop && _currentSendPosition >= _audioData.size()) {
|
||||
_currentSendPosition = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class AudioInjector : public QObject {
|
|||
public:
|
||||
AudioInjector(QObject* parent);
|
||||
AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
||||
AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions);
|
||||
~AudioInjector();
|
||||
|
||||
bool isFinished() const { return _isFinished; }
|
||||
|
@ -51,7 +52,7 @@ private:
|
|||
void injectToMixer();
|
||||
void injectLocally();
|
||||
|
||||
Sound* _sound;
|
||||
QByteArray _audioData;
|
||||
AudioInjectorOptions _options;
|
||||
bool _shouldStop;
|
||||
float _loudness;
|
||||
|
|
|
@ -43,28 +43,32 @@ void AudioScriptingInterface::stopAllInjectors() {
|
|||
}
|
||||
|
||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||
|
||||
AudioInjector* injector = new AudioInjector(sound, injectorOptions);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
||||
injector->moveToThread(injectorThread);
|
||||
|
||||
// start injecting when the injector thread starts
|
||||
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
||||
|
||||
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
||||
connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater);
|
||||
connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
|
||||
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
|
||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||
|
||||
injectorThread->start();
|
||||
|
||||
_activeInjectors.append(QPointer<AudioInjector>(injector));
|
||||
|
||||
return injector;
|
||||
if (sound) {
|
||||
AudioInjector* injector = new AudioInjector(sound, injectorOptions);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
||||
injector->moveToThread(injectorThread);
|
||||
|
||||
// start injecting when the injector thread starts
|
||||
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
||||
|
||||
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
||||
connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater);
|
||||
connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
|
||||
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
|
||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||
|
||||
injectorThread->start();
|
||||
|
||||
_activeInjectors.append(QPointer<AudioInjector>(injector));
|
||||
|
||||
return injector;
|
||||
} else {
|
||||
qDebug() << "AudioScriptingInterface::playSound called with null Sound object.";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::stopInjector(AudioInjector* injector) {
|
||||
|
|
|
@ -29,96 +29,27 @@
|
|||
#include "AudioEditBuffer.h"
|
||||
#include "Sound.h"
|
||||
|
||||
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, Sound* const& in) {
|
||||
return engine->newQObject(in);
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in) {
|
||||
return engine->newQObject(in.data());
|
||||
}
|
||||
|
||||
void soundFromScriptValue(const QScriptValue& object, Sound*& out) {
|
||||
out = qobject_cast<Sound*>(object.toQObject());
|
||||
void soundFromScriptValue(const QScriptValue &object, SharedSoundPointer &out) {
|
||||
out = SharedSoundPointer(qobject_cast<Sound*>(object.toQObject()));
|
||||
qDebug() << "Sound from script value" << out.data();
|
||||
}
|
||||
|
||||
// procedural audio version of Sound
|
||||
Sound::Sound(float volume, float frequency, float duration, float decay, QObject* parent) :
|
||||
QObject(parent),
|
||||
_isStereo(false)
|
||||
{
|
||||
static char monoAudioData[MAX_PACKET_SIZE];
|
||||
static int16_t* monoAudioSamples = (int16_t*)(monoAudioData);
|
||||
|
||||
float t;
|
||||
const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float)SAMPLE_RATE * 1000.0;
|
||||
const float MAX_VOLUME = 32000.f;
|
||||
const float MAX_DURATION = 2.f;
|
||||
const float MIN_AUDIBLE_VOLUME = 0.001f;
|
||||
const float NOISE_MAGNITUDE = 0.02f;
|
||||
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||
int numSamples = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; // we add sounds in chunks of this many samples
|
||||
|
||||
int chunkStartingSample = 0;
|
||||
float waveFrequency = (frequency / SAMPLE_RATE) * TWO_PI;
|
||||
while (volume > 0.f) {
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
t = (float)chunkStartingSample + (float)i;
|
||||
float sample = sinf(t * waveFrequency);
|
||||
sample += ((randFloat() - 0.5f) * NOISE_MAGNITUDE);
|
||||
sample *= volume * MAX_VOLUME;
|
||||
|
||||
monoAudioSamples[i] = glm::clamp((int)sample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
volume *= (1.f - decay);
|
||||
}
|
||||
// add the monoAudioSamples to our actual output Byte Array
|
||||
_byteArray.append(monoAudioData, numSamples * sizeof(int16_t));
|
||||
chunkStartingSample += numSamples;
|
||||
duration = glm::clamp(duration - (AUDIO_CALLBACK_MSECS / 1000.f), 0.f, MAX_DURATION);
|
||||
//qDebug() << "decaying... _duration=" << _duration;
|
||||
if (duration == 0.f || (volume < MIN_AUDIBLE_VOLUME)) {
|
||||
volume = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sound::Sound(const QUrl& sampleURL, bool isStereo, QObject* parent) :
|
||||
QObject(parent),
|
||||
Sound::Sound(const QUrl& url, bool isStereo) :
|
||||
Resource(url),
|
||||
_isStereo(isStereo),
|
||||
_hasDownloaded(false)
|
||||
_isReady(false)
|
||||
{
|
||||
// assume we have a QApplication or QCoreApplication instance and use the
|
||||
// QNetworkAccess manager to grab the raw audio file at the given URL
|
||||
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
|
||||
qDebug() << "Requesting audio file" << sampleURL.toDisplayString();
|
||||
|
||||
QNetworkReply* soundDownload = networkAccessManager.get(QNetworkRequest(sampleURL));
|
||||
connect(soundDownload, &QNetworkReply::finished, this, &Sound::replyFinished);
|
||||
connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)),
|
||||
this, SLOT(replyError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
Sound::Sound(const QByteArray byteArray, QObject* parent) :
|
||||
QObject(parent),
|
||||
_byteArray(byteArray),
|
||||
_isStereo(false),
|
||||
_hasDownloaded(true)
|
||||
{
|
||||
}
|
||||
|
||||
void Sound::append(const QByteArray byteArray) {
|
||||
_byteArray.append(byteArray);
|
||||
}
|
||||
|
||||
void Sound::replyFinished() {
|
||||
|
||||
QNetworkReply* reply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
|
||||
void Sound::downloadFinished(QNetworkReply* reply) {
|
||||
// replace our byte array with the downloaded data
|
||||
QByteArray rawAudioByteArray = reply->readAll();
|
||||
|
||||
// foreach(QByteArray b, reply->rawHeaderList())
|
||||
// qDebug() << b.constData() << ": " << reply->rawHeader(b).constData();
|
||||
|
||||
if (reply->hasRawHeader("Content-Type")) {
|
||||
|
||||
QByteArray headerContentType = reply->rawHeader("Content-Type");
|
||||
|
@ -141,12 +72,7 @@ void Sound::replyFinished() {
|
|||
qDebug() << "Network reply without 'Content-Type'.";
|
||||
}
|
||||
|
||||
_hasDownloaded = true;
|
||||
}
|
||||
|
||||
void Sound::replyError(QNetworkReply::NetworkError code) {
|
||||
QNetworkReply* reply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
qDebug() << "Error downloading sound file at" << reply->url().toString() << "-" << reply->errorString();
|
||||
_isReady = true;
|
||||
}
|
||||
|
||||
void Sound::downSample(const QByteArray& rawAudioByteArray) {
|
||||
|
|
|
@ -16,38 +16,37 @@
|
|||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtScript/qscriptengine.h>
|
||||
|
||||
class Sound : public QObject {
|
||||
#include <ResourceCache.h>
|
||||
|
||||
class Sound : public Resource {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool downloaded READ hasDownloaded)
|
||||
Q_PROPERTY(bool downloaded READ isReady)
|
||||
public:
|
||||
Sound(const QUrl& sampleURL, bool isStereo = false, QObject* parent = NULL);
|
||||
Sound(float volume, float frequency, float duration, float decay, QObject* parent = NULL);
|
||||
Sound(const QByteArray byteArray, QObject* parent = NULL);
|
||||
void append(const QByteArray byteArray);
|
||||
Sound(const QUrl& url, bool isStereo = false);
|
||||
|
||||
bool isStereo() const { return _isStereo; }
|
||||
bool hasDownloaded() const { return _hasDownloaded; }
|
||||
|
||||
bool isReady() const { return _isReady; }
|
||||
|
||||
const QByteArray& getByteArray() { return _byteArray; }
|
||||
|
||||
private:
|
||||
QByteArray _byteArray;
|
||||
bool _isStereo;
|
||||
bool _hasDownloaded;
|
||||
bool _isReady;
|
||||
|
||||
void trimFrames();
|
||||
void downSample(const QByteArray& rawAudioByteArray);
|
||||
void interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& outputAudioByteArray);
|
||||
|
||||
private slots:
|
||||
void replyFinished();
|
||||
void replyError(QNetworkReply::NetworkError code);
|
||||
|
||||
virtual void downloadFinished(QNetworkReply* reply);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Sound*)
|
||||
typedef QSharedPointer<Sound> SharedSoundPointer;
|
||||
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, Sound* const& in);
|
||||
void soundFromScriptValue(const QScriptValue& object, Sound*& out);
|
||||
Q_DECLARE_METATYPE(SharedSoundPointer)
|
||||
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in);
|
||||
void soundFromScriptValue(const QScriptValue& object, SharedSoundPointer& out);
|
||||
|
||||
#endif // hifi_Sound_h
|
||||
|
|
43
libraries/audio/src/SoundCache.cpp
Normal file
43
libraries/audio/src/SoundCache.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// SoundCache.cpp
|
||||
// libraries/audio/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-11-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
|
||||
//
|
||||
|
||||
#include <qthread.h>
|
||||
|
||||
#include "SoundCache.h"
|
||||
|
||||
static int soundPointerMetaTypeId = qRegisterMetaType<SharedSoundPointer>();
|
||||
|
||||
SoundCache& SoundCache::getInstance() {
|
||||
static SoundCache staticInstance;
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
SoundCache::SoundCache(QObject* parent) :
|
||||
ResourceCache(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SharedSoundPointer SoundCache::getSound(const QUrl& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
SharedSoundPointer result;
|
||||
QMetaObject::invokeMethod(this, "getSound", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
return getResource(url).staticCast<Sound>();
|
||||
}
|
||||
|
||||
QSharedPointer<Resource> SoundCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||
bool delayLoad, const void* extra) {
|
||||
qDebug() << "Requesting sound at" << url.toString();
|
||||
return QSharedPointer<Resource>(new Sound(url), &Resource::allReferencesCleared);
|
||||
}
|
34
libraries/audio/src/SoundCache.h
Normal file
34
libraries/audio/src/SoundCache.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// SoundCache.h
|
||||
// libraries/audio/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-11-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_SoundCache_h
|
||||
#define hifi_SoundCache_h
|
||||
|
||||
#include <ResourceCache.h>
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
/// Scriptable interface for sound loading.
|
||||
class SoundCache : public ResourceCache {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static SoundCache& getInstance();
|
||||
|
||||
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
|
||||
|
||||
protected:
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url,
|
||||
const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra);
|
||||
private:
|
||||
SoundCache(QObject* parent = NULL);
|
||||
};
|
||||
|
||||
#endif // hifi_SoundCache_h
|
|
@ -168,7 +168,7 @@ void Player::setupAudioThread() {
|
|||
_audioThread = new QThread();
|
||||
_options.position = _avatar->getPosition();
|
||||
_options.orientation = _avatar->getOrientation();
|
||||
_injector.reset(new AudioInjector(_recording->getAudio(), _options), &QObject::deleteLater);
|
||||
_injector.reset(new AudioInjector(_recording->getAudioData(), _options), &QObject::deleteLater);
|
||||
_injector->moveToThread(_audioThread);
|
||||
_audioThread->start();
|
||||
QMetaObject::invokeMethod(_injector.data(), "injectAudio", Qt::QueuedConnection);
|
||||
|
|
|
@ -43,13 +43,6 @@ void RecordingFrame::setBlendshapeCoefficients(QVector<float> blendshapeCoeffici
|
|||
_blendshapeCoefficients = blendshapeCoefficients;
|
||||
}
|
||||
|
||||
Recording::Recording() : _audio(NULL) {
|
||||
}
|
||||
|
||||
Recording::~Recording() {
|
||||
delete _audio;
|
||||
}
|
||||
|
||||
int Recording::getLength() const {
|
||||
if (_timestamps.isEmpty()) {
|
||||
return 0;
|
||||
|
@ -77,19 +70,10 @@ void Recording::addFrame(int timestamp, RecordingFrame &frame) {
|
|||
_frames << frame;
|
||||
}
|
||||
|
||||
void Recording::addAudioPacket(const QByteArray& byteArray) {
|
||||
if (!_audio) {
|
||||
_audio = new Sound(byteArray);
|
||||
return;
|
||||
}
|
||||
_audio->append(byteArray);
|
||||
}
|
||||
|
||||
void Recording::clear() {
|
||||
_timestamps.clear();
|
||||
_frames.clear();
|
||||
delete _audio;
|
||||
_audio = NULL;
|
||||
_audioData.clear();
|
||||
}
|
||||
|
||||
void writeVec3(QDataStream& stream, const glm::vec3& value) {
|
||||
|
@ -324,7 +308,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) {
|
|||
fileStream << buffer;
|
||||
}
|
||||
|
||||
fileStream << recording->_audio->getByteArray();
|
||||
fileStream << recording->getAudioData();
|
||||
|
||||
qint64 writingTime = timer.restart();
|
||||
// Write data length and CRC-16
|
||||
|
@ -367,7 +351,7 @@ void writeRecordingToFile(RecordingPointer recording, const QString& filename) {
|
|||
|
||||
qDebug() << "Recording:";
|
||||
qDebug() << "Total frames:" << recording->getFrameNumber();
|
||||
qDebug() << "Audio array:" << recording->getAudio()->getByteArray().size();
|
||||
qDebug() << "Audio array:" << recording->getAudioData().size();
|
||||
}
|
||||
|
||||
qint64 checksumTime = timer.elapsed();
|
||||
|
@ -642,7 +626,7 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, const QString
|
|||
|
||||
qDebug() << "Recording:";
|
||||
qDebug() << "Total frames:" << recording->getFrameNumber();
|
||||
qDebug() << "Audio array:" << recording->getAudio()->getByteArray().size();
|
||||
qDebug() << "Audio array:" << recording->getAudioData().size();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,6 @@ public:
|
|||
/// Stores a recording
|
||||
class Recording {
|
||||
public:
|
||||
Recording();
|
||||
~Recording();
|
||||
|
||||
bool isEmpty() const { return _timestamps.isEmpty(); }
|
||||
int getLength() const; // in ms
|
||||
|
||||
|
@ -58,11 +55,11 @@ public:
|
|||
int getFrameNumber() const { return _frames.size(); }
|
||||
qint32 getFrameTimestamp(int i) const;
|
||||
const RecordingFrame& getFrame(int i) const;
|
||||
Sound* getAudio() const { return _audio; }
|
||||
const QByteArray& getAudioData() const { return _audioData; }
|
||||
|
||||
protected:
|
||||
void addFrame(int timestamp, RecordingFrame& frame);
|
||||
void addAudioPacket(const QByteArray& byteArray);
|
||||
void addAudioPacket(const QByteArray& byteArray) { _audioData.append(byteArray); }
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
@ -70,7 +67,7 @@ private:
|
|||
QVector<qint32> _timestamps;
|
||||
QVector<RecordingFrame> _frames;
|
||||
|
||||
Sound* _audio;
|
||||
QByteArray _audioData;
|
||||
|
||||
friend class Recorder;
|
||||
friend class Player;
|
||||
|
|
|
@ -28,6 +28,7 @@ const float EntityItem::DEFAULT_GLOW_LEVEL = 0.0f;
|
|||
const float EntityItem::DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
|
||||
const float EntityItem::DEFAULT_MASS = 1.0f;
|
||||
const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL;
|
||||
const QString EntityItem::DEFAULT_USER_DATA = QString("");
|
||||
const float EntityItem::DEFAULT_DAMPING = 0.5f;
|
||||
const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0);
|
||||
const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second
|
||||
|
@ -71,6 +72,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
|||
_gravity = DEFAULT_GRAVITY;
|
||||
_damping = DEFAULT_DAMPING;
|
||||
_lifetime = DEFAULT_LIFETIME;
|
||||
_userData = DEFAULT_USER_DATA;
|
||||
_registrationPoint = DEFAULT_REGISTRATION_POINT;
|
||||
_angularVelocity = DEFAULT_ANGULAR_VELOCITY;
|
||||
_angularDamping = DEFAULT_ANGULAR_DAMPING;
|
||||
|
@ -123,6 +125,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
requestedProperties += PROP_IGNORE_FOR_COLLISIONS;
|
||||
requestedProperties += PROP_COLLISIONS_WILL_MOVE;
|
||||
requestedProperties += PROP_LOCKED;
|
||||
requestedProperties += PROP_USER_DATA;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -239,6 +242,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, getIgnoreForCollisions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData());
|
||||
|
||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||
requestedProperties,
|
||||
|
@ -502,6 +506,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint;
|
||||
|
@ -758,6 +763,7 @@ EntityItemProperties EntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignoreForCollisions, getIgnoreForCollisions);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionsWillMove, getCollisionsWillMove);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData);
|
||||
|
||||
properties._defaultSettings = false;
|
||||
|
||||
|
@ -794,6 +800,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, setIgnoreForCollisions);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, setCollisionsWillMove);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||
|
||||
if (somethingChanged) {
|
||||
somethingChangedNotification(); // notify derived classes that something has changed
|
||||
|
|
|
@ -252,6 +252,10 @@ public:
|
|||
bool getLocked() const { return _locked; }
|
||||
void setLocked(bool value) { _locked = value; }
|
||||
|
||||
static const QString DEFAULT_USER_DATA;
|
||||
const QString& getUserData() const { return _userData; }
|
||||
void setUserData(const QString& value) { _userData = value; }
|
||||
|
||||
// TODO: We need to get rid of these users of getRadius()...
|
||||
float getRadius() const;
|
||||
|
||||
|
@ -292,6 +296,7 @@ protected:
|
|||
bool _ignoreForCollisions;
|
||||
bool _collisionsWillMove;
|
||||
bool _locked;
|
||||
QString _userData;
|
||||
|
||||
// NOTE: Radius support is obsolete, but these private helper functions are available for this class to
|
||||
// parse old data streams
|
||||
|
|
|
@ -37,6 +37,7 @@ EntityItemProperties::EntityItemProperties() :
|
|||
_gravity(EntityItem::DEFAULT_GRAVITY),
|
||||
_damping(EntityItem::DEFAULT_DAMPING),
|
||||
_lifetime(EntityItem::DEFAULT_LIFETIME),
|
||||
_userData(EntityItem::DEFAULT_USER_DATA),
|
||||
_script(EntityItem::DEFAULT_SCRIPT),
|
||||
_registrationPoint(EntityItem::DEFAULT_REGISTRATION_POINT),
|
||||
_angularVelocity(EntityItem::DEFAULT_ANGULAR_VELOCITY),
|
||||
|
@ -53,6 +54,7 @@ EntityItemProperties::EntityItemProperties() :
|
|||
_gravityChanged(false),
|
||||
_dampingChanged(false),
|
||||
_lifetimeChanged(false),
|
||||
_userDataChanged(false),
|
||||
_scriptChanged(false),
|
||||
_registrationPointChanged(false),
|
||||
_angularVelocityChanged(false),
|
||||
|
@ -223,6 +225,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_CUTOFF, cutoff);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LOCKED, locked);
|
||||
CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures);
|
||||
CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
@ -276,6 +279,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(cutoff);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(locked);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(textures);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(userData);
|
||||
|
||||
// Sitting properties support
|
||||
QScriptValue sittingPoints = engine->newObject();
|
||||
|
@ -350,6 +354,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(cutoff, setCutoff);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(textures, setTextures);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(userData, setUserData);
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
@ -512,6 +517,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, properties.getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, properties.getUserData());
|
||||
}
|
||||
if (propertyCount > 0) {
|
||||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
@ -722,6 +728,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_USER_DATA, setUserData);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
@ -764,6 +771,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_gravityChanged = true;
|
||||
_dampingChanged = true;
|
||||
_lifetimeChanged = true;
|
||||
_userDataChanged = true;
|
||||
_scriptChanged = true;
|
||||
_registrationPointChanged = true;
|
||||
_angularVelocityChanged = true;
|
||||
|
|
|
@ -81,8 +81,9 @@ enum EntityPropertyList {
|
|||
// used by Model entities
|
||||
PROP_TEXTURES,
|
||||
PROP_ANIMATION_SETTINGS,
|
||||
PROP_USER_DATA,
|
||||
|
||||
PROP_LAST_ITEM = PROP_ANIMATION_SETTINGS
|
||||
PROP_LAST_ITEM = PROP_USER_DATA
|
||||
};
|
||||
|
||||
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
|
||||
|
@ -156,9 +157,13 @@ public:
|
|||
|
||||
float getDamping() const { return _damping; }
|
||||
void setDamping(float value) { _damping = value; _dampingChanged = true; }
|
||||
|
||||
|
||||
float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity
|
||||
void setLifetime(float value) { _lifetime = value; _lifetimeChanged = true; } /// set the lifetime in seconds for the entity
|
||||
|
||||
const QString& getUserData() const { return _userData; }
|
||||
void setUserData(const QString& value) { _userData = value; _userDataChanged = true; }
|
||||
|
||||
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
|
||||
quint64 getCreated() const { return _created; }
|
||||
void setCreated(quint64 usecTime) { _created = usecTime; }
|
||||
|
@ -216,6 +221,7 @@ public:
|
|||
bool gravityChanged() const { return _gravityChanged; }
|
||||
bool dampingChanged() const { return _dampingChanged; }
|
||||
bool lifetimeChanged() const { return _lifetimeChanged; }
|
||||
bool userDataChanged() const { return _userDataChanged; }
|
||||
bool scriptChanged() const { return _scriptChanged; }
|
||||
bool dimensionsChanged() const { return _dimensionsChanged; }
|
||||
bool registrationPointChanged() const { return _registrationPointChanged; }
|
||||
|
@ -315,6 +321,7 @@ private:
|
|||
glm::vec3 _gravity;
|
||||
float _damping;
|
||||
float _lifetime;
|
||||
QString _userData;
|
||||
QString _script;
|
||||
glm::vec3 _registrationPoint;
|
||||
glm::vec3 _angularVelocity;
|
||||
|
@ -331,6 +338,7 @@ private:
|
|||
bool _gravityChanged;
|
||||
bool _dampingChanged;
|
||||
bool _lifetimeChanged;
|
||||
bool _userDataChanged;
|
||||
bool _scriptChanged;
|
||||
bool _registrationPointChanged;
|
||||
bool _angularVelocityChanged;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue