mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-08 07:57:46 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into reverb_smoothing
Conflicts: libraries/audio-client/src/AudioClient.cpp libraries/audio-client/src/AudioClient.h
This commit is contained in:
commit
b59aaf8a0f
134 changed files with 2138 additions and 1573 deletions
|
@ -125,6 +125,8 @@ if (NOT ANDROID)
|
|||
add_subdirectory(interface)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(tools)
|
||||
else ()
|
||||
endif ()
|
||||
|
||||
if (ANDROID OR DESKTOP_GVR)
|
||||
add_subdirectory(gvr-interface)
|
||||
endif ()
|
|
@ -208,7 +208,7 @@ void Agent::run() {
|
|||
|
||||
_scriptEngine.init(); // must be done before we set up the viewers
|
||||
|
||||
_scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance());
|
||||
_scriptEngine.registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
|
||||
_scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer);
|
||||
_entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener());
|
||||
|
|
|
@ -136,7 +136,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
|||
|
||||
// Create Singleton objects on main thread
|
||||
NetworkAccessManager::getInstance();
|
||||
SoundCache::getInstance();
|
||||
auto soundCache = DependencyManager::get<SoundCache>();
|
||||
}
|
||||
|
||||
void AssignmentClient::sendAssignmentRequest() {
|
||||
|
|
|
@ -147,3 +147,14 @@ void EntityServer::pruneDeletedEntities() {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) {
|
||||
bool wantEditLogging = false;
|
||||
readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging);
|
||||
qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging));
|
||||
|
||||
|
||||
EntityTree* tree = static_cast<EntityTree*>(_tree);
|
||||
tree->setWantEditLogging(wantEditLogging);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent);
|
||||
|
||||
virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode);
|
||||
virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject);
|
||||
|
||||
public slots:
|
||||
void pruneDeletedEntities();
|
||||
|
|
|
@ -271,9 +271,10 @@ void MetavoxelSession::handleMessage(const QVariant& message) {
|
|||
_lodPacketNumber = _sequencer.getIncomingPacketNumber();
|
||||
|
||||
} else if (userType == MetavoxelEditMessage::Type) {
|
||||
QMetaObject::invokeMethod(_sender->getServer(), "applyEdit", Q_ARG(const MetavoxelEditMessage&,
|
||||
message.value<MetavoxelEditMessage>()));
|
||||
|
||||
if (_node->getCanAdjustLocks()) {
|
||||
QMetaObject::invokeMethod(_sender->getServer(), "applyEdit",
|
||||
Q_ARG(const MetavoxelEditMessage&, message.value<MetavoxelEditMessage>()));
|
||||
}
|
||||
} else if (userType == QMetaType::QVariantList) {
|
||||
foreach (const QVariant& element, message.toList()) {
|
||||
handleMessage(element);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{
|
||||
"name": "access_token",
|
||||
"label": "Access Token",
|
||||
"help": "This is an access token generated on the <a href='https://data.highfidelity.io/user/security' target='_blank'>My Security</a> page of your High Fidelity account.<br/>Generate a token with the 'domains' scope and paste it here.<br/>This is required to associate this domain-server with a domain in your account."
|
||||
"help": "This is an access token generated on the <a href='https://metaverse.highfidelity.io/user/security' target='_blank'>My Security</a> page of your High Fidelity account.<br/>Generate a token with the 'domains' scope and paste it here.<br/>This is required to associate this domain-server with a domain in your account."
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
|
@ -30,7 +30,7 @@
|
|||
},
|
||||
{
|
||||
"value": "disabled",
|
||||
"label": "None: use the network information I have entered for this domain at data.highfidelity.io"
|
||||
"label": "None: use the network information I have entered for this domain at metaverse.highfidelity.io"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -409,6 +409,13 @@
|
|||
"default": "",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "wantEditLogging",
|
||||
"type": "checkbox",
|
||||
"help": "Logging of all edits to entities",
|
||||
"default": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "verboseDebug",
|
||||
"type": "checkbox",
|
||||
|
|
|
@ -652,7 +652,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
|
|||
clickedButton.attr('disabled', 'disabled')
|
||||
|
||||
// get a list of user domains from data-web
|
||||
data_web_domains_url = "https://data.highfidelity.io/api/v1/domains?access_token="
|
||||
data_web_domains_url = "https://metaverse.highfidelity.io/api/v1/domains?access_token="
|
||||
$.getJSON(data_web_domains_url + Settings.initialValues.metaverse.access_token, function(data){
|
||||
|
||||
modal_buttons = {
|
||||
|
@ -682,7 +682,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
|
|||
modal_buttons["success"] = {
|
||||
label: 'Create new domain',
|
||||
callback: function() {
|
||||
window.open("https://data.highfidelity.io/user/domains", '_blank');
|
||||
window.open("https://metaverse.highfidelity.io/user/domains", '_blank');
|
||||
}
|
||||
}
|
||||
modal_body = "<p>You do not have any domains in your High Fidelity account." +
|
||||
|
|
|
@ -32,10 +32,4 @@ Script.update.connect(function() {
|
|||
injector = Audio.playSound(sound, audioOptions);
|
||||
print("Playing: " + injector);
|
||||
}
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
if (injector !== null) {
|
||||
injector.stop();
|
||||
}
|
||||
});
|
|
@ -85,10 +85,10 @@ function checkHands(deltaTime) {
|
|||
var chord = Controller.getTriggerValue(chordHand);
|
||||
|
||||
if (volume > 1.0) volume = 1.0;
|
||||
if ((chord > 0.1) && Audio.isInjectorPlaying(soundPlaying)) {
|
||||
if ((chord > 0.1) && soundPlaying.isPlaying) {
|
||||
// If chord finger trigger pulled, stop current chord
|
||||
print("stopped sound");
|
||||
Audio.stopInjector(soundPlaying);
|
||||
soundPlaying.stop();
|
||||
}
|
||||
|
||||
var BUTTON_COUNT = 6;
|
||||
|
@ -132,16 +132,21 @@ function checkHands(deltaTime) {
|
|||
}
|
||||
|
||||
function playChord(position, volume) {
|
||||
if (Audio.isInjectorPlaying(soundPlaying)) {
|
||||
if (soundPlaying.isPlaying) {
|
||||
print("stopped sound");
|
||||
Audio.stopInjector(soundPlaying);
|
||||
soundPlaying.stop();
|
||||
}
|
||||
|
||||
print("Played sound: " + whichChord + " at volume " + options.volume);
|
||||
soundPlaying = Audio.playSound(chords[guitarSelector + whichChord], {
|
||||
position: position,
|
||||
volume: volume
|
||||
});
|
||||
if (!soundPlaying) {
|
||||
soundPlaying = Audio.playSound(chords[guitarSelector + whichChord], {
|
||||
position: position,
|
||||
volume: volume
|
||||
});
|
||||
} else {
|
||||
soundPlaying.restart();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function keyPressEvent(event) {
|
||||
|
|
|
@ -105,15 +105,7 @@ var toolBar = (function () {
|
|||
newSphereButton,
|
||||
newLightButton,
|
||||
newTextButton,
|
||||
browseModelsButton,
|
||||
loadURLMenuItem,
|
||||
loadFileMenuItem,
|
||||
menuItemWidth,
|
||||
menuItemOffset,
|
||||
menuItemHeight,
|
||||
menuItemMargin = 5,
|
||||
menuTextColor = { red: 255, green: 255, blue: 255 },
|
||||
menuBackgroundColor = { red: 18, green: 66, blue: 66 };
|
||||
browseModelsButton;
|
||||
|
||||
function initialize() {
|
||||
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL);
|
||||
|
@ -145,34 +137,6 @@ var toolBar = (function () {
|
|||
visible: true
|
||||
});
|
||||
|
||||
menuItemOffset = toolBar.height / 3 + 2;
|
||||
menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2;
|
||||
|
||||
loadURLMenuItem = Overlays.addOverlay("text", {
|
||||
height: menuItemHeight,
|
||||
backgroundColor: menuBackgroundColor,
|
||||
topMargin: menuItemMargin,
|
||||
text: "Model URL",
|
||||
alpha: 0.9,
|
||||
backgroundAlpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
loadFileMenuItem = Overlays.addOverlay("text", {
|
||||
height: menuItemHeight,
|
||||
backgroundColor: menuBackgroundColor,
|
||||
topMargin: menuItemMargin,
|
||||
text: "Model File",
|
||||
alpha: 0.9,
|
||||
backgroundAlpha: 0.9,
|
||||
visible: false
|
||||
});
|
||||
|
||||
menuItemWidth = Math.max(Overlays.textSize(loadURLMenuItem, "Model URL").width,
|
||||
Overlays.textSize(loadFileMenuItem, "Model File").width) + 20;
|
||||
Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth });
|
||||
Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth });
|
||||
|
||||
newCubeButton = toolBar.addTool({
|
||||
imageURL: toolIconUrl + "add-cube.svg",
|
||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
||||
|
@ -211,17 +175,6 @@ var toolBar = (function () {
|
|||
|
||||
}
|
||||
|
||||
function toggleNewModelButton(active) {
|
||||
if (active === undefined) {
|
||||
active = !toolBar.toolSelected(newModelButton);
|
||||
}
|
||||
toolBar.selectTool(newModelButton, active);
|
||||
|
||||
Overlays.editOverlay(loadURLMenuItem, { visible: active });
|
||||
Overlays.editOverlay(loadFileMenuItem, { visible: active });
|
||||
}
|
||||
|
||||
|
||||
that.setActive = function(active) {
|
||||
if (active != isActive) {
|
||||
isActive = active;
|
||||
|
@ -237,6 +190,7 @@ var toolBar = (function () {
|
|||
cameraManager.enable();
|
||||
entityListTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
Window.setFocus();
|
||||
}
|
||||
|
@ -245,7 +199,7 @@ var toolBar = (function () {
|
|||
};
|
||||
|
||||
var RESIZE_INTERVAL = 50;
|
||||
var RESIZE_TIMEOUT = 20000;
|
||||
var RESIZE_TIMEOUT = 120000; // 2 minutes
|
||||
var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL;
|
||||
function addModel(url) {
|
||||
var position;
|
||||
|
@ -306,9 +260,6 @@ var toolBar = (function () {
|
|||
toolsY = (windowDimensions.y - toolBar.height) / 2;
|
||||
|
||||
toolBar.move(toolsX, toolsY);
|
||||
|
||||
Overlays.editOverlay(loadURLMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset });
|
||||
Overlays.editOverlay(loadFileMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset + menuItemHeight });
|
||||
};
|
||||
|
||||
that.mousePressEvent = function (event) {
|
||||
|
@ -324,12 +275,6 @@ var toolBar = (function () {
|
|||
}
|
||||
|
||||
if (newModelButton === toolBar.clicked(clickedOverlay)) {
|
||||
toggleNewModelButton();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (clickedOverlay === loadURLMenuItem) {
|
||||
toggleNewModelButton(false);
|
||||
url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]);
|
||||
if (url !== null && url !== "") {
|
||||
addModel(url);
|
||||
|
@ -337,22 +282,7 @@ var toolBar = (function () {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (clickedOverlay === loadFileMenuItem) {
|
||||
toggleNewModelButton(false);
|
||||
|
||||
file = Window.browse("Select your model file ...",
|
||||
Settings.getValue("LastModelUploadLocation").path(),
|
||||
"Model files (*.fst *.fbx)");
|
||||
//"Model files (*.fst *.fbx *.svo)");
|
||||
if (file !== null) {
|
||||
Settings.setValue("LastModelUploadLocation", file);
|
||||
modelUploader.upload(file, addModel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (browseModelsButton === toolBar.clicked(clickedOverlay)) {
|
||||
toggleNewModelButton(false);
|
||||
url = Window.s3Browse(".*(fbx|FBX)");
|
||||
if (url !== null && url !== "") {
|
||||
addModel(url);
|
||||
|
@ -425,7 +355,7 @@ var toolBar = (function () {
|
|||
placingEntityID = Entities.addEntity({
|
||||
type: "Text",
|
||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
||||
dimensions: { x: 0.5, y: 0.3, z: 0.01 },
|
||||
dimensions: { x: 0.65, y: 0.3, z: 0.01 },
|
||||
backgroundColor: { red: 64, green: 64, blue: 64 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: "some text",
|
||||
|
@ -443,8 +373,6 @@ var toolBar = (function () {
|
|||
|
||||
that.cleanup = function () {
|
||||
toolBar.cleanup();
|
||||
Overlays.deleteOverlay(loadURLMenuItem);
|
||||
Overlays.deleteOverlay(loadFileMenuItem);
|
||||
};
|
||||
|
||||
return that;
|
||||
|
@ -606,7 +534,9 @@ function highlightEntityUnderCursor(position, accurateRay) {
|
|||
|
||||
function mouseReleaseEvent(event) {
|
||||
if (placingEntityID) {
|
||||
selectionManager.setSelections([placingEntityID]);
|
||||
if (isActive) {
|
||||
selectionManager.setSelections([placingEntityID]);
|
||||
}
|
||||
placingEntityID = null;
|
||||
}
|
||||
if (isActive && selectionManager.hasSelection()) {
|
||||
|
@ -1029,9 +959,18 @@ PropertiesTool = function(opts) {
|
|||
selectionManager.saveProperties();
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
var properties = selectionManager.savedProperties[selectionManager.selections[i].id];
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
dimensions: properties.naturalDimensions,
|
||||
});
|
||||
var naturalDimensions = properties.naturalDimensions;
|
||||
|
||||
// If any of the natural dimensions are not 0, resize
|
||||
if (properties.type == "Model" && naturalDimensions.x == 0
|
||||
&& naturalDimensions.y == 0 && naturalDimensions.z == 0) {
|
||||
Window.alert("Cannot reset entity to its natural dimensions: Model URL"
|
||||
+ " is invalid or the model has not yet been loaded.");
|
||||
} else {
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
dimensions: properties.naturalDimensions,
|
||||
});
|
||||
}
|
||||
}
|
||||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
|
|
|
@ -48,7 +48,8 @@
|
|||
this.turnSounds = new Array();
|
||||
this.moveSound = null;
|
||||
this.turnSound = null;
|
||||
this.injector = null;
|
||||
this.moveInjector = null;
|
||||
this.turnInjector = null;
|
||||
|
||||
var debug = false;
|
||||
var displayRotateTargets = true; // change to false if you don't want the rotate targets
|
||||
|
@ -92,9 +93,14 @@
|
|||
}
|
||||
if (this.moveSound && this.moveSound.downloaded) {
|
||||
if (debug) {
|
||||
print("playMoveSound() --- calling this.injector = Audio.playSound(this.moveSound...)");
|
||||
print("playMoveSound() --- calling this.moveInjector = Audio.playSound(this.moveSound...)");
|
||||
}
|
||||
|
||||
if (!this.moveInjector) {
|
||||
this.moveInjector = Audio.playSound(this.moveSound, { position: this.properties.position, loop: true, volume: 0.1 });
|
||||
} else {
|
||||
this.moveInjector.restart();
|
||||
}
|
||||
this.injector = Audio.playSound(this.moveSound, { position: this.properties.position, loop: true, volume: 0.1 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,9 +111,13 @@
|
|||
}
|
||||
if (this.turnSound && this.turnSound.downloaded) {
|
||||
if (debug) {
|
||||
print("playTurnSound() --- calling this.injector = Audio.playSound(this.turnSound...)");
|
||||
print("playTurnSound() --- calling this.turnInjector = Audio.playSound(this.turnSound...)");
|
||||
}
|
||||
if (!this.turnInjector) {
|
||||
this.turnInjector = Audio.playSound(this.turnSound, { position: this.properties.position, loop: true, volume: 0.1 });
|
||||
} else {
|
||||
this.turnInjector.restart();
|
||||
}
|
||||
this.injector = Audio.playSound(this.turnSound, { position: this.properties.position, loop: true, volume: 0.1 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +126,11 @@
|
|||
if (debug) {
|
||||
print("stopSound()");
|
||||
}
|
||||
if (this.injector) {
|
||||
Audio.stopInjector(this.injector);
|
||||
this.injector = null;
|
||||
if (this.turnInjector) {
|
||||
this.turnInjector.stop();
|
||||
}
|
||||
if (this.moveInjector) {
|
||||
this.moveInjector.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +186,7 @@
|
|||
|
||||
this.move = function(mouseEvent) {
|
||||
this.updatePosition(mouseEvent);
|
||||
if (this.injector === null) {
|
||||
if (this.moveInjector === null || !this.moveInjector.isPlaying) {
|
||||
this.playMoveSound();
|
||||
}
|
||||
};
|
||||
|
@ -233,7 +245,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (this.injector === null) {
|
||||
if (this.turnInjector === null || !this.turnInjector.isPlaying) {
|
||||
this.playTurnSound();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -75,14 +75,14 @@ function maybePlaySound(deltaTime) {
|
|||
//print("number playing = " + numPlaying);
|
||||
}
|
||||
for (var i = 0; i < playing.length; i++) {
|
||||
if (!Audio.isInjectorPlaying(playing[i].audioId)) {
|
||||
if (!playing[i].audioId.isPlaying) {
|
||||
Entities.deleteEntity(playing[i].entityId);
|
||||
if (useLights) {
|
||||
Entities.deleteEntity(playing[i].lightId);
|
||||
}
|
||||
playing.splice(i, 1);
|
||||
} else {
|
||||
var loudness = Audio.getLoudness(playing[i].audioId);
|
||||
var loudness = playing[i].audioId.loudness;
|
||||
var newColor = { red: playing[i].color.red, green: playing[i].color.green, blue: playing[i].color.blue };
|
||||
if (loudness > 0.05) {
|
||||
newColor.red *= (1.0 - loudness);
|
||||
|
|
|
@ -76,9 +76,6 @@ function scriptEnding() {
|
|||
if (entity != null) {
|
||||
Entities.deleteEntity(entity);
|
||||
}
|
||||
if (injector != null) {
|
||||
injector.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Script.update.connect(update);
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
//
|
||||
|
||||
|
||||
print("BUTTERFLIES START");
|
||||
|
||||
|
||||
var numButterflies = 25;
|
||||
|
||||
|
||||
|
@ -109,7 +112,7 @@ function updateButterflies(deltaTime) {
|
|||
var properties = Entities.getEntityProperties(butterflies[i]);
|
||||
if (Vec3.length(Vec3.subtract(properties.position, flockPosition)) > range) {
|
||||
Entities.editEntity(butterflies[i], { position: flockPosition } );
|
||||
} else if (properties.velocity.y < 0.0) {
|
||||
} else if (properties.velocity.y <= 0.0) {
|
||||
// If falling, Create a new direction and impulse
|
||||
var HORIZ_SCALE = 0.50;
|
||||
var VERT_SCALE = 0.50;
|
||||
|
@ -139,3 +142,5 @@ Script.scriptEnding.connect(function() {
|
|||
Entities.deleteEntity(butterflies[i]);
|
||||
}
|
||||
});
|
||||
|
||||
print("BUTTERFLIES END");
|
||||
|
|
|
@ -168,14 +168,16 @@
|
|||
</script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div>
|
||||
<div id="entity-list-header">
|
||||
<input type="button" id="refresh" value="Refresh"></button>
|
||||
<input type="button" id="teleport" value="Teleport"></button>
|
||||
<input type="button" id="delete" style="background-color: rgb(244, 64, 64); float: right" value="Delete"></button>
|
||||
</div>
|
||||
|
||||
<div id="entity-list">
|
||||
<input type="text" class="search" id="filter" placeholder="Filter" />
|
||||
<div id="search-area">
|
||||
<input type="text" class="search" id="filter" placeholder="Filter" />
|
||||
</div>
|
||||
<table id="entity-table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
var elModelAnimationSettings = document.getElementById("property-model-animation-settings");
|
||||
var elModelTextures = document.getElementById("property-model-textures");
|
||||
var elModelOriginalTextures = document.getElementById("property-model-original-textures");
|
||||
var elModelShapeType = document.getElementById("property-model-shape");
|
||||
|
||||
var elTextSections = document.querySelectorAll(".text-section");
|
||||
var elTextText = document.getElementById("property-text-text");
|
||||
|
@ -258,6 +259,7 @@
|
|||
elModelAnimationSettings.value = properties.animationSettings;
|
||||
elModelTextures.value = properties.textures;
|
||||
elModelOriginalTextures.value = properties.originalTextures;
|
||||
elModelShapeType.value = properties.shapeType;
|
||||
}
|
||||
|
||||
if (properties.type != "Text") {
|
||||
|
@ -404,6 +406,7 @@
|
|||
elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex'));
|
||||
elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings'));
|
||||
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
|
||||
elModelShapeType.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeType'));
|
||||
|
||||
elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text'));
|
||||
elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight'));
|
||||
|
@ -664,6 +667,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="model-section property">
|
||||
<div class="label">Shape Type</div>
|
||||
<div class="value">
|
||||
<select name="SelectShapeType" id="property-model-shape" name="SelectShapeType">
|
||||
<option value=0>None</option>
|
||||
<option value=1>Box</option>
|
||||
<option value=2>Sphere</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="text-section property">
|
||||
<div class="label">Text</div>
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
elPosY.value = origin.y.toFixed(2);
|
||||
}
|
||||
|
||||
if (data.minorGridSpacing !== undefined) {
|
||||
elMinorSpacing.value = data.minorGridSpacing;
|
||||
if (data.minorGridWidth !== undefined) {
|
||||
elMinorSpacing.value = data.minorGridWidth;
|
||||
}
|
||||
|
||||
if (data.majorGridEvery !== undefined) {
|
||||
|
@ -57,7 +57,7 @@
|
|||
origin: {
|
||||
y: elPosY.value,
|
||||
},
|
||||
minorGridSpacing: elMinorSpacing.value,
|
||||
minorGridWidth: elMinorSpacing.value,
|
||||
majorGridEvery: elMajorSpacing.value,
|
||||
gridColor: gridColor,
|
||||
colorIndex: gridColorIndex,
|
||||
|
|
|
@ -86,6 +86,20 @@ input[type=button] {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
#entity-list-header {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#search-area {
|
||||
width: 100%;
|
||||
padding: 0.5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#search-area input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
textarea, input {
|
||||
margin: 0;
|
||||
padding: 1.5pt;
|
||||
|
@ -120,6 +134,7 @@ table#entity-table {
|
|||
}
|
||||
|
||||
#entity-table tr.selected {
|
||||
color: rgb(43, 43, 43);
|
||||
background-color: #AAA;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ modelUploader = (function () {
|
|||
//svoBuffer,
|
||||
mapping,
|
||||
geometry,
|
||||
API_URL = "https://data.highfidelity.io/api/v1/models",
|
||||
API_URL = "https://metaverse.highfidelity.io/api/v1/models",
|
||||
MODEL_URL = "http://public.highfidelity.io/models/content",
|
||||
NAME_FIELD = "name",
|
||||
SCALE_FIELD = "scale",
|
||||
|
|
|
@ -55,7 +55,9 @@ var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.st
|
|||
var currentDrone = null;
|
||||
|
||||
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.stereo.raw")
|
||||
var latinInjector = null;
|
||||
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.stereo.raw")
|
||||
var elevatorInjector = null;
|
||||
var currentMuzakInjector = null;
|
||||
var currentSound = null;
|
||||
|
||||
|
@ -140,7 +142,11 @@ function drawLobby() {
|
|||
|
||||
if (droneSound.downloaded) {
|
||||
// start the drone sound
|
||||
currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME });
|
||||
if (!currentDrone) {
|
||||
currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME });
|
||||
} else {
|
||||
currentDrone.restart();
|
||||
}
|
||||
}
|
||||
|
||||
// start one of our muzak sounds
|
||||
|
@ -152,7 +158,7 @@ var places = {};
|
|||
|
||||
function changeLobbyTextures() {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", "https://data.highfidelity.io/api/v1/places?limit=21", false);
|
||||
req.open("GET", "https://metaverse.highfidelity.io/api/v1/places?limit=21", false);
|
||||
req.send();
|
||||
|
||||
places = JSON.parse(req.responseText).data.places;
|
||||
|
@ -173,6 +179,26 @@ function changeLobbyTextures() {
|
|||
|
||||
var MUZAK_VOLUME = 0.1;
|
||||
|
||||
function playCurrentSound(secondOffset) {
|
||||
if (currentSound == latinSound) {
|
||||
if (!latinInjector) {
|
||||
latinInjector = Audio.playSound(latinSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME });
|
||||
} else {
|
||||
latinInjector.restart();
|
||||
}
|
||||
|
||||
currentMuzakInjector = latinInjector;
|
||||
} else if (currentSound == elevatorSound) {
|
||||
if (!elevatorInjector) {
|
||||
elevatorInjector = Audio.playSound(elevatorSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME });
|
||||
} else {
|
||||
elevatorInjector.restart();
|
||||
}
|
||||
|
||||
currentMuzakInjector = elevatorInjector;
|
||||
}
|
||||
}
|
||||
|
||||
function playNextMuzak() {
|
||||
if (panelWall) {
|
||||
if (currentSound == latinSound) {
|
||||
|
@ -184,8 +210,8 @@ function playNextMuzak() {
|
|||
currentSound = latinSound;
|
||||
}
|
||||
}
|
||||
|
||||
currentMuzakInjector = Audio.playSound(currentSound, { localOnly: true, volume: MUZAK_VOLUME });
|
||||
|
||||
playCurrentSound(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,10 +226,11 @@ function playRandomMuzak() {
|
|||
currentSound = elevatorSound;
|
||||
}
|
||||
|
||||
if (currentSound) {
|
||||
if (currentSound) {
|
||||
// pick a random number of seconds from 0-10 to offset the muzak
|
||||
var secondOffset = Math.random() * 10;
|
||||
currentMuzakInjector = Audio.playSound(currentSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME });
|
||||
|
||||
playCurrentSound(secondOffset);
|
||||
} else {
|
||||
currentMuzakInjector = null;
|
||||
}
|
||||
|
@ -227,10 +254,9 @@ function cleanupLobby() {
|
|||
panelWall = false;
|
||||
orbShell = false;
|
||||
|
||||
Audio.stopInjector(currentDrone);
|
||||
currentDrone = null;
|
||||
currentDrone.stop();
|
||||
currentMuzakInjector.stop();
|
||||
|
||||
Audio.stopInjector(currentMuzakInjector);
|
||||
currentMuzakInjector = null;
|
||||
|
||||
places = {};
|
||||
|
@ -354,7 +380,7 @@ function update(deltaTime) {
|
|||
Overlays.editOverlay(descriptionText, { position: textOverlayPosition() });
|
||||
|
||||
// if the reticle is up then we may need to play the next muzak
|
||||
if (currentMuzakInjector && !Audio.isInjectorPlaying(currentMuzakInjector)) {
|
||||
if (currentMuzakInjector && !currentMuzakInjector.isPlaying) {
|
||||
playNextMuzak();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,20 +21,13 @@ var offset = Vec3.normalize(Quat.getFront(MyAvatar.orientation));
|
|||
var position = Vec3.sum(MyAvatar.position, offset);
|
||||
|
||||
function update(deltaTime) {
|
||||
if (!Audio.isInjectorPlaying(soundPlaying)) {
|
||||
soundPlaying = Audio.playSound(sound, {
|
||||
position: position,
|
||||
loop: true
|
||||
});
|
||||
print("Started sound loop");
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
if (Audio.isInjectorPlaying(soundPlaying)) {
|
||||
Audio.stopInjector(soundPlaying);
|
||||
print("Stopped sound loop");
|
||||
}
|
||||
if (sound.downloaded && !soundPlaying) {
|
||||
print("Started sound loop");
|
||||
soundPlaying = Audio.playSound(sound, {
|
||||
position: position,
|
||||
loop: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Script.update.connect(update);
|
||||
|
|
|
@ -32,14 +32,13 @@ var sound = Audio.playSound(soundClip, { position: orbitCenter, loop: true, volu
|
|||
function update(deltaTime) {
|
||||
time += deltaTime;
|
||||
currentPosition = { x: orbitCenter.x + Math.cos(time * SPEED) * RADIUS, y: orbitCenter.y, z: orbitCenter.z + Math.sin(time * SPEED) * RADIUS };
|
||||
trailingLoudness = 0.9 * trailingLoudness + 0.1 * Audio.getLoudness(sound);
|
||||
trailingLoudness = 0.9 * trailingLoudness + 0.1 * sound.loudness;
|
||||
Entities.editEntity( objectId, { position: currentPosition, color: { red: Math.min(trailingLoudness * 2000, 255), green: 0, blue: 0 } } );
|
||||
Audio.setInjectorOptions(sound, { position: currentPosition });
|
||||
sound.setOptions({ position: currentPosition });
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
Entities.deleteEntity(objectId);
|
||||
Audio.stopInjector(sound);
|
||||
});
|
||||
|
||||
Script.update.connect(update);
|
|
@ -30,7 +30,7 @@ var playing = false;
|
|||
var ball = false;
|
||||
|
||||
function maybePlaySound(deltaTime) {
|
||||
if (sound.downloaded) {
|
||||
if (sound.downloaded && !soundPlaying) {
|
||||
var properties = {
|
||||
type: "Sphere",
|
||||
position: options.position,
|
||||
|
@ -45,11 +45,9 @@ function maybePlaySound(deltaTime) {
|
|||
}
|
||||
|
||||
function scriptEnding() {
|
||||
if (Audio.isInjectorPlaying(soundPlaying)) {
|
||||
Audio.stopInjector(soundPlaying);
|
||||
Entities.deleteEntity(ball);
|
||||
print("Stopped sound.");
|
||||
}
|
||||
if (ball) {
|
||||
Entities.deleteEntity(ball);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect a call back that happens every frame
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <HifiSockAddr.h>
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
|
||||
#include <HifiSockAddr.h>
|
||||
|
||||
class QThread;
|
||||
|
||||
class Client : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Client(QObject* parent = 0);
|
||||
|
||||
virtual void cleanupBeforeQuit() = 0;
|
||||
protected:
|
||||
|
||||
void setupNetworking();
|
||||
virtual void processVerifiedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& incomingPacket);
|
||||
private slots:
|
||||
|
|
|
@ -86,6 +86,13 @@ GVRInterface::GVRInterface(int argc, char* argv[]) :
|
|||
QTimer* idleTimer = new QTimer(this);
|
||||
connect(idleTimer, &QTimer::timeout, this, &GVRInterface::idle);
|
||||
idleTimer->start(0);
|
||||
|
||||
// call our quit handler before we go down
|
||||
connect(this, &QCoreApplication::aboutToQuit, this, &GVRInterface::handleApplicationQuit);
|
||||
}
|
||||
|
||||
void GVRInterface::handleApplicationQuit() {
|
||||
_client->cleanupBeforeQuit();
|
||||
}
|
||||
|
||||
void GVRInterface::idle() {
|
||||
|
|
|
@ -53,6 +53,7 @@ private slots:
|
|||
void handleApplicationStateChange(Qt::ApplicationState state);
|
||||
void idle();
|
||||
private:
|
||||
void handleApplicationQuit();
|
||||
|
||||
void enterVRMode();
|
||||
void leaveVRMode();
|
||||
|
|
|
@ -37,7 +37,7 @@ RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString
|
|||
DependencyManager::set<AvatarHashMap>();
|
||||
|
||||
// get our audio client setup on its own thread
|
||||
QThread* audioThread = new QThread(this);
|
||||
QThread* audioThread = new QThread();
|
||||
auto audioClient = DependencyManager::set<AudioClient>();
|
||||
|
||||
audioClient->setPositionGetter(getPositionForAudio);
|
||||
|
@ -45,6 +45,8 @@ RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString
|
|||
|
||||
audioClient->moveToThread(audioThread);
|
||||
connect(audioThread, &QThread::started, audioClient.data(), &AudioClient::start);
|
||||
connect(audioClient.data(), &AudioClient::destroyed, audioThread, &QThread::quit);
|
||||
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
||||
|
||||
audioThread->start();
|
||||
|
||||
|
@ -68,15 +70,13 @@ void RenderingClient::sendAvatarPacket() {
|
|||
_fakeAvatar.sendIdentityPacket();
|
||||
}
|
||||
|
||||
RenderingClient::~RenderingClient() {
|
||||
auto audioClient = DependencyManager::get<AudioClient>();
|
||||
|
||||
// stop the audio client
|
||||
QMetaObject::invokeMethod(audioClient.data(), "stop", Qt::BlockingQueuedConnection);
|
||||
void RenderingClient::cleanupBeforeQuit() {
|
||||
|
||||
// ask the audio thread to quit and wait until it is done
|
||||
audioClient->thread()->quit();
|
||||
audioClient->thread()->wait();
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"stop", Qt::BlockingQueuedConnection);
|
||||
|
||||
// destroy the AudioClient so it and its thread will safely go down
|
||||
DependencyManager::destroy<AudioClient>();
|
||||
}
|
||||
|
||||
void RenderingClient::processVerifiedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& incomingPacket) {
|
||||
|
|
|
@ -26,7 +26,6 @@ class RenderingClient : public Client {
|
|||
Q_OBJECT
|
||||
public:
|
||||
RenderingClient(QObject* parent = 0, const QString& launchURLString = QString());
|
||||
~RenderingClient();
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
const glm::quat& getOrientation() const { return _orientation; }
|
||||
|
@ -35,6 +34,8 @@ public:
|
|||
static glm::vec3 getPositionForAudio() { return _instance->getPosition(); }
|
||||
static glm::quat getOrientationForAudio() { return _instance->getOrientation(); }
|
||||
|
||||
virtual void cleanupBeforeQuit();
|
||||
|
||||
private slots:
|
||||
void goToLocation(const glm::vec3& newPosition,
|
||||
bool hasOrientationChange, const glm::quat& newOrientation,
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include <HFBackEvent.h>
|
||||
#include <LogHandler.h>
|
||||
#include <MainWindow.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <OctalCode.h>
|
||||
#include <OctreeSceneStats.h>
|
||||
|
@ -156,18 +157,27 @@ public:
|
|||
bool nativeEventFilter(const QByteArray &eventType, void* msg, long* result) Q_DECL_OVERRIDE {
|
||||
if (eventType == "windows_generic_MSG") {
|
||||
MSG* message = (MSG*)msg;
|
||||
|
||||
if (message->message == UWM_IDENTIFY_INSTANCES) {
|
||||
*result = UWM_IDENTIFY_INSTANCES;
|
||||
return true;
|
||||
}
|
||||
if (message->message == WM_SHOWWINDOW) {
|
||||
Application::getInstance()->getWindow()->showNormal();
|
||||
|
||||
if (message->message == UWM_SHOW_APPLICATION) {
|
||||
MainWindow* applicationWindow = Application::getInstance()->getWindow();
|
||||
if (applicationWindow->isMinimized()) {
|
||||
applicationWindow->showNormal(); // Restores to windowed or maximized state appropriately.
|
||||
}
|
||||
Application::getInstance()->setActiveWindow(applicationWindow); // Flashes the taskbar icon if not focus.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message->message == WM_COPYDATA) {
|
||||
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam);
|
||||
QUrl url = QUrl((const char*)(pcds->lpData));
|
||||
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,6 +212,8 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
auto addressManager = DependencyManager::set<AddressManager>();
|
||||
auto nodeList = DependencyManager::set<NodeList>(NodeType::Agent, listenPort);
|
||||
auto geometryCache = DependencyManager::set<GeometryCache>();
|
||||
auto scriptCache = DependencyManager::set<ScriptCache>();
|
||||
auto soundCache = DependencyManager::set<SoundCache>();
|
||||
auto glowEffect = DependencyManager::set<GlowEffect>();
|
||||
auto faceshift = DependencyManager::set<Faceshift>();
|
||||
auto audio = DependencyManager::set<AudioClient>();
|
||||
|
@ -319,7 +331,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), &_datagramProcessor, SLOT(processDatagrams()));
|
||||
|
||||
// put the audio processing on a separate thread
|
||||
QThread* audioThread = new QThread(this);
|
||||
QThread* audioThread = new QThread();
|
||||
audioThread->setObjectName("Audio Thread");
|
||||
|
||||
auto audioIO = DependencyManager::get<AudioClient>();
|
||||
|
@ -329,7 +341,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
audioIO->moveToThread(audioThread);
|
||||
connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start);
|
||||
connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
|
||||
connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit);
|
||||
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
||||
connect(audioIO.data(), &AudioClient::muteToggled, this, &Application::audioMuteToggled);
|
||||
|
||||
audioThread->start();
|
||||
|
||||
|
@ -507,57 +521,65 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
void Application::aboutToQuit() {
|
||||
_aboutToQuit = true;
|
||||
setFullscreen(false); // if you exit while in full screen, you'll get bad behavior when you restart.
|
||||
|
||||
cleanupBeforeQuit();
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
void Application::cleanupBeforeQuit() {
|
||||
// make sure we don't call the idle timer any more
|
||||
delete idleTimer;
|
||||
|
||||
// save state
|
||||
QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
|
||||
_settingsThread.quit();
|
||||
saveSettings();
|
||||
|
||||
_entities.getTree()->setSimulation(NULL);
|
||||
qInstallMessageHandler(NULL);
|
||||
|
||||
_window->saveGeometry();
|
||||
|
||||
int DELAY_TIME = 1000;
|
||||
UserActivityLogger::getInstance().close(DELAY_TIME);
|
||||
|
||||
// make sure we don't call the idle timer any more
|
||||
delete idleTimer;
|
||||
|
||||
// TODO: now that this is in cleanupBeforeQuit do we really need it to stop and force
|
||||
// an event loop to send the packet?
|
||||
UserActivityLogger::getInstance().close();
|
||||
|
||||
// let the avatar mixer know we're out
|
||||
MyAvatar::sendKillAvatar();
|
||||
|
||||
// stop the AudioClient
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"stop", Qt::BlockingQueuedConnection);
|
||||
|
||||
// destroy the AudioClient so it and its thread have a chance to go down safely
|
||||
DependencyManager::destroy<AudioClient>();
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
EntityTree* tree = _entities.getTree();
|
||||
tree->lockForWrite();
|
||||
_entities.getTree()->setSimulation(NULL);
|
||||
tree->unlock();
|
||||
|
||||
qInstallMessageHandler(NULL);
|
||||
|
||||
// ask the datagram processing thread to quit and wait until it is done
|
||||
_nodeThread->quit();
|
||||
_nodeThread->wait();
|
||||
|
||||
// kill any audio injectors that are still around
|
||||
AudioScriptingInterface::getInstance().stopAllInjectors();
|
||||
|
||||
auto audioIO = DependencyManager::get<AudioClient>();
|
||||
|
||||
// stop the audio process
|
||||
QMetaObject::invokeMethod(audioIO.data(), "stop", Qt::BlockingQueuedConnection);
|
||||
|
||||
// ask the audio thread to quit and wait until it is done
|
||||
audioIO->thread()->quit();
|
||||
audioIO->thread()->wait();
|
||||
|
||||
_octreeProcessor.terminate();
|
||||
_entityEditSender.terminate();
|
||||
|
||||
Menu::getInstance()->deleteLater();
|
||||
|
||||
_myAvatar = NULL;
|
||||
|
||||
ModelEntityItem::cleanupLoadedAnimations() ;
|
||||
|
||||
DependencyManager::destroy<GLCanvas>();
|
||||
|
||||
qDebug() << "start destroying ResourceCaches Application::~Application() line:" << __LINE__;
|
||||
DependencyManager::destroy<AnimationCache>();
|
||||
DependencyManager::destroy<TextureCache>();
|
||||
DependencyManager::destroy<GeometryCache>();
|
||||
DependencyManager::destroy<ScriptCache>();
|
||||
DependencyManager::destroy<SoundCache>();
|
||||
qDebug() << "done destroying ResourceCaches Application::~Application() line:" << __LINE__;
|
||||
}
|
||||
|
||||
void Application::initializeGL() {
|
||||
|
@ -2594,6 +2616,9 @@ const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f };
|
|||
const GLfloat WORLD_DIFFUSE_COLOR[] = { 0.6f, 0.525f, 0.525f };
|
||||
const GLfloat WORLD_SPECULAR_COLOR[] = { 0.94f, 0.94f, 0.737f, 1.0f };
|
||||
|
||||
const glm::vec3 GLOBAL_LIGHT_COLOR = { 0.6f, 0.525f, 0.525f };
|
||||
const float GLOBAL_LIGHT_INTENSITY = 1.0f;
|
||||
|
||||
void Application::setupWorldLight() {
|
||||
|
||||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||
|
@ -2608,6 +2633,7 @@ void Application::setupWorldLight() {
|
|||
glLightfv(GL_LIGHT0, GL_SPECULAR, WORLD_SPECULAR_COLOR);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, WORLD_SPECULAR_COLOR);
|
||||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
||||
|
||||
}
|
||||
|
||||
bool Application::shouldRenderMesh(float largestDimension, float distanceToCamera) {
|
||||
|
@ -2814,7 +2840,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
|||
|
||||
{
|
||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY);
|
||||
PROFILE_RANGE("DeferredLighting");
|
||||
PerformanceTimer perfTimer("lighting");
|
||||
DependencyManager::get<DeferredLightingEffect>()->render();
|
||||
|
@ -3452,7 +3478,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance());
|
||||
scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels);
|
||||
|
||||
|
|
|
@ -117,6 +117,8 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-entities-commands.html
|
|||
#ifdef Q_OS_WIN
|
||||
static const UINT UWM_IDENTIFY_INSTANCES =
|
||||
RegisterWindowMessage("UWM_IDENTIFY_INSTANCES_{8AB82783-B74A-4258-955B-8188C22AA0D6}");
|
||||
static const UINT UWM_SHOW_APPLICATION =
|
||||
RegisterWindowMessage("UWM_SHOW_APPLICATION_{71123FD6-3DA8-4DC1-9C27-8A12A6250CBA}");
|
||||
#endif
|
||||
|
||||
class Application;
|
||||
|
@ -408,6 +410,8 @@ private:
|
|||
|
||||
void initDisplay();
|
||||
void init();
|
||||
|
||||
void cleanupBeforeQuit();
|
||||
|
||||
void update(float deltaTime);
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
_windowGeometry("WindowGeometry")
|
||||
_windowGeometry("WindowGeometry"),
|
||||
_windowState("WindowState", 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,13 +35,24 @@ void MainWindow::restoreGeometry() {
|
|||
QRect geometry = _windowGeometry.get(qApp->desktop()->availableGeometry());
|
||||
move(geometry.topLeft());
|
||||
resize(geometry.size());
|
||||
|
||||
// Restore to maximized or full screen after restoring to windowed so that going windowed goes to good position and sizes.
|
||||
Qt::WindowStates state = (Qt::WindowStates)_windowState.get(Qt::WindowNoState);
|
||||
if (state != Qt::WindowNoState) {
|
||||
setWindowState(state);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::saveGeometry() {
|
||||
// Did not use geometry() on purpose,
|
||||
// see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
|
||||
QRect geometry(pos(), size());
|
||||
_windowGeometry.set(geometry);
|
||||
_windowState.set((int)windowState());
|
||||
|
||||
// Save position and size only if windowed so that have good values for windowed after starting maximized or full screen.
|
||||
if (windowState() == Qt::WindowNoState) {
|
||||
QRect geometry(pos(), size());
|
||||
_windowGeometry.set(geometry);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::moveEvent(QMoveEvent* event) {
|
||||
|
|
|
@ -38,6 +38,7 @@ protected:
|
|||
|
||||
private:
|
||||
Setting::Handle<QRect> _windowGeometry;
|
||||
Setting::Handle<int> _windowState;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__MainWindow__) */
|
||||
|
|
|
@ -111,7 +111,7 @@ void drawText(int x, int y, float scale, float radians, int mono,
|
|||
glRotated(double(radians * DEGREES_PER_RADIAN), 0.0, 0.0, 1.0);
|
||||
glScalef(scale / 0.1f, scale / 0.1f, 1.0f);
|
||||
|
||||
glm::vec4 colorV4 = {color[0], color[1], color[3], 1.0f };
|
||||
glm::vec4 colorV4 = {color[0], color[1], color[2], 1.0f };
|
||||
textRenderer(mono)->draw(0, 0, string, colorV4);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
|
|
@ -760,19 +760,19 @@ void SkeletonModel::buildShapes() {
|
|||
Shape::Type type = joint.shapeType;
|
||||
int parentIndex = joint.parentIndex;
|
||||
if (parentIndex == -1 || radius < EPSILON) {
|
||||
type = SHAPE_TYPE_UNKNOWN;
|
||||
} else if (type == SHAPE_TYPE_CAPSULE && halfHeight < EPSILON) {
|
||||
type = INVALID_SHAPE;
|
||||
} else if (type == CAPSULE_SHAPE && halfHeight < EPSILON) {
|
||||
// this shape is forced to be a sphere
|
||||
type = SHAPE_TYPE_SPHERE;
|
||||
type = SPHERE_SHAPE;
|
||||
}
|
||||
Shape* shape = NULL;
|
||||
if (type == SHAPE_TYPE_SPHERE) {
|
||||
if (type == SPHERE_SHAPE) {
|
||||
shape = new VerletSphereShape(radius, &(points[i]));
|
||||
shape->setEntity(this);
|
||||
float mass = massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume());
|
||||
points[i].setMass(mass);
|
||||
totalMass += mass;
|
||||
} else if (type == SHAPE_TYPE_CAPSULE) {
|
||||
} else if (type == CAPSULE_SHAPE) {
|
||||
assert(parentIndex != -1);
|
||||
shape = new VerletCapsuleShape(radius, &(points[parentIndex]), &(points[i]));
|
||||
shape->setEntity(this);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
|
@ -36,7 +37,7 @@ static BOOL CALLBACK enumWindowsCallback(HWND hWnd, LPARAM lParam) {
|
|||
#endif
|
||||
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
int main(int argc, const char* argv[]) {
|
||||
#ifdef Q_OS_WIN
|
||||
// Run only one instance of Interface at a time.
|
||||
HANDLE mutex = CreateMutex(NULL, FALSE, "High Fidelity Interface");
|
||||
|
@ -46,15 +47,32 @@ int main(int argc, const char * argv[]) {
|
|||
HWND otherInstance = NULL;
|
||||
EnumWindows(enumWindowsCallback, (LPARAM)&otherInstance);
|
||||
if (otherInstance) {
|
||||
ShowWindow(otherInstance, SW_RESTORE);
|
||||
SetForegroundWindow(otherInstance);
|
||||
// Show other instance.
|
||||
SendMessage(otherInstance, UWM_SHOW_APPLICATION, 0, 0);
|
||||
|
||||
QUrl url = QUrl(argv[1]);
|
||||
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
||||
COPYDATASTRUCT cds;
|
||||
cds.cbData = strlen(argv[1]) + 1;
|
||||
cds.lpData = (PVOID)argv[1];
|
||||
SendMessage(otherInstance, WM_COPYDATA, 0, (LPARAM)&cds);
|
||||
// Send command line --url value to other instance.
|
||||
if (argc >= 3) {
|
||||
QStringList arguments;
|
||||
for (int i = 0; i < argc; i += 1) {
|
||||
arguments << argv[i];
|
||||
}
|
||||
|
||||
QCommandLineParser parser;
|
||||
QCommandLineOption urlOption("url", "", "value");
|
||||
parser.addOption(urlOption);
|
||||
parser.process(arguments);
|
||||
|
||||
if (parser.isSet(urlOption)) {
|
||||
QUrl url = QUrl(parser.value(urlOption));
|
||||
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
|
||||
QByteArray urlBytes = url.toString().toLatin1();
|
||||
const char* urlChars = urlBytes.data();
|
||||
COPYDATASTRUCT cds;
|
||||
cds.cbData = urlBytes.length() + 1;
|
||||
cds.lpData = (PVOID)urlChars;
|
||||
SendMessage(otherInstance, WM_COPYDATA, 0, (LPARAM)&cds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -788,13 +788,12 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
|
||||
// Audio VU Meter and Mute Icon
|
||||
const int MUTE_ICON_SIZE = 24;
|
||||
const int AUDIO_METER_INSET = 2;
|
||||
const int MUTE_ICON_PADDING = 10;
|
||||
const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET - MUTE_ICON_PADDING;
|
||||
const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 * AUDIO_METER_INSET;
|
||||
const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - MUTE_ICON_PADDING;
|
||||
const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 ;
|
||||
const int AUDIO_METER_HEIGHT = 8;
|
||||
const int AUDIO_METER_GAP = 5;
|
||||
const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET + AUDIO_METER_GAP;
|
||||
const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_GAP;
|
||||
|
||||
int audioMeterY;
|
||||
bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !OculusManager::isConnected();
|
||||
|
@ -847,7 +846,7 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
|
||||
// Draw audio meter background Quad
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X, audioMeterY, AUDIO_METER_WIDTH, AUDIO_METER_HEIGHT,
|
||||
glm::vec4(0, 0, 0, 1));
|
||||
glm::vec4(0.298f, 0.757f, 0.722f, 1));
|
||||
|
||||
if (audioLevel > AUDIO_RED_START) {
|
||||
glm::vec4 quadColor;
|
||||
|
@ -857,10 +856,10 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
quadColor = glm::vec4(1, 1, 1, 1);
|
||||
}
|
||||
// Draw Red Quad
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START,
|
||||
audioMeterY + AUDIO_METER_INSET,
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_RED_START,
|
||||
audioMeterY,
|
||||
audioLevel - AUDIO_RED_START,
|
||||
AUDIO_METER_HEIGHT - AUDIO_METER_INSET, quadColor,
|
||||
AUDIO_METER_HEIGHT, quadColor,
|
||||
_audioRedQuad);
|
||||
|
||||
audioLevel = AUDIO_RED_START;
|
||||
|
@ -874,26 +873,28 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
quadColor = glm::vec4(1, 1, 1, 1);
|
||||
}
|
||||
// Draw Green Quad
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START,
|
||||
audioMeterY + AUDIO_METER_INSET,
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_GREEN_START,
|
||||
audioMeterY,
|
||||
audioLevel - AUDIO_GREEN_START,
|
||||
AUDIO_METER_HEIGHT - AUDIO_METER_INSET, quadColor,
|
||||
AUDIO_METER_HEIGHT, quadColor,
|
||||
_audioGreenQuad);
|
||||
|
||||
audioLevel = AUDIO_GREEN_START;
|
||||
}
|
||||
// Draw Blue Quad
|
||||
glm::vec4 quadColor;
|
||||
if (!isClipping) {
|
||||
quadColor = AUDIO_METER_BLUE;
|
||||
} else {
|
||||
quadColor = glm::vec4(1, 1, 1, 1);
|
||||
|
||||
if (audioLevel >= 0) {
|
||||
glm::vec4 quadColor;
|
||||
if (!isClipping) {
|
||||
quadColor = AUDIO_METER_BLUE;
|
||||
} else {
|
||||
quadColor = glm::vec4(1, 1, 1, 1);
|
||||
}
|
||||
// Draw Blue (low level) quad
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X,
|
||||
audioMeterY,
|
||||
audioLevel, AUDIO_METER_HEIGHT, quadColor,
|
||||
_audioBlueQuad);
|
||||
}
|
||||
// Draw Blue (low level) quad
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET,
|
||||
audioMeterY + AUDIO_METER_INSET,
|
||||
audioLevel, AUDIO_METER_HEIGHT - AUDIO_METER_INSET, quadColor,
|
||||
_audioBlueQuad);
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderStatsAndLogs() {
|
||||
|
|
|
@ -59,8 +59,8 @@ CachesSizeDialog::CachesSizeDialog(QWidget* parent) :
|
|||
void CachesSizeDialog::confirmClicked(bool checked) {
|
||||
DependencyManager::get<AnimationCache>()->setUnusedResourceCacheSize(_animations->value() * BYTES_PER_MEGABYTES);
|
||||
DependencyManager::get<GeometryCache>()->setUnusedResourceCacheSize(_geometries->value() * BYTES_PER_MEGABYTES);
|
||||
ScriptCache::getInstance()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES);
|
||||
SoundCache::getInstance().setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES);
|
||||
DependencyManager::get<ScriptCache>()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES);
|
||||
DependencyManager::get<SoundCache>()->setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES);
|
||||
DependencyManager::get<TextureCache>()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES);
|
||||
|
||||
QDialog::close();
|
||||
|
@ -69,8 +69,8 @@ void CachesSizeDialog::confirmClicked(bool checked) {
|
|||
void CachesSizeDialog::resetClicked(bool checked) {
|
||||
_animations->setValue(DependencyManager::get<AnimationCache>()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
_geometries->setValue(DependencyManager::get<GeometryCache>()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
_scripts->setValue(ScriptCache::getInstance()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
_sounds->setValue(SoundCache::getInstance().getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
_scripts->setValue(DependencyManager::get<ScriptCache>()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
_sounds->setValue(DependencyManager::get<SoundCache>()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
_textures->setValue(DependencyManager::get<TextureCache>()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "ui_loginDialog.h"
|
||||
#include "LoginDialog.h"
|
||||
|
||||
const QString FORGOT_PASSWORD_URL = "https://data.highfidelity.io/users/password/new";
|
||||
const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.io/users/password/new";
|
||||
|
||||
LoginDialog::LoginDialog(QWidget* parent) :
|
||||
FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP),
|
||||
|
|
|
@ -37,7 +37,6 @@ using namespace std;
|
|||
const int STATS_PELS_PER_LINE = 20;
|
||||
|
||||
const int STATS_GENERAL_MIN_WIDTH = 165;
|
||||
const int STATS_BANDWIDTH_MIN_WIDTH = 250;
|
||||
const int STATS_PING_MIN_WIDTH = 190;
|
||||
const int STATS_GEO_MIN_WIDTH = 240;
|
||||
const int STATS_OCTREE_MIN_WIDTH = 410;
|
||||
|
@ -52,7 +51,6 @@ Stats::Stats():
|
|||
_recentMaxPackets(0),
|
||||
_resetRecentMaxPacketsSoon(true),
|
||||
_generalStatsWidth(STATS_GENERAL_MIN_WIDTH),
|
||||
_bandwidthStatsWidth(STATS_BANDWIDTH_MIN_WIDTH),
|
||||
_pingStatsWidth(STATS_PING_MIN_WIDTH),
|
||||
_geoStatsWidth(STATS_GEO_MIN_WIDTH),
|
||||
_octreeStatsWidth(STATS_OCTREE_MIN_WIDTH),
|
||||
|
@ -133,7 +131,6 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
int extraSpace = glCanvas->width() - horizontalOffset -2
|
||||
- STATS_GENERAL_MIN_WIDTH
|
||||
- STATS_BANDWIDTH_MIN_WIDTH
|
||||
- (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0)
|
||||
- STATS_GEO_MIN_WIDTH
|
||||
- STATS_OCTREE_MIN_WIDTH;
|
||||
|
@ -141,7 +138,6 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
int panels = 4;
|
||||
|
||||
_generalStatsWidth = STATS_GENERAL_MIN_WIDTH;
|
||||
_bandwidthStatsWidth = STATS_BANDWIDTH_MIN_WIDTH;
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
|
||||
_pingStatsWidth = STATS_PING_MIN_WIDTH;
|
||||
} else {
|
||||
|
@ -153,13 +149,12 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
|
||||
if (extraSpace > panels) {
|
||||
_generalStatsWidth += (int) extraSpace / panels;
|
||||
_bandwidthStatsWidth += (int) extraSpace / panels;
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
|
||||
_pingStatsWidth += (int) extraSpace / panels;
|
||||
}
|
||||
_geoStatsWidth += (int) extraSpace / panels;
|
||||
_octreeStatsWidth += glCanvas->width() -
|
||||
(_generalStatsWidth + _bandwidthStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||
(_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,14 +226,14 @@ void Stats::display(
|
|||
int totalAvatars = DependencyManager::get<AvatarManager>()->size() - 1;
|
||||
int totalServers = DependencyManager::get<NodeList>()->size();
|
||||
|
||||
lines = _expanded ? 5 : 3;
|
||||
lines = 5;
|
||||
int columnOneWidth = _generalStatsWidth;
|
||||
|
||||
PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up
|
||||
|
||||
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) {
|
||||
|
||||
columnOneWidth = _generalStatsWidth + _bandwidthStatsWidth + _pingStatsWidth + _geoStatsWidth; // 4 columns wide...
|
||||
columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide...
|
||||
// we will also include room for 1 line per timing record and a header of 4 lines
|
||||
lines += 4;
|
||||
|
||||
|
@ -267,11 +262,22 @@ void Stats::display(
|
|||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarNodes.toUtf8().constData(), color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, framesPerSecond.toUtf8().constData(), color);
|
||||
|
||||
QString packetsPerSecondString = QString("Packets In/Out: %1/%2").arg(inPacketsPerSecond).arg(outPacketsPerSecond);
|
||||
QString averageMegabitsPerSecond = QString("Mbps In/Out: %1/%2").
|
||||
arg((float)inKbitsPerSecond * 1.0f / 1000.0f).
|
||||
arg((float)outKbitsPerSecond * 1.0f / 1000.0f);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, packetsPerSecondString.toUtf8().constData(), color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, averageMegabitsPerSecond.toUtf8().constData(), color);
|
||||
|
||||
|
||||
// TODO: the display of these timing details should all be moved to JavaScript
|
||||
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) {
|
||||
// Timing details...
|
||||
verticalOffset += STATS_PELS_PER_LINE * 4; // skip 4 lines to be under the other columns
|
||||
verticalOffset += STATS_PELS_PER_LINE * 6; // skip 6 lines to be under the other columns
|
||||
drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font,
|
||||
"-------------------------------------------------------- Function "
|
||||
"------------------------------------------------------- --msecs- -calls--", color);
|
||||
|
@ -294,13 +300,14 @@ void Stats::display(
|
|||
j.toBack();
|
||||
while (j.hasPrevious()) {
|
||||
j.previous();
|
||||
QChar noBreakingSpace = QChar::Nbsp;
|
||||
QString functionName = j.value();
|
||||
const PerformanceTimerRecord& record = allRecords.value(functionName);
|
||||
|
||||
QString perfLine = QString("%1: %2 [%3]").
|
||||
arg(QString(qPrintable(functionName)), 120).
|
||||
arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3).
|
||||
arg(record.getCount(), 6);
|
||||
arg(QString(qPrintable(functionName)), 120, noBreakingSpace).
|
||||
arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace).
|
||||
arg((int)record.getCount(), 6, 10, noBreakingSpace);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, perfLine.toUtf8().constData(), color);
|
||||
|
@ -308,30 +315,9 @@ void Stats::display(
|
|||
}
|
||||
|
||||
|
||||
|
||||
verticalOffset = 0;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + 1;
|
||||
|
||||
if (columnOneWidth == _generalStatsWidth) {
|
||||
drawBackground(backgroundColor, horizontalOffset, 0, _bandwidthStatsWidth, lines * STATS_PELS_PER_LINE + 10);
|
||||
}
|
||||
horizontalOffset += 5;
|
||||
|
||||
QString packetsPerSecondString = QString("Packets In/Out: %1/%2").arg(inPacketsPerSecond).arg(outPacketsPerSecond);
|
||||
QString averageMegabitsPerSecond = QString("Mbps In/Out: %1/%2").
|
||||
arg((float)inKbitsPerSecond * 1.0f / 1000.0f).
|
||||
arg((float)outKbitsPerSecond * 1.0f / 1000.0f);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, packetsPerSecondString.toUtf8().constData(), color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, averageMegabitsPerSecond.toUtf8().constData(), color);
|
||||
|
||||
|
||||
|
||||
verticalOffset = 0;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _bandwidthStatsWidth +1;
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
|
||||
int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingOctreeMax = -1;
|
||||
|
||||
|
@ -411,7 +397,7 @@ void Stats::display(
|
|||
}
|
||||
|
||||
verticalOffset = 0;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _bandwidthStatsWidth + _pingStatsWidth + 2;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + 2;
|
||||
}
|
||||
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
@ -491,7 +477,7 @@ void Stats::display(
|
|||
}
|
||||
|
||||
verticalOffset = 0;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _bandwidthStatsWidth + _pingStatsWidth + _geoStatsWidth + 3;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3;
|
||||
|
||||
lines = _expanded ? 14 : 3;
|
||||
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() {
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) :
|
||||
|
|
|
@ -20,6 +20,7 @@ const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
|||
const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
|
||||
const float DEFAULT_MARGIN = 0.1f;
|
||||
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
|
||||
const float LINE_SCALE_RATIO = 1.2f;
|
||||
|
||||
Text3DOverlay::Text3DOverlay() :
|
||||
|
@ -104,8 +105,6 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, quadColor);
|
||||
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation
|
||||
|
||||
// Same font properties as textSize()
|
||||
TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
float maxHeight = (float)textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
|
@ -229,22 +228,12 @@ Text3DOverlay* Text3DOverlay::createClone() const {
|
|||
}
|
||||
|
||||
QSizeF Text3DOverlay::textSize(const QString& text) const {
|
||||
auto textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
auto extents = textRenderer->computeExtent(text);
|
||||
|
||||
QFont font(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); // Same font properties as render()
|
||||
QFontMetrics fontMetrics(font);
|
||||
const float TEXT_SCALE_ADJUST = 1.025f; // Experimentally detemined for the specified font
|
||||
const int TEXT_HEIGHT_ADJUST = -10;
|
||||
float scaleFactor = _lineHeight * TEXT_SCALE_ADJUST * LINE_SCALE_RATIO / (float)FIXED_FONT_POINT_SIZE;
|
||||
float maxHeight = (float)textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
QStringList lines = text.split(QRegExp("\r\n|\r|\n"));
|
||||
|
||||
float width = 0.0f;
|
||||
for (int i = 0; i < lines.count(); i += 1) {
|
||||
width = std::max(width, scaleFactor * (float)fontMetrics.width(qPrintable(lines[i])));
|
||||
}
|
||||
|
||||
float height = lines.count() * scaleFactor * (float)(fontMetrics.height() + TEXT_HEIGHT_ADJUST);
|
||||
|
||||
return QSizeF(width, height);
|
||||
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,19 +165,8 @@ QScriptValue TextOverlay::getProperty(const QString& property) {
|
|||
}
|
||||
|
||||
QSizeF TextOverlay::textSize(const QString& text) const {
|
||||
auto textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT);
|
||||
auto extents = textRenderer->computeExtent(text);
|
||||
|
||||
QFont font(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); // Same font properties as render()
|
||||
QFontMetrics fontMetrics(font);
|
||||
const int TEXT_HEIGHT_ADJUST = -2; // Experimentally determined for the specified font
|
||||
|
||||
QStringList lines = text.split(QRegExp("\r\n|\r|\n"));
|
||||
|
||||
int width = 0;
|
||||
for (int i = 0; i < lines.count(); i += 1) {
|
||||
width = std::max(width, fontMetrics.width(qPrintable(lines[i])));
|
||||
}
|
||||
|
||||
int height = lines.count() * (fontMetrics.height() + TEXT_HEIGHT_ADJUST);
|
||||
|
||||
return QSizeF(width, height);
|
||||
return QSizeF(extents.x, extents.y);
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
<string><style type="text/css">
|
||||
a { text-decoration: none; color: #267077;}
|
||||
</style>
|
||||
Invalid username or password. <a href="https://data.highfidelity.io/password/new">Recover?</a></string>
|
||||
Invalid username or password. <a href="https://metaverse.highfidelity.io/password/new">Recover?</a></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
|
@ -458,7 +458,7 @@ border-radius: 4px; padding-top: 1px;</string>
|
|||
<string><style type="text/css">
|
||||
a { text-decoration: none; color: #267077;}
|
||||
</style>
|
||||
<a href="https://data.highfidelity.io/password/new">Recover password?</a></string>
|
||||
<a href="https://metaverse.highfidelity.io/password/new">Recover password?</a></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -139,8 +139,14 @@ AudioClient::AudioClient() :
|
|||
}
|
||||
|
||||
AudioClient::~AudioClient() {
|
||||
gverb_free(_gverb);
|
||||
gverb_free(_gverbLocal);
|
||||
stop();
|
||||
|
||||
if (_gverbLocal) {
|
||||
gverb_free(_gverbLocal);
|
||||
}
|
||||
if (_gverb) {
|
||||
gverb_free(_gverb);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioClient::reset() {
|
||||
|
@ -533,9 +539,9 @@ bool AudioClient::switchOutputToAudioDevice(const QString& outputDeviceName) {
|
|||
ty_gverb* AudioClient::createGverbFilter() {
|
||||
// Initialize a new gverb instance
|
||||
ty_gverb* filter = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
||||
_reverbOptions->getTailLevel());
|
||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
||||
_reverbOptions->getTailLevel());
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
@ -989,14 +995,16 @@ bool AudioClient::outputLocalInjector(bool isStereo, qreal volume, AudioInjector
|
|||
|
||||
QAudioOutput* localOutput = new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName),
|
||||
localFormat,
|
||||
injector);
|
||||
injector->getLocalBuffer());
|
||||
|
||||
localOutput->setVolume(volume);
|
||||
|
||||
// move the localOutput to the same thread as the local injector buffer
|
||||
localOutput->moveToThread(injector->getLocalBuffer()->thread());
|
||||
|
||||
// have it be cleaned up when that injector is done
|
||||
connect(injector, &AudioInjector::finished, localOutput, &QAudioOutput::stop);
|
||||
// have it be stopped when that local buffer is about to close
|
||||
connect(injector->getLocalBuffer(), &AudioInjectorLocalBuffer::bufferEmpty, localOutput, &QAudioOutput::stop);
|
||||
connect(injector->getLocalBuffer(), &QIODevice::aboutToClose, localOutput, &QAudioOutput::stop);
|
||||
|
||||
qDebug() << "Starting QAudioOutput for local injector" << localOutput;
|
||||
|
||||
|
@ -1007,7 +1015,6 @@ bool AudioClient::outputLocalInjector(bool isStereo, qreal volume, AudioInjector
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void AudioClient::outputFormatChanged() {
|
||||
int outputFormatChannelCountTimesSampleRate = _outputFormat.channelCount() * _outputFormat.sampleRate();
|
||||
_outputFrameSize = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * outputFormatChannelCountTimesSampleRate / _desiredOutputFormat.sampleRate();
|
||||
|
|
|
@ -188,6 +188,10 @@ protected:
|
|||
AudioClient();
|
||||
~AudioClient();
|
||||
|
||||
virtual void customDeleter() {
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
private:
|
||||
void outputFormatChanged();
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDataStream>
|
||||
|
||||
#include <NodeList.h>
|
||||
|
@ -21,79 +22,77 @@
|
|||
|
||||
#include "AudioInjector.h"
|
||||
|
||||
QScriptValue injectorToScriptValue(QScriptEngine* engine, AudioInjector* const& in) {
|
||||
return engine->newQObject(in);
|
||||
}
|
||||
|
||||
void injectorFromScriptValue(const QScriptValue& object, AudioInjector*& out) {
|
||||
out = qobject_cast<AudioInjector*>(object.toQObject());
|
||||
}
|
||||
|
||||
AudioInjector::AudioInjector(QObject* parent) :
|
||||
QObject(parent),
|
||||
_options(),
|
||||
_shouldStop(false),
|
||||
_loudness(0.0f),
|
||||
_isFinished(false),
|
||||
_currentSendPosition(0),
|
||||
_localBuffer(NULL)
|
||||
QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) :
|
||||
_audioData(sound->getByteArray()),
|
||||
_options(injectorOptions),
|
||||
_shouldStop(false),
|
||||
_loudness(0.0f),
|
||||
_isFinished(false),
|
||||
_currentSendPosition(0),
|
||||
_localBuffer(NULL)
|
||||
_options(injectorOptions)
|
||||
{
|
||||
}
|
||||
|
||||
AudioInjector::AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions) :
|
||||
_audioData(audioData),
|
||||
_options(injectorOptions),
|
||||
_shouldStop(false),
|
||||
_loudness(0.0f),
|
||||
_isFinished(false),
|
||||
_currentSendPosition(0),
|
||||
_localBuffer(NULL)
|
||||
_options(injectorOptions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AudioInjector::~AudioInjector() {
|
||||
if (_localBuffer) {
|
||||
_localBuffer->stop();
|
||||
void AudioInjector::setIsFinished(bool isFinished) {
|
||||
_isFinished = isFinished;
|
||||
|
||||
if (_isFinished) {
|
||||
emit finished();
|
||||
|
||||
if (_localBuffer) {
|
||||
_localBuffer->stop();
|
||||
_localBuffer->deleteLater();
|
||||
_localBuffer = NULL;
|
||||
}
|
||||
|
||||
_isStarted = false;
|
||||
_shouldStop = false;
|
||||
|
||||
if (_shouldDeleteAfterFinish) {
|
||||
// we've been asked to delete after finishing, trigger a queued deleteLater here
|
||||
qDebug() << "AudioInjector triggering delete from setIsFinished";
|
||||
QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInjector::setOptions(AudioInjectorOptions& options) {
|
||||
_options = options;
|
||||
}
|
||||
|
||||
float AudioInjector::getLoudness() {
|
||||
return _loudness;
|
||||
}
|
||||
|
||||
void AudioInjector::injectAudio() {
|
||||
|
||||
// check if we need to offset the sound by some number of seconds
|
||||
if (_options.secondOffset > 0.0f) {
|
||||
if (!_isStarted) {
|
||||
// check if we need to offset the sound by some number of seconds
|
||||
if (_options.secondOffset > 0.0f) {
|
||||
|
||||
// convert the offset into a number of bytes
|
||||
int byteOffset = (int) floorf(AudioConstants::SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f));
|
||||
byteOffset *= sizeof(int16_t);
|
||||
|
||||
_currentSendPosition = byteOffset;
|
||||
} else {
|
||||
_currentSendPosition = 0;
|
||||
}
|
||||
|
||||
// convert the offset into a number of bytes
|
||||
int byteOffset = (int) floorf(AudioConstants::SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f));
|
||||
byteOffset *= sizeof(int16_t);
|
||||
|
||||
_currentSendPosition = byteOffset;
|
||||
}
|
||||
|
||||
if (_options.localOnly) {
|
||||
injectLocally();
|
||||
if (_options.localOnly) {
|
||||
injectLocally();
|
||||
} else {
|
||||
injectToMixer();
|
||||
}
|
||||
} else {
|
||||
injectToMixer();
|
||||
}
|
||||
qDebug() << "AudioInjector::injectAudio called but already started.";
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInjector::restart() {
|
||||
qDebug() << "Restarting an AudioInjector by stopping and starting over.";
|
||||
stop();
|
||||
setIsFinished(false);
|
||||
QMetaObject::invokeMethod(this, "injectAudio", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void AudioInjector::injectLocally() {
|
||||
|
@ -102,6 +101,7 @@ void AudioInjector::injectLocally() {
|
|||
if (_audioData.size() > 0) {
|
||||
|
||||
_localBuffer = new AudioInjectorLocalBuffer(_audioData, this);
|
||||
|
||||
_localBuffer->open(QIODevice::ReadOnly);
|
||||
_localBuffer->setShouldLoop(_options.loop);
|
||||
|
||||
|
@ -236,6 +236,14 @@ void AudioInjector::injectToMixer() {
|
|||
// send two packets before the first sleep so the mixer can start playback right away
|
||||
|
||||
if (_currentSendPosition != bytesToCopy && _currentSendPosition < _audioData.size()) {
|
||||
|
||||
// process events in case we have been told to stop and be deleted
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
if (_shouldStop) {
|
||||
break;
|
||||
}
|
||||
|
||||
// not the first packet and not done
|
||||
// sleep for the appropriate time
|
||||
int usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000;
|
||||
|
@ -251,8 +259,7 @@ void AudioInjector::injectToMixer() {
|
|||
}
|
||||
}
|
||||
|
||||
_isFinished = true;
|
||||
emit finished();
|
||||
setIsFinished(true);
|
||||
}
|
||||
|
||||
void AudioInjector::stop() {
|
||||
|
@ -260,7 +267,11 @@ void AudioInjector::stop() {
|
|||
|
||||
if (_options.localOnly) {
|
||||
// we're only a local injector, so we can say we are finished right away too
|
||||
_isFinished = true;
|
||||
emit finished();
|
||||
setIsFinished(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInjector::stopAndDeleteLater() {
|
||||
stop();
|
||||
QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define hifi_AudioInjector_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -24,15 +25,18 @@
|
|||
|
||||
class AbstractAudioInterface;
|
||||
|
||||
// In order to make scripting cleaner for the AudioInjector, the script now holds on to the AudioInjector object
|
||||
// until it dies.
|
||||
|
||||
class AudioInjector : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioInjector(QObject* parent);
|
||||
AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
||||
AudioInjector(const QByteArray& audioData, const AudioInjectorOptions& injectorOptions);
|
||||
~AudioInjector();
|
||||
|
||||
bool isFinished() const { return _isFinished; }
|
||||
|
||||
int getCurrentSendPosition() const { return _currentSendPosition; }
|
||||
|
||||
AudioInjectorLocalBuffer* getLocalBuffer() const { return _localBuffer; }
|
||||
|
@ -41,30 +45,37 @@ public:
|
|||
void setLocalAudioInterface(AbstractAudioInterface* localAudioInterface) { _localAudioInterface = localAudioInterface; }
|
||||
public slots:
|
||||
void injectAudio();
|
||||
void restart();
|
||||
|
||||
void stop();
|
||||
void setOptions(AudioInjectorOptions& options);
|
||||
void triggerDeleteAfterFinish() { _shouldDeleteAfterFinish = true; }
|
||||
void stopAndDeleteLater();
|
||||
|
||||
void setOptions(AudioInjectorOptions& options) { _options = options; }
|
||||
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
|
||||
float getLoudness();
|
||||
float getLoudness() const { return _loudness; }
|
||||
bool isPlaying() const { return !_isFinished; }
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private:
|
||||
void injectToMixer();
|
||||
void injectLocally();
|
||||
|
||||
void setIsFinished(bool isFinished);
|
||||
|
||||
QByteArray _audioData;
|
||||
AudioInjectorOptions _options;
|
||||
bool _shouldStop;
|
||||
float _loudness;
|
||||
bool _isFinished;
|
||||
int _currentSendPosition;
|
||||
AbstractAudioInterface* _localAudioInterface;
|
||||
AudioInjectorLocalBuffer* _localBuffer;
|
||||
bool _shouldStop = false;
|
||||
float _loudness = 0.0f;
|
||||
bool _isStarted = false;
|
||||
bool _isFinished = false;
|
||||
bool _shouldDeleteAfterFinish = false;
|
||||
int _currentSendPosition = 0;
|
||||
AbstractAudioInterface* _localAudioInterface = NULL;
|
||||
AudioInjectorLocalBuffer* _localBuffer = NULL;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioInjector*)
|
||||
|
||||
QScriptValue injectorToScriptValue(QScriptEngine* engine, AudioInjector* const& in);
|
||||
void injectorFromScriptValue(const QScriptValue& object, AudioInjector*& out);
|
||||
|
||||
#endif // hifi_AudioInjector_h
|
||||
|
|
|
@ -23,9 +23,18 @@ AudioInjectorLocalBuffer::AudioInjectorLocalBuffer(const QByteArray& rawAudioArr
|
|||
|
||||
void AudioInjectorLocalBuffer::stop() {
|
||||
_isStopped = true;
|
||||
|
||||
QIODevice::close();
|
||||
}
|
||||
|
||||
bool AudioInjectorLocalBuffer::seek(qint64 pos) {
|
||||
if (_isStopped) {
|
||||
return false;
|
||||
} else {
|
||||
return QIODevice::seek(pos);
|
||||
}
|
||||
}
|
||||
|
||||
qint64 AudioInjectorLocalBuffer::readData(char* data, qint64 maxSize) {
|
||||
if (!_isStopped) {
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ public:
|
|||
|
||||
void stop();
|
||||
|
||||
bool seek(qint64 pos);
|
||||
|
||||
qint64 readData(char* data, qint64 maxSize);
|
||||
qint64 writeData(const char* data, qint64 maxSize) { return 0; }
|
||||
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
|
||||
static int soundPointerMetaTypeId = qRegisterMetaType<SharedSoundPointer>();
|
||||
|
||||
SoundCache& SoundCache::getInstance() {
|
||||
static SoundCache staticInstance;
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
SoundCache::SoundCache(QObject* parent) :
|
||||
ResourceCache(parent)
|
||||
{
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
#include "Sound.h"
|
||||
|
||||
/// Scriptable interface for sound loading.
|
||||
class SoundCache : public ResourceCache {
|
||||
class SoundCache : public ResourceCache, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
static SoundCache& getInstance();
|
||||
|
||||
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <gpu/GPUConfig.h>
|
||||
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
#include <TextRenderer.h>
|
||||
|
@ -49,7 +50,12 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
|
|||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
|
||||
// TODO: Determine if we want these entities to have the deferred lighting effect? I think we do, so that the color
|
||||
// used for a sphere, or box have the same look as those used on a text entity.
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram();
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, glm::vec4(toGlm(getBackgroundColorX()), alpha));
|
||||
DependencyManager::get<DeferredLightingEffect>()->releaseSimpleProgram();
|
||||
|
||||
TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f);
|
||||
|
||||
|
|
|
@ -96,11 +96,6 @@ void BoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst
|
|||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
}
|
||||
|
||||
void BoxEntityItem::computeShapeInfo(ShapeInfo& info) const {
|
||||
glm::vec3 halfExtents = 0.5f * getDimensionsInMeters();
|
||||
info.setBox(halfExtents);
|
||||
}
|
||||
|
||||
void BoxEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qDebug() << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
_color[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
|
||||
void computeShapeInfo(ShapeInfo& info) const;
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
|
|
|
@ -57,8 +57,6 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
|||
_collisionsWillMove = ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE;
|
||||
_locked = ENTITY_ITEM_DEFAULT_LOCKED;
|
||||
_userData = ENTITY_ITEM_DEFAULT_USER_DATA;
|
||||
|
||||
recalculateCollisionShape();
|
||||
}
|
||||
|
||||
EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
||||
|
@ -70,7 +68,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
|||
_lastEditedFromRemote = 0;
|
||||
_lastEditedFromRemoteInRemoteTime = 0;
|
||||
_created = UNKNOWN_CREATED_TIME;
|
||||
_physicsInfo = NULL;
|
||||
_dirtyFlags = 0;
|
||||
_changedOnServer = 0;
|
||||
_element = NULL;
|
||||
|
@ -86,7 +83,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
|
|||
_lastEditedFromRemote = 0;
|
||||
_lastEditedFromRemoteInRemoteTime = 0;
|
||||
_created = UNKNOWN_CREATED_TIME;
|
||||
_physicsInfo = NULL;
|
||||
_dirtyFlags = 0;
|
||||
_changedOnServer = 0;
|
||||
_element = NULL;
|
||||
|
@ -541,7 +537,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
|
||||
|
||||
recalculateCollisionShape();
|
||||
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY))) {
|
||||
// NOTE: This code is attempting to "repair" the old data we just got from the server to make it more
|
||||
// closely match where the entities should be if they'd stepped forward in time to "now". The server
|
||||
|
@ -1003,14 +998,7 @@ float EntityItem::getRadius() const {
|
|||
}
|
||||
|
||||
void EntityItem::computeShapeInfo(ShapeInfo& info) const {
|
||||
info.clear();
|
||||
}
|
||||
|
||||
void EntityItem::recalculateCollisionShape() {
|
||||
AACube entityAACube = getMinimumAACube();
|
||||
entityAACube.scale(TREE_SCALE); // scale to meters
|
||||
_collisionShape.setTranslation(entityAACube.calcCenter());
|
||||
_collisionShape.setScale(entityAACube.getScale());
|
||||
info.setParams(getShapeType(), 0.5f * getDimensionsInMeters());
|
||||
}
|
||||
|
||||
const float MIN_POSITION_DELTA = 0.0001f;
|
||||
|
@ -1023,7 +1011,6 @@ const float MIN_SPIN_DELTA = 0.0003f;
|
|||
void EntityItem::updatePosition(const glm::vec3& value) {
|
||||
if (glm::distance(_position, value) * (float)TREE_SCALE > MIN_POSITION_DELTA) {
|
||||
_position = value;
|
||||
recalculateCollisionShape();
|
||||
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||
}
|
||||
}
|
||||
|
@ -1032,7 +1019,6 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) {
|
|||
glm::vec3 position = glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f);
|
||||
if (glm::distance(_position, position) * (float)TREE_SCALE > MIN_POSITION_DELTA) {
|
||||
_position = position;
|
||||
recalculateCollisionShape();
|
||||
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||
}
|
||||
}
|
||||
|
@ -1040,7 +1026,6 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) {
|
|||
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||
if (_dimensions != value) {
|
||||
_dimensions = glm::abs(value);
|
||||
recalculateCollisionShape();
|
||||
_dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS);
|
||||
}
|
||||
}
|
||||
|
@ -1049,7 +1034,6 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) {
|
|||
glm::vec3 dimensions = glm::abs(value) / (float) TREE_SCALE;
|
||||
if (_dimensions != dimensions) {
|
||||
_dimensions = dimensions;
|
||||
recalculateCollisionShape();
|
||||
_dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS);
|
||||
}
|
||||
}
|
||||
|
@ -1057,7 +1041,6 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) {
|
|||
void EntityItem::updateRotation(const glm::quat& rotation) {
|
||||
if (glm::dot(_rotation, rotation) < MIN_ALIGNMENT_DOT) {
|
||||
_rotation = rotation;
|
||||
recalculateCollisionShape();
|
||||
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <AACubeShape.h>
|
||||
#include <AnimationCache.h> // for Animation, AnimationCache, and AnimationPointer classes
|
||||
#include <CollisionInfo.h>
|
||||
#include <Octree.h> // for EncodeBitstreamParams class
|
||||
|
@ -150,7 +149,7 @@ public:
|
|||
glm::vec3 getPositionInMeters() const { return _position * (float) TREE_SCALE; } /// get position in meters
|
||||
|
||||
/// set position in domain scale units (0.0 - 1.0)
|
||||
void setPosition(const glm::vec3& value) { _position = value; recalculateCollisionShape(); }
|
||||
void setPosition(const glm::vec3& value) { _position = value; }
|
||||
void setPositionInMeters(const glm::vec3& value) /// set position in meter units (0.0 - TREE_SCALE)
|
||||
{ setPosition(glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f)); }
|
||||
|
||||
|
@ -162,13 +161,13 @@ public:
|
|||
float getLargestDimension() const { return glm::length(_dimensions); } /// get the largest possible dimension
|
||||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
|
||||
virtual void setDimensions(const glm::vec3& value) { _dimensions = value; recalculateCollisionShape(); }
|
||||
virtual void setDimensions(const glm::vec3& value) { _dimensions = value; }
|
||||
|
||||
/// set dimensions in meter units (0.0 - TREE_SCALE) this will also reset radius appropriately
|
||||
void setDimensionsInMeters(const glm::vec3& value) { setDimensions(value / (float) TREE_SCALE); }
|
||||
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
void setRotation(const glm::quat& rotation) { _rotation = rotation; recalculateCollisionShape(); }
|
||||
void setRotation(const glm::quat& rotation) { _rotation = rotation; }
|
||||
|
||||
float getGlowLevel() const { return _glowLevel; }
|
||||
void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; }
|
||||
|
@ -225,7 +224,7 @@ public:
|
|||
|
||||
/// registration point as ratio of entity
|
||||
void setRegistrationPoint(const glm::vec3& value)
|
||||
{ _registrationPoint = glm::clamp(value, 0.0f, 1.0f); recalculateCollisionShape(); }
|
||||
{ _registrationPoint = glm::clamp(value, 0.0f, 1.0f); }
|
||||
|
||||
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
|
||||
void setAngularVelocity(const glm::vec3& value) { _angularVelocity = value; }
|
||||
|
@ -254,11 +253,12 @@ public:
|
|||
// TODO: We need to get rid of these users of getRadius()...
|
||||
float getRadius() const;
|
||||
|
||||
void applyHardCollision(const CollisionInfo& collisionInfo);
|
||||
virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; }
|
||||
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
|
||||
virtual void computeShapeInfo(ShapeInfo& info) const;
|
||||
|
||||
/// return preferred shape type (actual physical shape may differ)
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; }
|
||||
|
||||
// updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags
|
||||
void updatePosition(const glm::vec3& value);
|
||||
void updatePositionInMeters(const glm::vec3& value);
|
||||
|
@ -277,6 +277,7 @@ public:
|
|||
void updateIgnoreForCollisions(bool value);
|
||||
void updateCollisionsWillMove(bool value);
|
||||
void updateLifetime(float value);
|
||||
virtual void updateShapeType(ShapeType type) { /* do nothing */ }
|
||||
|
||||
uint32_t getDirtyFlags() const { return _dirtyFlags; }
|
||||
void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; }
|
||||
|
@ -297,7 +298,6 @@ protected:
|
|||
static bool _sendPhysicsUpdates;
|
||||
|
||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
||||
virtual void recalculateCollisionShape();
|
||||
|
||||
EntityTypes::EntityType _type;
|
||||
QUuid _id;
|
||||
|
@ -353,11 +353,9 @@ protected:
|
|||
/// set radius in domain scale units (0.0 - 1.0) this will also reset dimensions to be equal for each axis
|
||||
void setRadius(float value);
|
||||
|
||||
AACubeShape _collisionShape;
|
||||
|
||||
// _physicsInfo is a hook reserved for use by the EntitySimulation, which is guaranteed to set _physicsInfo
|
||||
// to a non-NULL value when the EntityItem has a representation in the physics engine.
|
||||
void* _physicsInfo; // only set by EntitySimulation
|
||||
void* _physicsInfo = NULL; // only set by EntitySimulation
|
||||
|
||||
// DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about.
|
||||
uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation
|
||||
|
|
|
@ -64,6 +64,7 @@ EntityItemProperties::EntityItemProperties() :
|
|||
CONSTRUCT_PROPERTY(lineHeight, TextEntityItem::DEFAULT_LINE_HEIGHT),
|
||||
CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR),
|
||||
CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR),
|
||||
CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE),
|
||||
|
||||
_id(UNKNOWN_ENTITY_ID),
|
||||
_idSet(false),
|
||||
|
@ -210,6 +211,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_LINE_HEIGHT, lineHeight);
|
||||
CHECK_PROPERTY_CHANGE(PROP_TEXT_COLOR, textColor);
|
||||
CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor);
|
||||
CHECK_PROPERTY_CHANGE(PROP_SHAPE_TYPE, shapeType);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
@ -268,6 +270,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(shapeType);
|
||||
|
||||
// Sitting properties support
|
||||
QScriptValue sittingPoints = engine->newObject();
|
||||
|
@ -347,6 +350,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(shapeType, setShapeType, ShapeType);
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
@ -510,6 +514,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, properties.getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)(properties.getShapeType()));
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
|
@ -731,6 +736,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
|
@ -820,6 +826,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_lineHeightChanged = true;
|
||||
_textColorChanged = true;
|
||||
_backgroundColorChanged = true;
|
||||
_shapeTypeChanged = true;
|
||||
}
|
||||
|
||||
AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <FBXReader.h> // for SittingPoint
|
||||
#include <PropertyFlags.h>
|
||||
#include <OctreeConstants.h>
|
||||
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "EntityItemID.h"
|
||||
#include "EntityItemPropertiesMacros.h"
|
||||
|
@ -82,8 +82,10 @@ enum EntityPropertyList {
|
|||
PROP_TEXTURES,
|
||||
PROP_ANIMATION_SETTINGS,
|
||||
PROP_USER_DATA,
|
||||
|
||||
PROP_LAST_ITEM = PROP_USER_DATA,
|
||||
PROP_SHAPE_TYPE,
|
||||
|
||||
// NOTE: add new properties ABOVE this line and then modify PROP_LAST_ITEM below
|
||||
PROP_LAST_ITEM = PROP_SHAPE_TYPE,
|
||||
|
||||
// These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter
|
||||
// since the derived class knows how to interpret it's own properties and knows the types it expects
|
||||
|
@ -179,6 +181,7 @@ public:
|
|||
DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType);
|
||||
|
||||
public:
|
||||
float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); }
|
||||
|
@ -191,6 +194,7 @@ public:
|
|||
bool containsBoundsProperties() const { return (_positionChanged || _dimensionsChanged); }
|
||||
bool containsPositionChange() const { return _positionChanged; }
|
||||
bool containsDimensionsChange() const { return _dimensionsChanged; }
|
||||
bool containsAnimationSettingsChange() const { return _animationSettingsChanged; }
|
||||
|
||||
float getGlowLevel() const { return _glowLevel; }
|
||||
float getLocalRenderAlpha() const { return _localRenderAlpha; }
|
||||
|
@ -253,12 +257,57 @@ inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
|||
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||
debug << "EntityItemProperties[" << "\n"
|
||||
<< " position:" << properties.getPosition() << "in meters" << "\n"
|
||||
<< " velocity:" << properties.getVelocity() << "in meters" << "\n"
|
||||
<< " last edited:" << properties.getLastEdited() << "\n"
|
||||
<< " edited ago:" << properties.getEditedAgo() << "\n"
|
||||
<< "]";
|
||||
debug << "EntityItemProperties[" << "\n";
|
||||
|
||||
// TODO: figure out why position and animationSettings don't seem to like the macro approach
|
||||
if (properties.containsPositionChange()) {
|
||||
debug << " position:" << properties.getPosition() << "in meters" << "\n";
|
||||
}
|
||||
if (properties.containsAnimationSettingsChange()) {
|
||||
debug << " animationSettings:" << properties.getAnimationSettings() << "\n";
|
||||
}
|
||||
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Dimensions, dimensions, "in meters");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Visible, visible, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Rotation, rotation, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Density, density, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Gravity, gravity, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Damping, damping, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifetime, lifetime, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationURL, animationURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFPS, animationFPS, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFrameIndex, animationFrameIndex, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationIsPlaying, animationIsPlaying, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, RegistrationPoint, registrationPoint, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AngularVelocity, angularVelocity, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AngularDamping, angularDamping, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, IgnoreForCollisions, ignoreForCollisions, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionsWillMove, collisionsWillMove, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, IsSpotlight, isSpotlight, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, DiffuseColor, diffuseColor, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientColor, ambientColor, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, SpecularColor, specularColor, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ConstantAttenuation, constantAttenuation, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, LinearAttenuation, linearAttenuation, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, QuadraticAttenuation, quadraticAttenuation, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Exponent, exponent, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Cutoff, cutoff, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Locked, locked, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Textures, textures, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, UserData, userData, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Text, text, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, LineHeight, lineHeight, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, TextColor, textColor, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundColor, backgroundColor, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ShapeType, shapeType, "");
|
||||
|
||||
debug << " last edited:" << properties.getLastEdited() << "\n";
|
||||
debug << " edited ago:" << properties.getEditedAgo() << "\n";
|
||||
debug << "]";
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
|
|
@ -180,6 +180,15 @@
|
|||
#define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \
|
||||
properties.setProperty(#P, _##P);
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S, E) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
E newValue = (E)(P.toVariant().toInt()); \
|
||||
if (_defaultSettings || newValue != _##P) { \
|
||||
S(newValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \
|
||||
QScriptValue P = object.property(#P); \
|
||||
if (P.isValid()) { \
|
||||
|
@ -312,6 +321,10 @@
|
|||
T _##n; \
|
||||
bool _##n##Changed;
|
||||
|
||||
#define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \
|
||||
if (P.n##Changed()) { \
|
||||
D << " " << #n << ":" << P.get##N() << x << "\n"; \
|
||||
}
|
||||
|
||||
|
||||
#endif // hifi_EntityItemPropertiesMacros_h
|
||||
|
|
|
@ -592,6 +592,10 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
|
|||
|
||||
// if the EntityItem exists, then update it
|
||||
if (existingEntity) {
|
||||
if (wantEditLogging()) {
|
||||
qDebug() << "User [" << senderNode->getUUID() << "] editing entity. ID:" << entityItemID;
|
||||
qDebug() << " properties:" << properties;
|
||||
}
|
||||
updateEntity(entityItemID, properties, senderNode->getCanAdjustLocks());
|
||||
existingEntity->markAsChangedOnServer();
|
||||
} else {
|
||||
|
|
|
@ -151,6 +151,9 @@ public:
|
|||
void emitEntityScriptChanging(const EntityItemID& entityItemID);
|
||||
|
||||
void setSimulation(EntitySimulation* simulation);
|
||||
|
||||
bool wantEditLogging() const { return _wantEditLogging; }
|
||||
void setWantEditLogging(bool value) { _wantEditLogging = value; }
|
||||
|
||||
signals:
|
||||
void deletingEntity(const EntityItemID& entityID);
|
||||
|
@ -180,6 +183,8 @@ private:
|
|||
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
|
||||
|
||||
EntitySimulation* _simulation;
|
||||
|
||||
bool _wantEditLogging = false;
|
||||
};
|
||||
|
||||
#endif // hifi_EntityTree_h
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <AACubeShape.h>
|
||||
#include <ShapeCollider.h>
|
||||
|
||||
#include <FBXReader.h>
|
||||
#include <GeometryUtil.h>
|
||||
|
||||
|
@ -570,33 +567,6 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
|
|||
return false;
|
||||
}
|
||||
|
||||
bool EntityTreeElement::findShapeCollisions(const Shape* shape, CollisionList& collisions) const {
|
||||
bool atLeastOneCollision = false;
|
||||
QList<EntityItem*>::iterator entityItr = _entityItems->begin();
|
||||
QList<EntityItem*>::const_iterator entityEnd = _entityItems->end();
|
||||
while(entityItr != entityEnd) {
|
||||
EntityItem* entity = (*entityItr);
|
||||
|
||||
// entities that are set for ignore for collisions then don't consider them for collision
|
||||
const Shape* otherCollisionShape = &entity->getCollisionShapeInMeters();
|
||||
|
||||
bool ignoreForCollisions = entity->getIgnoreForCollisions();
|
||||
if (shape != otherCollisionShape && !ignoreForCollisions) {
|
||||
if (ShapeCollider::collideShapes(shape, otherCollisionShape, collisions)) {
|
||||
CollisionInfo* lastCollision = collisions.getLastCollision();
|
||||
if (lastCollision) {
|
||||
lastCollision->_extraData = entity;
|
||||
atLeastOneCollision = true;
|
||||
} else {
|
||||
qDebug() << "UNEXPECTED - ShapeCollider::collideShapes() returned true, but no lastCollision.";
|
||||
}
|
||||
}
|
||||
}
|
||||
++entityItr;
|
||||
}
|
||||
return atLeastOneCollision;
|
||||
}
|
||||
|
||||
void EntityTreeElement::updateEntityItemID(const EntityItemID& creatorTokenEntityID, const EntityItemID& knownIDEntityID) {
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
|
|
|
@ -142,8 +142,6 @@ public:
|
|||
virtual bool findSpherePenetration(const glm::vec3& center, float radius,
|
||||
glm::vec3& penetration, void** penetratedObject) const;
|
||||
|
||||
virtual bool findShapeCollisions(const Shape* shape, CollisionList& collisions) const;
|
||||
|
||||
const QList<EntityItem*>& getEntities() const { return *_entityItems; }
|
||||
QList<EntityItem*>& getEntities() { return *_entityItems; }
|
||||
bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; }
|
||||
|
|
|
@ -42,16 +42,11 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI
|
|||
_cutoff = PI;
|
||||
|
||||
setProperties(properties);
|
||||
|
||||
// a light is not collide-able so we make it's shape be a tiny sphere at origin
|
||||
_emptyShape.setTranslation(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
_emptyShape.setRadius(0.0f);
|
||||
}
|
||||
|
||||
void LightEntityItem::setDimensions(const glm::vec3& value) {
|
||||
float maxDimension = glm::max(value.x, value.y, value.z);
|
||||
_dimensions = glm::vec3(maxDimension, maxDimension, maxDimension);
|
||||
recalculateCollisionShape();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#ifndef hifi_LightEntityItem_h
|
||||
#define hifi_LightEntityItem_h
|
||||
|
||||
#include <SphereShape.h>
|
||||
#include "EntityItem.h"
|
||||
|
||||
class LightEntityItem : public EntityItem {
|
||||
|
@ -98,13 +97,10 @@ public:
|
|||
float getCutoff() const { return _cutoff; }
|
||||
void setCutoff(float value) { _cutoff = value; }
|
||||
|
||||
virtual const Shape& getCollisionShapeInMeters() const { return _emptyShape; }
|
||||
|
||||
static bool getLightsArePickable() { return _lightsArePickable; }
|
||||
static void setLightsArePickable(bool value) { _lightsArePickable = value; }
|
||||
|
||||
protected:
|
||||
virtual void recalculateCollisionShape() { /* nothing to do */ }
|
||||
|
||||
// properties of a light
|
||||
rgbColor _ambientColor;
|
||||
|
@ -117,9 +113,6 @@ protected:
|
|||
float _exponent;
|
||||
float _cutoff;
|
||||
|
||||
// used for collision detection
|
||||
SphereShape _emptyShape;
|
||||
|
||||
static bool _lightsArePickable;
|
||||
};
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ EntityItemProperties ModelEntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -66,6 +67,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -116,6 +118,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -131,6 +134,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams&
|
|||
requestedProperties += PROP_ANIMATION_PLAYING;
|
||||
requestedProperties += PROP_ANIMATION_SETTINGS;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -153,21 +157,12 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType());
|
||||
}
|
||||
|
||||
|
||||
QMap<QString, AnimationPointer> ModelEntityItem::_loadedAnimations; // TODO: improve cleanup by leveraging the AnimationPointer(s)
|
||||
|
||||
// This class/instance will cleanup the animations once unloaded.
|
||||
class EntityAnimationsBookkeeper {
|
||||
public:
|
||||
~EntityAnimationsBookkeeper() {
|
||||
ModelEntityItem::cleanupLoadedAnimations();
|
||||
}
|
||||
};
|
||||
|
||||
EntityAnimationsBookkeeper modelAnimationsBookkeeperInstance;
|
||||
|
||||
void ModelEntityItem::cleanupLoadedAnimations() {
|
||||
foreach(AnimationPointer animation, _loadedAnimations) {
|
||||
animation.clear();
|
||||
|
@ -245,21 +240,6 @@ bool ModelEntityItem::needsToCallUpdate() const {
|
|||
return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate();
|
||||
}
|
||||
|
||||
void ModelEntityItem::computeShapeInfo(ShapeInfo& info) const {
|
||||
// HACK: Default first first approximation is to boxify the entity... but only if it is small enough.
|
||||
// The limit here is chosen to something that most avatars could not comfortably fit inside
|
||||
// to prevent houses from getting boxified... we don't want the things inside houses to
|
||||
// collide with a house as if it were a giant solid block.
|
||||
const float MAX_SIZE_FOR_BOXIFICATION_HACK = 3.0f;
|
||||
float diagonal = glm::length(getDimensionsInMeters());
|
||||
if (diagonal < MAX_SIZE_FOR_BOXIFICATION_HACK) {
|
||||
glm::vec3 halfExtents = 0.5f * getDimensionsInMeters();
|
||||
info.setBox(halfExtents);
|
||||
} else {
|
||||
info.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityItem::update(const quint64& now) {
|
||||
// only advance the frame index if we're playing
|
||||
if (getAnimationIsPlaying()) {
|
||||
|
@ -280,6 +260,13 @@ void ModelEntityItem::debugDump() const {
|
|||
qDebug() << " model URL:" << getModelURL();
|
||||
}
|
||||
|
||||
void ModelEntityItem::updateShapeType(ShapeType type) {
|
||||
if (type != _shapeType) {
|
||||
_shapeType = type;
|
||||
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationURL(const QString& url) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
|
||||
_animationURL = url;
|
||||
|
|
|
@ -46,9 +46,10 @@ public:
|
|||
|
||||
virtual void update(const quint64& now);
|
||||
virtual bool needsToCallUpdate() const;
|
||||
void computeShapeInfo(ShapeInfo& info) const;
|
||||
virtual void debugDump() const;
|
||||
|
||||
void updateShapeType(ShapeType type);
|
||||
virtual ShapeType getShapeType() const { return _shapeType; }
|
||||
|
||||
// TODO: Move these to subclasses, or other appropriate abstraction
|
||||
// getters/setters applicable to models and particles
|
||||
|
@ -126,6 +127,7 @@ protected:
|
|||
AnimationLoop _animationLoop;
|
||||
QString _animationSettings;
|
||||
QString _textures;
|
||||
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
||||
|
||||
// used on client side
|
||||
bool _jointMappingCompleted;
|
||||
|
|
|
@ -94,19 +94,6 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi
|
|||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
}
|
||||
|
||||
void SphereEntityItem::recalculateCollisionShape() {
|
||||
_sphereShape.setTranslation(getCenterInMeters());
|
||||
glm::vec3 dimensionsInMeters = getDimensionsInMeters();
|
||||
float largestDiameter = glm::max(dimensionsInMeters.x, dimensionsInMeters.y, dimensionsInMeters.z);
|
||||
_sphereShape.setRadius(largestDiameter / 2.0f);
|
||||
}
|
||||
|
||||
void SphereEntityItem::computeShapeInfo(ShapeInfo& info) const {
|
||||
glm::vec3 halfExtents = 0.5f * getDimensionsInMeters();
|
||||
// TODO: support ellipsoid shapes
|
||||
info.setSphere(halfExtents.x);
|
||||
}
|
||||
|
||||
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||
void** intersectedObject, bool precisionPicking) const {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#ifndef hifi_SphereEntityItem_h
|
||||
#define hifi_SphereEntityItem_h
|
||||
|
||||
#include <SphereShape.h>
|
||||
#include "EntityItem.h"
|
||||
|
||||
class SphereEntityItem : public EntityItem {
|
||||
|
@ -51,12 +50,10 @@ public:
|
|||
_color[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
|
||||
virtual const Shape& getCollisionShapeInMeters() const { return _sphereShape; }
|
||||
|
||||
// TODO: implement proper contains for 3D ellipsoid
|
||||
//virtual bool contains(const glm::vec3& point) const;
|
||||
|
||||
void computeShapeInfo(ShapeInfo& info) const;
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; }
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
@ -66,10 +63,8 @@ public:
|
|||
virtual void debugDump() const;
|
||||
|
||||
protected:
|
||||
virtual void recalculateCollisionShape();
|
||||
|
||||
rgbColor _color;
|
||||
SphereShape _sphereShape;
|
||||
};
|
||||
|
||||
#endif // hifi_SphereEntityItem_h
|
||||
|
|
|
@ -44,7 +44,6 @@ void TextEntityItem::setDimensions(const glm::vec3& value) {
|
|||
// NOTE: Text Entities always have a "depth" of 1cm.
|
||||
float fixedDepth = 0.01f / (float)TREE_SCALE;
|
||||
_dimensions = glm::vec3(value.x, value.y, fixedDepth);
|
||||
recalculateCollisionShape();
|
||||
}
|
||||
|
||||
EntityItemProperties TextEntityItem::getProperties() const {
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
|
||||
virtual void setDimensions(const glm::vec3& value);
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties() const;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <GeometryUtil.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <OctalCode.h>
|
||||
#include <Shape.h>
|
||||
|
||||
#include "FBXReader.h"
|
||||
|
||||
|
@ -1126,7 +1127,7 @@ FBXTexture getTexture(const QString& textureID,
|
|||
texture.transform.setTranslation(p.translation);
|
||||
texture.transform.setRotation(glm::quat(glm::radians(p.rotation)));
|
||||
texture.transform.setScale(p.scaling);
|
||||
if ((p.UVSet != "map1") || (p.UVSet != "UVSet0")) {
|
||||
if ((p.UVSet != "map1") && (p.UVSet != "UVSet0")) {
|
||||
texture.texcoordSet = 1;
|
||||
}
|
||||
texture.texcoordSetName = p.UVSet;
|
||||
|
@ -1166,7 +1167,6 @@ int matchTextureUVSetToAttributeChannel(const QString& texUVSetName, const QHash
|
|||
|
||||
FBXLight extractLight(const FBXNode& object) {
|
||||
FBXLight light;
|
||||
int unkwnon = 0;
|
||||
foreach (const FBXNode& subobject, object.children) {
|
||||
QString childname = QString(subobject.name);
|
||||
if (subobject.name == "Properties70") {
|
||||
|
@ -1556,6 +1556,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
|||
if (property.name == propertyName) {
|
||||
QString v = property.properties.at(0).toString();
|
||||
if (property.properties.at(0) == "UVSet") {
|
||||
std::string uvName = property.properties.at(index).toString().toStdString();
|
||||
tex.assign(tex.UVSet, property.properties.at(index).toString());
|
||||
} else if (property.properties.at(0) == "CurrentTextureBlendMode") {
|
||||
tex.assign<uint8_t>(tex.currentTextureBlendMode, property.properties.at(index).value<int>());
|
||||
|
@ -1951,7 +1952,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
|||
joint.inverseBindRotation = joint.inverseDefaultRotation;
|
||||
joint.name = model.name;
|
||||
joint.shapePosition = glm::vec3(0.0f);
|
||||
joint.shapeType = SHAPE_TYPE_UNKNOWN;
|
||||
joint.shapeType = INVALID_SHAPE;
|
||||
|
||||
foreach (const QString& childID, childMap.values(modelID)) {
|
||||
QString type = typeFlags.value(childID);
|
||||
|
@ -2375,10 +2376,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
|||
if (collideLikeCapsule) {
|
||||
joint.shapeRotation = rotationBetween(defaultCapsuleAxis, jointShapeInfo.boneBegin);
|
||||
joint.shapePosition = 0.5f * jointShapeInfo.boneBegin;
|
||||
joint.shapeType = SHAPE_TYPE_CAPSULE;
|
||||
joint.shapeType = CAPSULE_SHAPE;
|
||||
} else {
|
||||
// collide the joint like a sphere
|
||||
joint.shapeType = SHAPE_TYPE_SPHERE;
|
||||
joint.shapeType = SPHERE_SHAPE;
|
||||
if (jointShapeInfo.numVertices > 0) {
|
||||
jointShapeInfo.averageVertex /= (float)jointShapeInfo.numVertices;
|
||||
joint.shapePosition = jointShapeInfo.averageVertex;
|
||||
|
@ -2398,8 +2399,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
|||
if (distanceFromEnd > joint.distanceToParent && distanceFromBegin > joint.distanceToParent) {
|
||||
// The shape is further from both joint endpoints than the endpoints are from each other
|
||||
// which probably means the model has a bad transform somewhere. We disable this shape
|
||||
// by setting its type to SHAPE_TYPE_UNKNOWN.
|
||||
joint.shapeType = SHAPE_TYPE_UNKNOWN;
|
||||
// by setting its type to INVALID_SHAPE.
|
||||
joint.shapeType = INVALID_SHAPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
#include <QVariant>
|
||||
#include <QVector>
|
||||
|
||||
#include <Extents.h>
|
||||
#include <Transform.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <Extents.h>
|
||||
#include <Transform.h>
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include <model/Geometry.h>
|
||||
#include <model/Material.h>
|
||||
|
||||
|
@ -53,12 +54,6 @@ public:
|
|||
QVector<glm::vec3> normals;
|
||||
};
|
||||
|
||||
enum ShapeType {
|
||||
SHAPE_TYPE_SPHERE = 0,
|
||||
SHAPE_TYPE_CAPSULE = 1,
|
||||
SHAPE_TYPE_UNKNOWN = 2
|
||||
};
|
||||
|
||||
/// A single joint (transformation node) extracted from an FBX document.
|
||||
class FBXJoint {
|
||||
public:
|
||||
|
@ -83,7 +78,7 @@ public:
|
|||
QString name;
|
||||
glm::vec3 shapePosition; // in joint frame
|
||||
glm::quat shapeRotation; // in joint frame
|
||||
ShapeType shapeType;
|
||||
quint8 shapeType;
|
||||
bool isSkeletonJoint;
|
||||
};
|
||||
|
||||
|
|
|
@ -129,17 +129,7 @@ public:
|
|||
void _glUniform1f(GLint location, GLfloat v0);
|
||||
void _glUniform2f(GLint location, GLfloat v0, GLfloat v1);
|
||||
void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value);
|
||||
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
|
||||
void _glMatrixMode(GLenum mode);
|
||||
void _glPushMatrix();
|
||||
void _glPopMatrix();
|
||||
void _glMultMatrixf(const GLfloat *m);
|
||||
void _glLoadMatrixf(const GLfloat *m);
|
||||
void _glLoadIdentity(void);
|
||||
void _glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glTranslatef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
|
||||
void _glDrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
|
||||
|
@ -201,16 +191,6 @@ public:
|
|||
COMMAND_glUniform4fv,
|
||||
COMMAND_glUniformMatrix4fv,
|
||||
|
||||
COMMAND_glMatrixMode,
|
||||
COMMAND_glPushMatrix,
|
||||
COMMAND_glPopMatrix,
|
||||
COMMAND_glMultMatrixf,
|
||||
COMMAND_glLoadMatrixf,
|
||||
COMMAND_glLoadIdentity,
|
||||
COMMAND_glRotatef,
|
||||
COMMAND_glScalef,
|
||||
COMMAND_glTranslatef,
|
||||
|
||||
COMMAND_glDrawArrays,
|
||||
COMMAND_glDrawRangeElements,
|
||||
|
||||
|
|
|
@ -54,16 +54,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
|||
(&::gpu::GLBackend::do_glUniform4fv),
|
||||
(&::gpu::GLBackend::do_glUniformMatrix4fv),
|
||||
|
||||
(&::gpu::GLBackend::do_glMatrixMode),
|
||||
(&::gpu::GLBackend::do_glPushMatrix),
|
||||
(&::gpu::GLBackend::do_glPopMatrix),
|
||||
(&::gpu::GLBackend::do_glMultMatrixf),
|
||||
(&::gpu::GLBackend::do_glLoadMatrixf),
|
||||
(&::gpu::GLBackend::do_glLoadIdentity),
|
||||
(&::gpu::GLBackend::do_glRotatef),
|
||||
(&::gpu::GLBackend::do_glScalef),
|
||||
(&::gpu::GLBackend::do_glTranslatef),
|
||||
|
||||
(&::gpu::GLBackend::do_glDrawArrays),
|
||||
(&::gpu::GLBackend::do_glDrawRangeElements),
|
||||
|
||||
|
@ -747,127 +737,6 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) {
|
|||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glMatrixMode(GLenum mode) {
|
||||
ADD_COMMAND_GL(glMatrixMode);
|
||||
|
||||
_params.push_back(mode);
|
||||
|
||||
DO_IT_NOW(_glMatrixMode, 1);
|
||||
}
|
||||
void GLBackend::do_glMatrixMode(Batch& batch, uint32 paramOffset) {
|
||||
glMatrixMode(batch._params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glPushMatrix() {
|
||||
ADD_COMMAND_GL(glPushMatrix);
|
||||
|
||||
DO_IT_NOW(_glPushMatrix, 0);
|
||||
}
|
||||
void GLBackend::do_glPushMatrix(Batch& batch, uint32 paramOffset) {
|
||||
glPushMatrix();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glPopMatrix() {
|
||||
ADD_COMMAND_GL(glPopMatrix);
|
||||
|
||||
DO_IT_NOW(_glPopMatrix, 0);
|
||||
}
|
||||
void GLBackend::do_glPopMatrix(Batch& batch, uint32 paramOffset) {
|
||||
glPopMatrix();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glMultMatrixf(const GLfloat *m) {
|
||||
ADD_COMMAND_GL(glMultMatrixf);
|
||||
|
||||
const int MATRIX4_SIZE = 16 * sizeof(float);
|
||||
_params.push_back(cacheData(MATRIX4_SIZE, m));
|
||||
|
||||
DO_IT_NOW(_glMultMatrixf, 1);
|
||||
}
|
||||
void GLBackend::do_glMultMatrixf(Batch& batch, uint32 paramOffset) {
|
||||
glMultMatrixf((const GLfloat*)batch.editData(batch._params[paramOffset]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glLoadMatrixf(const GLfloat *m) {
|
||||
ADD_COMMAND_GL(glLoadMatrixf);
|
||||
|
||||
const int MATRIX4_SIZE = 16 * sizeof(float);
|
||||
_params.push_back(cacheData(MATRIX4_SIZE, m));
|
||||
|
||||
DO_IT_NOW(_glLoadMatrixf, 1);
|
||||
}
|
||||
void GLBackend::do_glLoadMatrixf(Batch& batch, uint32 paramOffset) {
|
||||
glLoadMatrixf((const GLfloat*)batch.editData(batch._params[paramOffset]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glLoadIdentity(void) {
|
||||
ADD_COMMAND_GL(glLoadIdentity);
|
||||
|
||||
DO_IT_NOW(_glLoadIdentity, 0);
|
||||
}
|
||||
void GLBackend::do_glLoadIdentity(Batch& batch, uint32 paramOffset) {
|
||||
glLoadIdentity();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
ADD_COMMAND_GL(glRotatef);
|
||||
|
||||
_params.push_back(z);
|
||||
_params.push_back(y);
|
||||
_params.push_back(x);
|
||||
_params.push_back(angle);
|
||||
|
||||
DO_IT_NOW(_glRotatef, 4);
|
||||
}
|
||||
void GLBackend::do_glRotatef(Batch& batch, uint32 paramOffset) {
|
||||
glRotatef(
|
||||
batch._params[paramOffset + 3]._float,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
ADD_COMMAND_GL(glScalef);
|
||||
|
||||
_params.push_back(z);
|
||||
_params.push_back(y);
|
||||
_params.push_back(x);
|
||||
|
||||
DO_IT_NOW(_glScalef, 3);
|
||||
}
|
||||
void GLBackend::do_glScalef(Batch& batch, uint32 paramOffset) {
|
||||
glScalef(
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
ADD_COMMAND_GL(glTranslatef);
|
||||
|
||||
_params.push_back(z);
|
||||
_params.push_back(y);
|
||||
_params.push_back(x);
|
||||
|
||||
DO_IT_NOW(_glTranslatef, 3);
|
||||
}
|
||||
void GLBackend::do_glTranslatef(Batch& batch, uint32 paramOffset) {
|
||||
glTranslatef(
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
ADD_COMMAND_GL(glDrawArrays);
|
||||
|
||||
|
|
|
@ -175,17 +175,7 @@ protected:
|
|||
void do_glUniform1f(Batch& batch, uint32 paramOffset);
|
||||
void do_glUniform2f(Batch& batch, uint32 paramOffset);
|
||||
void do_glUniform4fv(Batch& batch, uint32 paramOffset);
|
||||
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
|
||||
|
||||
void do_glMatrixMode(Batch& batch, uint32 paramOffset);
|
||||
void do_glPushMatrix(Batch& batch, uint32 paramOffset);
|
||||
void do_glPopMatrix(Batch& batch, uint32 paramOffset);
|
||||
void do_glMultMatrixf(Batch& batch, uint32 paramOffset);
|
||||
void do_glLoadMatrixf(Batch& batch, uint32 paramOffset);
|
||||
void do_glLoadIdentity(Batch& batch, uint32 paramOffset);
|
||||
void do_glRotatef(Batch& batch, uint32 paramOffset);
|
||||
void do_glScalef(Batch& batch, uint32 paramOffset);
|
||||
void do_glTranslatef(Batch& batch, uint32 paramOffset);
|
||||
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
|
||||
|
||||
void do_glDrawArrays(Batch& batch, uint32 paramOffset);
|
||||
void do_glDrawRangeElements(Batch& batch, uint32 paramOffset);
|
||||
|
|
|
@ -85,8 +85,11 @@ bool Texture::Storage::allocateMip(uint16 level) {
|
|||
bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) {
|
||||
// Ok we should be able to do that...
|
||||
allocateMip(level);
|
||||
_mips[level]->_format = format;
|
||||
Size allocated = _mips[level]->_sysmem.setData(size, bytes);
|
||||
auto mip = _mips[level];
|
||||
mip->_format = format;
|
||||
Size allocated = mip->_sysmem.setData(size, bytes);
|
||||
mip->_isGPULoaded = false;
|
||||
|
||||
return allocated == size;
|
||||
}
|
||||
|
||||
|
|
|
@ -465,9 +465,9 @@ void Bitstream::writeRawDelta(const QScriptValue& value, const QScriptValue& ref
|
|||
} else if (reference.isArray()) {
|
||||
if (value.isArray()) {
|
||||
*this << false;
|
||||
int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
int length = value.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
*this << length;
|
||||
int referenceLength = reference.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
int referenceLength = reference.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i < referenceLength) {
|
||||
writeDelta(value.property(i), reference.property(i));
|
||||
|
@ -555,7 +555,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
} else {
|
||||
QVariant variant;
|
||||
readRawDelta(variant, reference.toVariant());
|
||||
value = ScriptCache::getInstance()->getEngine()->newVariant(variant);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newVariant(variant);
|
||||
}
|
||||
} else if (reference.isQObject()) {
|
||||
bool typeChanged;
|
||||
|
@ -566,7 +566,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
} else {
|
||||
QObject* object;
|
||||
readRawDelta(object, reference.toQObject());
|
||||
value = ScriptCache::getInstance()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership);
|
||||
}
|
||||
} else if (reference.isQMetaObject()) {
|
||||
bool typeChanged;
|
||||
|
@ -577,7 +577,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
} else {
|
||||
const QMetaObject* metaObject;
|
||||
*this >> metaObject;
|
||||
value = ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newQMetaObject(metaObject);
|
||||
}
|
||||
} else if (reference.isDate()) {
|
||||
bool typeChanged;
|
||||
|
@ -588,7 +588,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
} else {
|
||||
QDateTime dateTime;
|
||||
*this >> dateTime;
|
||||
value = ScriptCache::getInstance()->getEngine()->newDate(dateTime);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newDate(dateTime);
|
||||
}
|
||||
} else if (reference.isRegExp()) {
|
||||
bool typeChanged;
|
||||
|
@ -599,7 +599,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
} else {
|
||||
QRegExp regExp;
|
||||
*this >> regExp;
|
||||
value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newRegExp(regExp);
|
||||
}
|
||||
} else if (reference.isArray()) {
|
||||
bool typeChanged;
|
||||
|
@ -610,8 +610,8 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
} else {
|
||||
int length;
|
||||
*this >> length;
|
||||
value = ScriptCache::getInstance()->getEngine()->newArray(length);
|
||||
int referenceLength = reference.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newArray(length);
|
||||
int referenceLength = reference.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
for (int i = 0; i < length; i++) {
|
||||
QScriptValue element;
|
||||
if (i < referenceLength) {
|
||||
|
@ -630,7 +630,7 @@ void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference)
|
|||
|
||||
} else {
|
||||
// start by shallow-copying the reference
|
||||
value = ScriptCache::getInstance()->getEngine()->newObject();
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newObject();
|
||||
for (QScriptValueIterator it(reference); it.hasNext(); ) {
|
||||
it.next();
|
||||
value.setProperty(it.scriptName(), it.value());
|
||||
|
@ -1036,7 +1036,7 @@ Bitstream& Bitstream::operator<<(const QScriptValue& value) {
|
|||
|
||||
} else if (value.isArray()) {
|
||||
writeScriptValueType(*this, ARRAY_SCRIPT_VALUE);
|
||||
int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
int length = value.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
*this << length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
*this << value.property(i);
|
||||
|
@ -1087,37 +1087,37 @@ Bitstream& Bitstream::operator>>(QScriptValue& value) {
|
|||
case VARIANT_SCRIPT_VALUE: {
|
||||
QVariant variantValue;
|
||||
*this >> variantValue;
|
||||
value = ScriptCache::getInstance()->getEngine()->newVariant(variantValue);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newVariant(variantValue);
|
||||
break;
|
||||
}
|
||||
case QOBJECT_SCRIPT_VALUE: {
|
||||
QObject* object;
|
||||
*this >> object;
|
||||
ScriptCache::getInstance()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership);
|
||||
DependencyManager::get<ScriptCache>()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership);
|
||||
break;
|
||||
}
|
||||
case QMETAOBJECT_SCRIPT_VALUE: {
|
||||
const QMetaObject* metaObject;
|
||||
*this >> metaObject;
|
||||
ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject);
|
||||
DependencyManager::get<ScriptCache>()->getEngine()->newQMetaObject(metaObject);
|
||||
break;
|
||||
}
|
||||
case DATE_SCRIPT_VALUE: {
|
||||
QDateTime dateTime;
|
||||
*this >> dateTime;
|
||||
value = ScriptCache::getInstance()->getEngine()->newDate(dateTime);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newDate(dateTime);
|
||||
break;
|
||||
}
|
||||
case REGEXP_SCRIPT_VALUE: {
|
||||
QRegExp regExp;
|
||||
*this >> regExp;
|
||||
value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newRegExp(regExp);
|
||||
break;
|
||||
}
|
||||
case ARRAY_SCRIPT_VALUE: {
|
||||
int length;
|
||||
*this >> length;
|
||||
value = ScriptCache::getInstance()->getEngine()->newArray(length);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newArray(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
QScriptValue element;
|
||||
*this >> element;
|
||||
|
@ -1126,7 +1126,7 @@ Bitstream& Bitstream::operator>>(QScriptValue& value) {
|
|||
break;
|
||||
}
|
||||
case OBJECT_SCRIPT_VALUE: {
|
||||
value = ScriptCache::getInstance()->getEngine()->newObject();
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newObject();
|
||||
forever {
|
||||
QScriptString name;
|
||||
*this >> name;
|
||||
|
@ -1477,7 +1477,7 @@ Bitstream& Bitstream::operator>(QScriptString& string) {
|
|||
QString rawString;
|
||||
*this >> rawString;
|
||||
string = (rawString == INVALID_STRING) ? QScriptString() :
|
||||
ScriptCache::getInstance()->getEngine()->toStringHandle(rawString);
|
||||
DependencyManager::get<ScriptCache>()->getEngine()->toStringHandle(rawString);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1828,7 +1828,7 @@ QJsonValue JSONWriter::getData(const QScriptValue& value) {
|
|||
} else if (value.isArray()) {
|
||||
object.insert("type", QString("ARRAY"));
|
||||
QJsonArray array;
|
||||
int length = value.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
int length = value.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
for (int i = 0; i < length; i++) {
|
||||
array.append(getData(value.property(i)));
|
||||
}
|
||||
|
@ -2209,31 +2209,31 @@ void JSONReader::putData(const QJsonValue& data, QScriptValue& value) {
|
|||
} else if (type == "VARIANT") {
|
||||
QVariant variant;
|
||||
putData(object.value("value"), variant);
|
||||
value = ScriptCache::getInstance()->getEngine()->newVariant(variant);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newVariant(variant);
|
||||
|
||||
} else if (type == "QOBJECT") {
|
||||
QObject* qObject;
|
||||
putData(object.value("value"), qObject);
|
||||
value = ScriptCache::getInstance()->getEngine()->newQObject(qObject, QScriptEngine::ScriptOwnership);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newQObject(qObject, QScriptEngine::ScriptOwnership);
|
||||
|
||||
} else if (type == "QMETAOBJECT") {
|
||||
const QMetaObject* metaObject;
|
||||
putData(object.value("value"), metaObject);
|
||||
value = ScriptCache::getInstance()->getEngine()->newQMetaObject(metaObject);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newQMetaObject(metaObject);
|
||||
|
||||
} else if (type == "DATE") {
|
||||
QDateTime dateTime;
|
||||
putData(object.value("value"), dateTime);
|
||||
value = ScriptCache::getInstance()->getEngine()->newDate(dateTime);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newDate(dateTime);
|
||||
|
||||
} else if (type == "REGEXP") {
|
||||
QRegExp regExp;
|
||||
putData(object.value("value"), regExp);
|
||||
value = ScriptCache::getInstance()->getEngine()->newRegExp(regExp);
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newRegExp(regExp);
|
||||
|
||||
} else if (type == "ARRAY") {
|
||||
QJsonArray array = object.value("value").toArray();
|
||||
value = ScriptCache::getInstance()->getEngine()->newArray(array.size());
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newArray(array.size());
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
QScriptValue element;
|
||||
putData(array.at(i), element);
|
||||
|
@ -2241,7 +2241,7 @@ void JSONReader::putData(const QJsonValue& data, QScriptValue& value) {
|
|||
}
|
||||
} else if (type == "OBJECT") {
|
||||
QJsonObject jsonObject = object.value("value").toObject();
|
||||
value = ScriptCache::getInstance()->getEngine()->newObject();
|
||||
value = DependencyManager::get<ScriptCache>()->getEngine()->newObject();
|
||||
for (QJsonObject::const_iterator it = jsonObject.constBegin(); it != jsonObject.constEnd(); it++) {
|
||||
QScriptValue element;
|
||||
putData(it.value(), element);
|
||||
|
|
|
@ -663,7 +663,7 @@ void ParameterizedURLEditor::updateURL() {
|
|||
QByteArray valuePropertyName = widget->property("valuePropertyName").toByteArray();
|
||||
const QMetaObject* widgetMetaObject = widget->metaObject();
|
||||
QMetaProperty widgetProperty = widgetMetaObject->property(widgetMetaObject->indexOfProperty(valuePropertyName));
|
||||
parameters.insert(ScriptCache::getInstance()->getEngine()->toStringHandle(
|
||||
parameters.insert(DependencyManager::get<ScriptCache>()->getEngine()->toStringHandle(
|
||||
widget->property("parameterName").toString()), widgetProperty.read(widget));
|
||||
}
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ void ParameterizedURLEditor::updateParameters() {
|
|||
if (_program) {
|
||||
_program->disconnect(this);
|
||||
}
|
||||
_program = ScriptCache::getInstance()->getProgram(_url.getURL());
|
||||
_program = DependencyManager::get<ScriptCache>()->getProgram(_url.getURL());
|
||||
if (_program->isLoaded()) {
|
||||
continueUpdatingParameters();
|
||||
} else {
|
||||
|
@ -698,7 +698,7 @@ void ParameterizedURLEditor::continueUpdatingParameters() {
|
|||
}
|
||||
delete form;
|
||||
}
|
||||
QSharedPointer<NetworkValue> value = ScriptCache::getInstance()->getValue(_url.getURL());
|
||||
QSharedPointer<NetworkValue> value = DependencyManager::get<ScriptCache>()->getValue(_url.getURL());
|
||||
const QList<ParameterInfo>& parameters = static_cast<RootNetworkValue*>(value.data())->getParameterInfo();
|
||||
if (parameters.isEmpty()) {
|
||||
return;
|
||||
|
|
|
@ -57,8 +57,8 @@ bool operator==(const QScriptValue& first, const QScriptValue& second) {
|
|||
if (!second.isArray()) {
|
||||
return false;
|
||||
}
|
||||
int length = first.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
if (second.property(ScriptCache::getInstance()->getLengthString()).toInt32() != length) {
|
||||
int length = first.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
if (second.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32() != length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
@ -103,11 +103,6 @@ bool operator<(const QScriptValue& first, const QScriptValue& second) {
|
|||
return first.lessThan(second);
|
||||
}
|
||||
|
||||
ScriptCache* ScriptCache::getInstance() {
|
||||
static ScriptCache cache;
|
||||
return &cache;
|
||||
}
|
||||
|
||||
ScriptCache::ScriptCache() :
|
||||
_engine(NULL)
|
||||
{
|
||||
|
|
|
@ -25,13 +25,11 @@ class NetworkProgram;
|
|||
class NetworkValue;
|
||||
|
||||
/// Maintains a cache of loaded scripts.
|
||||
class ScriptCache : public ResourceCache {
|
||||
class ScriptCache : public ResourceCache, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
|
||||
static ScriptCache* getInstance();
|
||||
|
||||
ScriptCache();
|
||||
|
||||
void setEngine(QScriptEngine* engine);
|
||||
|
|
|
@ -23,6 +23,7 @@ typedef gpu::BufferView::Index Index;
|
|||
typedef gpu::BufferView BufferView;
|
||||
typedef AABox Box;
|
||||
typedef std::vector< Box > Boxes;
|
||||
typedef glm::vec3 Vec3;
|
||||
|
||||
class Mesh {
|
||||
public:
|
||||
|
@ -35,7 +36,7 @@ public:
|
|||
typedef gpu::Stream::Format VertexFormat;
|
||||
typedef std::map< Slot, BufferView > BufferViewMap;
|
||||
|
||||
typedef glm::vec3 Vec3;
|
||||
typedef model::Vec3 Vec3;
|
||||
|
||||
Mesh();
|
||||
Mesh(const Mesh& mesh);
|
||||
|
|
97
libraries/model/src/model/Light.cpp
Executable file
97
libraries/model/src/model/Light.cpp
Executable file
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// Light.cpp
|
||||
// libraries/model/src/model
|
||||
//
|
||||
// Created by Sam Gateau on 1/26/2014.
|
||||
// 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 "Light.h"
|
||||
|
||||
using namespace model;
|
||||
|
||||
Light::Light() :
|
||||
_flags(0),
|
||||
_schemaBuffer(),
|
||||
_transform() {
|
||||
// only if created from nothing shall we create the Buffer to store the properties
|
||||
Schema schema;
|
||||
_schemaBuffer = gpu::BufferView(new gpu::Buffer(sizeof(Schema), (const gpu::Buffer::Byte*) &schema));
|
||||
}
|
||||
|
||||
Light::Light(const Light& light) :
|
||||
_flags(light._flags),
|
||||
_schemaBuffer(light._schemaBuffer),
|
||||
_transform(light._transform) {
|
||||
}
|
||||
|
||||
Light& Light::operator= (const Light& light) {
|
||||
_flags = (light._flags);
|
||||
_schemaBuffer = (light._schemaBuffer);
|
||||
_transform = (light._transform);
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Light::~Light() {
|
||||
}
|
||||
|
||||
void Light::setPosition(const Vec3& position) {
|
||||
_transform.setTranslation(position);
|
||||
editSchema()._position = Vec4(position, 1.f);
|
||||
}
|
||||
|
||||
void Light::setOrientation(const glm::quat& orientation) {
|
||||
_transform.setRotation(orientation);
|
||||
}
|
||||
|
||||
void Light::setDirection(const Vec3& direction) {
|
||||
editSchema()._direction = glm::normalize(direction);
|
||||
}
|
||||
|
||||
const Vec3& Light::getDirection() const {
|
||||
return getSchema()._direction;
|
||||
}
|
||||
|
||||
void Light::setColor(const Color& color) {
|
||||
editSchema()._color = color;
|
||||
}
|
||||
|
||||
void Light::setIntensity(float intensity) {
|
||||
editSchema()._intensity = intensity;
|
||||
}
|
||||
|
||||
void Light::setMaximumRadius(float radius) {
|
||||
if (radius <= 0.f) {
|
||||
radius = 1.0f;
|
||||
}
|
||||
float CutOffIntensityRatio = 0.05f;
|
||||
float surfaceRadius = radius / (sqrt(1.0f / CutOffIntensityRatio) - 1.f);
|
||||
editSchema()._attenuation = Vec4(surfaceRadius, 1.0f/surfaceRadius, CutOffIntensityRatio, radius);
|
||||
}
|
||||
|
||||
void Light::setSpotAngle(float angle) {
|
||||
if (angle <= 0.f) {
|
||||
angle = 0.0f;
|
||||
}
|
||||
float cosAngle = cos(angle);
|
||||
editSchema()._spot.x = cos(angle);
|
||||
editSchema()._spot.y = sin(angle);
|
||||
editSchema()._spot.z = angle;
|
||||
}
|
||||
|
||||
void Light::setSpotExponent(float exponent) {
|
||||
if (exponent <= 0.f) {
|
||||
exponent = 1.0f;
|
||||
}
|
||||
editSchema()._spot.w = exponent;
|
||||
}
|
||||
|
||||
void Light::setShowContour(float show) {
|
||||
if (show <= 0.f) {
|
||||
show = 0.0f;
|
||||
}
|
||||
editSchema()._control.w = show;
|
||||
}
|
294
libraries/model/src/model/Light.h
Executable file
294
libraries/model/src/model/Light.h
Executable file
|
@ -0,0 +1,294 @@
|
|||
//
|
||||
// Light.h
|
||||
// libraries/model/src/model
|
||||
//
|
||||
// Created by Sam Gateau on 12/10/2014.
|
||||
// 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_model_Light_h
|
||||
#define hifi_model_Light_h
|
||||
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "Transform.h"
|
||||
#include "gpu/Resource.h"
|
||||
#include "gpu/Texture.h"
|
||||
|
||||
namespace model {
|
||||
typedef gpu::BufferView UniformBufferView;
|
||||
typedef gpu::TextureView TextureView;
|
||||
typedef glm::vec3 Vec3;
|
||||
typedef glm::vec4 Vec4;
|
||||
typedef glm::quat Quat;
|
||||
|
||||
class SphericalHarmonics {
|
||||
public:
|
||||
glm::vec3 L00 ; float spare0;
|
||||
glm::vec3 L1m1 ; float spare1;
|
||||
glm::vec3 L10 ; float spare2;
|
||||
glm::vec3 L11 ; float spare3;
|
||||
glm::vec3 L2m2 ; float spare4;
|
||||
glm::vec3 L2m1 ; float spare5;
|
||||
glm::vec3 L20 ; float spare6;
|
||||
glm::vec3 L21 ; float spare7;
|
||||
glm::vec3 L22 ; float spare8;
|
||||
|
||||
static const int NUM_COEFFICIENTS = 9;
|
||||
|
||||
enum Preset {
|
||||
OLD_TOWN_SQUARE = 0,
|
||||
GRACE_CATHEDRAL,
|
||||
EUCALYPTUS_GROVE,
|
||||
ST_PETERS_BASILICA,
|
||||
UFFIZI_GALLERY,
|
||||
GALILEOS_TOMB,
|
||||
VINE_STREET_KITCHEN,
|
||||
BREEZEWAY,
|
||||
CAMPUS_SUNSET,
|
||||
FUNSTON_BEACH_SUNSET,
|
||||
|
||||
NUM_PRESET,
|
||||
};
|
||||
|
||||
void assignPreset(int p) {
|
||||
switch (p) {
|
||||
case OLD_TOWN_SQUARE: {
|
||||
L00 = glm::vec3( 0.871297f, 0.875222f, 0.864470f);
|
||||
L1m1 = glm::vec3( 0.175058f, 0.245335f, 0.312891f);
|
||||
L10 = glm::vec3( 0.034675f, 0.036107f, 0.037362f);
|
||||
L11 = glm::vec3(-0.004629f,-0.029448f,-0.048028f);
|
||||
L2m2 = glm::vec3(-0.120535f,-0.121160f,-0.117507f);
|
||||
L2m1 = glm::vec3( 0.003242f, 0.003624f, 0.007511f);
|
||||
L20 = glm::vec3(-0.028667f,-0.024926f,-0.020998f);
|
||||
L21 = glm::vec3(-0.077539f,-0.086325f,-0.091591f);
|
||||
L22 = glm::vec3(-0.161784f,-0.191783f,-0.219152f);
|
||||
}
|
||||
break;
|
||||
case GRACE_CATHEDRAL: {
|
||||
L00 = glm::vec3( 0.79f, 0.44f, 0.54f);
|
||||
L1m1 = glm::vec3( 0.39f, 0.35f, 0.60f);
|
||||
L10 = glm::vec3(-0.34f, -0.18f, -0.27f);
|
||||
L11 = glm::vec3(-0.29f, -0.06f, 0.01f);
|
||||
L2m2 = glm::vec3(-0.11f, -0.05f, -0.12f);
|
||||
L2m1 = glm::vec3(-0.26f, -0.22f, -0.47f);
|
||||
L20 = glm::vec3(-0.16f, -0.09f, -0.15f);
|
||||
L21 = glm::vec3( 0.56f, 0.21f, 0.14f);
|
||||
L22 = glm::vec3( 0.21f, -0.05f, -0.30f);
|
||||
}
|
||||
break;
|
||||
case EUCALYPTUS_GROVE: {
|
||||
L00 = glm::vec3( 0.38f, 0.43f, 0.45f);
|
||||
L1m1 = glm::vec3( 0.29f, 0.36f, 0.41f);
|
||||
L10 = glm::vec3( 0.04f, 0.03f, 0.01f);
|
||||
L11 = glm::vec3(-0.10f, -0.10f, -0.09f);
|
||||
L2m2 = glm::vec3(-0.06f, -0.06f, -0.04f);
|
||||
L2m1 = glm::vec3( 0.01f, -0.01f, -0.05f);
|
||||
L20 = glm::vec3(-0.09f, -0.13f, -0.15f);
|
||||
L21 = glm::vec3(-0.06f, -0.05f, -0.04f);
|
||||
L22 = glm::vec3( 0.02f, 0.00f, -0.05f);
|
||||
}
|
||||
break;
|
||||
case ST_PETERS_BASILICA: {
|
||||
L00 = glm::vec3( 0.36f, 0.26f, 0.23f);
|
||||
L1m1 = glm::vec3( 0.18f, 0.14f, 0.13f);
|
||||
L10 = glm::vec3(-0.02f, -0.01f, 0.00f);
|
||||
L11 = glm::vec3( 0.03f, 0.02f, -0.00f);
|
||||
L2m2 = glm::vec3( 0.02f, 0.01f, -0.00f);
|
||||
L2m1 = glm::vec3(-0.05f, -0.03f, -0.01f);
|
||||
L20 = glm::vec3(-0.09f, -0.08f, -0.07f);
|
||||
L21 = glm::vec3( 0.01f, 0.00f, 0.00f);
|
||||
L22 = glm::vec3(-0.08f, -0.03f, -0.00f);
|
||||
}
|
||||
break;
|
||||
case UFFIZI_GALLERY: {
|
||||
L00 = glm::vec3( 0.32f, 0.31f, 0.35f);
|
||||
L1m1 = glm::vec3( 0.37f, 0.37f, 0.43f);
|
||||
L10 = glm::vec3( 0.00f, 0.00f, 0.00f);
|
||||
L11 = glm::vec3(-0.01f, -0.01f, -0.01f);
|
||||
L2m2 = glm::vec3(-0.02f, -0.02f, -0.03f);
|
||||
L2m1 = glm::vec3(-0.01f, -0.01f, -0.01f);
|
||||
L20 = glm::vec3(-0.28f, -0.28f, -0.32f);
|
||||
L21 = glm::vec3( 0.00f, 0.00f, 0.00f);
|
||||
L22 = glm::vec3(-0.24f, -0.24f, -0.28f);
|
||||
}
|
||||
break;
|
||||
case GALILEOS_TOMB: {
|
||||
L00 = glm::vec3( 1.04f, 0.76f, 0.71f);
|
||||
L1m1 = glm::vec3( 0.44f, 0.34f, 0.34f);
|
||||
L10 = glm::vec3(-0.22f, -0.18f, -0.17f);
|
||||
L11 = glm::vec3( 0.71f, 0.54f, 0.56f);
|
||||
L2m2 = glm::vec3( 0.64f, 0.50f, 0.52f);
|
||||
L2m1 = glm::vec3(-0.12f, -0.09f, -0.08f);
|
||||
L20 = glm::vec3(-0.37f, -0.28f, -0.32f);
|
||||
L21 = glm::vec3(-0.17f, -0.13f, -0.13f);
|
||||
L22 = glm::vec3( 0.55f, 0.42f, 0.42f);
|
||||
}
|
||||
break;
|
||||
case VINE_STREET_KITCHEN: {
|
||||
L00 = glm::vec3( 0.64f, 0.67f, 0.73f);
|
||||
L1m1 = glm::vec3( 0.28f, 0.32f, 0.33f);
|
||||
L10 = glm::vec3( 0.42f, 0.60f, 0.77f);
|
||||
L11 = glm::vec3(-0.05f, -0.04f, -0.02f);
|
||||
L2m2 = glm::vec3(-0.10f, -0.08f, -0.05f);
|
||||
L2m1 = glm::vec3( 0.25f, 0.39f, 0.53f);
|
||||
L20 = glm::vec3( 0.38f, 0.54f, 0.71f);
|
||||
L21 = glm::vec3( 0.06f, 0.01f, -0.02f);
|
||||
L22 = glm::vec3(-0.03f, -0.02f, -0.03f);
|
||||
}
|
||||
break;
|
||||
case BREEZEWAY: {
|
||||
L00 = glm::vec3( 0.32f, 0.36f, 0.38f);
|
||||
L1m1 = glm::vec3( 0.37f, 0.41f, 0.45f);
|
||||
L10 = glm::vec3(-0.01f, -0.01f, -0.01f);
|
||||
L11 = glm::vec3(-0.10f, -0.12f, -0.12f);
|
||||
L2m2 = glm::vec3(-0.13f, -0.15f, -0.17f);
|
||||
L2m1 = glm::vec3(-0.01f, -0.02f, 0.02f);
|
||||
L20 = glm::vec3(-0.07f, -0.08f, -0.09f);
|
||||
L21 = glm::vec3( 0.02f, 0.03f, 0.03f);
|
||||
L22 = glm::vec3(-0.29f, -0.32f, -0.36f);
|
||||
}
|
||||
break;
|
||||
case CAMPUS_SUNSET: {
|
||||
L00 = glm::vec3( 0.79f, 0.94f, 0.98f);
|
||||
L1m1 = glm::vec3( 0.44f, 0.56f, 0.70f);
|
||||
L10 = glm::vec3(-0.10f, -0.18f, -0.27f);
|
||||
L11 = glm::vec3( 0.45f, 0.38f, 0.20f);
|
||||
L2m2 = glm::vec3( 0.18f, 0.14f, 0.05f);
|
||||
L2m1 = glm::vec3(-0.14f, -0.22f, -0.31f);
|
||||
L20 = glm::vec3(-0.39f, -0.40f, -0.36f);
|
||||
L21 = glm::vec3( 0.09f, 0.07f, 0.04f);
|
||||
L22 = glm::vec3( 0.67f, 0.67f, 0.52f);
|
||||
}
|
||||
break;
|
||||
case FUNSTON_BEACH_SUNSET: {
|
||||
L00 = glm::vec3( 0.68f, 0.69f, 0.70f);
|
||||
L1m1 = glm::vec3( 0.32f, 0.37f, 0.44f);
|
||||
L10 = glm::vec3(-0.17f, -0.17f, -0.17f);
|
||||
L11 = glm::vec3(-0.45f, -0.42f, -0.34f);
|
||||
L2m2 = glm::vec3(-0.17f, -0.17f, -0.15f);
|
||||
L2m1 = glm::vec3(-0.08f, -0.09f, -0.10f);
|
||||
L20 = glm::vec3(-0.03f, -0.02f, -0.01f);
|
||||
L21 = glm::vec3( 0.16f, 0.14f, 0.10f);
|
||||
L22 = glm::vec3( 0.37f, 0.31f, 0.20f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Light {
|
||||
public:
|
||||
enum Type {
|
||||
SUN = 0,
|
||||
POINT,
|
||||
SPOT,
|
||||
|
||||
NUM_TYPES,
|
||||
};
|
||||
|
||||
typedef Vec3 Color;
|
||||
|
||||
enum FlagBit {
|
||||
COLOR_BIT = 0,
|
||||
INTENSITY_BIT,
|
||||
RANGE_BIT,
|
||||
SPOT_BIT,
|
||||
TRANSFORM_BIT,
|
||||
|
||||
NUM_FLAGS,
|
||||
};
|
||||
typedef std::bitset<NUM_FLAGS> Flags;
|
||||
|
||||
Light();
|
||||
Light(const Light& light);
|
||||
Light& operator= (const Light& light);
|
||||
virtual ~Light();
|
||||
|
||||
void setType(Type type) { editSchema()._control.x = float(type); }
|
||||
Type getType() const { return Type((int) getSchema()._control.x); }
|
||||
|
||||
void setPosition(const Vec3& position);
|
||||
const Vec3& getPosition() const { return _transform.getTranslation(); }
|
||||
|
||||
void setDirection(const Vec3& direction);
|
||||
const Vec3& getDirection() const;
|
||||
|
||||
void setOrientation(const Quat& orientation);
|
||||
const glm::quat& getOrientation() const { return _transform.getRotation(); }
|
||||
|
||||
const Color& getColor() const { return getSchema()._color; }
|
||||
void setColor(const Color& color);
|
||||
|
||||
float getIntensity() const { return getSchema()._intensity; }
|
||||
void setIntensity(float intensity);
|
||||
|
||||
bool isRanged() const { return (getType() == POINT) || (getType() == SPOT ); }
|
||||
|
||||
void setMaximumRadius(float radius);
|
||||
float getMaximumRadius() const { return getSchema()._attenuation.w; }
|
||||
|
||||
// Spot properties
|
||||
bool isSpot() const { return getType() == SPOT; }
|
||||
void setSpotAngle(float angle);
|
||||
float getSpotAngle() const { return getSchema()._spot.z; }
|
||||
void setSpotExponent(float exponent);
|
||||
float getSpotExponent() const { return getSchema()._spot.w; }
|
||||
|
||||
// For editing purpose, show the light volume contour.
|
||||
// Set to non 0 to show it, the value is used as the intensity of the contour color
|
||||
void setShowContour(float show);
|
||||
float getShowContour() const { return getSchema()._control.w; }
|
||||
|
||||
// Spherical Harmonics storing the Ambien lighting approximation used for the Sun typed light
|
||||
void setAmbientSphere(const SphericalHarmonics& sphere) { _ambientSphere = sphere; }
|
||||
const SphericalHarmonics& getAmbientSphere() const { return _ambientSphere; }
|
||||
void setAmbientSpherePreset(SphericalHarmonics::Preset preset) { _ambientSphere.assignPreset(preset); }
|
||||
|
||||
// Schema to access the attribute values of the light
|
||||
class Schema {
|
||||
public:
|
||||
Vec4 _position;
|
||||
Vec3 _direction;
|
||||
float _spare0;
|
||||
Color _color;
|
||||
float _intensity;
|
||||
Vec4 _attenuation;
|
||||
Vec4 _spot;
|
||||
Vec4 _shadow;
|
||||
|
||||
Vec4 _control;
|
||||
|
||||
Schema() :
|
||||
_position(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
_direction(0.0f, 0.0f, -1.0f),
|
||||
_spare0(0.f),
|
||||
_color(1.0f),
|
||||
_intensity(1.0f),
|
||||
_attenuation(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
_spot(0.0f, 0.0f, 0.0f, 3.0f),
|
||||
_control(0.0f)
|
||||
{}
|
||||
};
|
||||
|
||||
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }
|
||||
|
||||
protected:
|
||||
|
||||
Flags _flags;
|
||||
UniformBufferView _schemaBuffer;
|
||||
Transform _transform;
|
||||
SphericalHarmonics _ambientSphere;
|
||||
|
||||
const Schema& getSchema() const { return _schemaBuffer.get<Schema>(); }
|
||||
Schema& editSchema() { return _schemaBuffer.edit<Schema>(); }
|
||||
};
|
||||
typedef QSharedPointer< Light > LightPointer;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -100,7 +100,6 @@ public:
|
|||
void setTextureView(MapChannel channel, const TextureView& texture);
|
||||
const TextureMap& getTextureMap() const { return _textureMap; }
|
||||
|
||||
const Schema* getSchema() const { return &_schemaBuffer.get<Schema>(); }
|
||||
protected:
|
||||
|
||||
Flags _flags;
|
||||
|
|
|
@ -202,14 +202,19 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
|
|||
|
||||
if (!domainObject.isEmpty()) {
|
||||
const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address";
|
||||
const QString DOMAIN_NETWORK_PORT_KEY = "network_port";
|
||||
const QString DOMAIN_ICE_SERVER_ADDRESS_KEY = "ice_server_address";
|
||||
|
||||
if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) {
|
||||
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
|
||||
|
||||
quint16 domainPort = domainObject.contains(DOMAIN_NETWORK_PORT_KEY)
|
||||
? domainObject[DOMAIN_NETWORK_PORT_KEY].toUInt()
|
||||
: DEFAULT_DOMAIN_SERVER_PORT;
|
||||
|
||||
qDebug() << "Possible domain change required to connect to" << domainHostname
|
||||
<< "on" << DEFAULT_DOMAIN_SERVER_PORT;
|
||||
emit possibleDomainChangeRequired(domainHostname, DEFAULT_DOMAIN_SERVER_PORT);
|
||||
<< "on" << domainPort;
|
||||
emit possibleDomainChangeRequired(domainHostname, domainPort);
|
||||
} else {
|
||||
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ const char SOLO_NODE_TYPES[2] = {
|
|||
NodeType::AudioMixer
|
||||
};
|
||||
|
||||
const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io");
|
||||
const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://metaverse.highfidelity.io");
|
||||
|
||||
LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) :
|
||||
_sessionUUID(),
|
||||
|
|
|
@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
|||
return 1;
|
||||
case PacketTypeEntityAddOrEdit:
|
||||
case PacketTypeEntityData:
|
||||
return VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME;
|
||||
return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE;
|
||||
case PacketTypeEntityErase:
|
||||
return 2;
|
||||
case PacketTypeAudioStreamStats:
|
||||
|
|
|
@ -127,6 +127,7 @@ const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4;
|
|||
const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7;
|
||||
const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8;
|
||||
const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -86,17 +86,9 @@ void UserActivityLogger::launch(QString applicationVersion) {
|
|||
logAction(ACTION_NAME, actionDetails);
|
||||
}
|
||||
|
||||
void UserActivityLogger::close(int delayTime) {
|
||||
void UserActivityLogger::close() {
|
||||
const QString ACTION_NAME = "close";
|
||||
|
||||
// In order to get the end of the session, we need to give the account manager enough time to send the packet.
|
||||
QEventLoop loop;
|
||||
QTimer timer;
|
||||
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||||
// Now we can log it
|
||||
logAction(ACTION_NAME, QJsonObject());
|
||||
timer.start(delayTime);
|
||||
loop.exec();
|
||||
}
|
||||
|
||||
void UserActivityLogger::changedDisplayName(QString displayName) {
|
||||
|
|
|
@ -30,7 +30,7 @@ public slots:
|
|||
void logAction(QString action, QJsonObject details = QJsonObject(), JSONCallbackParameters params = JSONCallbackParameters());
|
||||
|
||||
void launch(QString applicationVersion);
|
||||
void close(int delayTime);
|
||||
void close();
|
||||
void changedDisplayName(QString displayName);
|
||||
void changedModel(QString typeOfModel, QString modelURL);
|
||||
void changedDomain(QString domainURL);
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <Shape.h>
|
||||
#include <ShapeCollider.h>
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include "OctreeConstants.h"
|
||||
|
@ -856,26 +855,6 @@ bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool findShapeCollisionsOp(OctreeElement* element, void* extraData) {
|
||||
ShapeArgs* args = static_cast<ShapeArgs*>(extraData);
|
||||
// coarse check against bounds
|
||||
AACube cube = element->getAACube();
|
||||
cube.scale(TREE_SCALE);
|
||||
if (!cube.expandedContains(args->shape->getTranslation(), args->shape->getBoundingRadius())) {
|
||||
return false;
|
||||
}
|
||||
if (element->hasContent()) {
|
||||
if (element->findShapeCollisions(args->shape, args->collisions)) {
|
||||
args->found = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!element->isLeaf()) {
|
||||
return true; // recurse on children
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint qHash(const glm::vec3& point) {
|
||||
// NOTE: TREE_SCALE = 16384 (15 bits) and multiplier is 1024 (11 bits),
|
||||
// so each component (26 bits) uses more than its alloted 21 bits.
|
||||
|
@ -947,37 +926,6 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end
|
|||
return args.found;
|
||||
}
|
||||
|
||||
bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
|
||||
Octree::lockType lockType, bool* accurateResult) {
|
||||
|
||||
ShapeArgs args = { shape, collisions, false };
|
||||
|
||||
bool gotLock = false;
|
||||
if (lockType == Octree::Lock) {
|
||||
lockForRead();
|
||||
gotLock = true;
|
||||
} else if (lockType == Octree::TryLock) {
|
||||
gotLock = tryLockForRead();
|
||||
if (!gotLock) {
|
||||
if (accurateResult) {
|
||||
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
|
||||
}
|
||||
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
|
||||
}
|
||||
}
|
||||
|
||||
recurseTreeWithOperation(findShapeCollisionsOp, &args);
|
||||
|
||||
if (gotLock) {
|
||||
unlock();
|
||||
}
|
||||
|
||||
if (accurateResult) {
|
||||
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
|
||||
}
|
||||
return args.found;
|
||||
}
|
||||
|
||||
bool Octree::findContentInCube(const AACube& cube, CubeList& cubes) {
|
||||
if (!tryLockForRead()) {
|
||||
return false;
|
||||
|
|
|
@ -308,9 +308,6 @@ public:
|
|||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration,
|
||||
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
bool findShapeCollisions(const Shape* shape, CollisionList& collisions,
|
||||
Octree::lockType = Octree::TryLock, bool* accurateResult = NULL);
|
||||
|
||||
bool findContentInCube(const AACube& cube, CubeList& cubes);
|
||||
|
||||
OctreeElement* getElementEnclosingPoint(const glm::vec3& point,
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <NodeList.h>
|
||||
#include <PerfStat.h>
|
||||
#include <AACubeShape.h>
|
||||
#include <ShapeCollider.h>
|
||||
|
||||
#include "AACube.h"
|
||||
#include "OctalCode.h"
|
||||
|
@ -1396,12 +1395,6 @@ bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius,
|
|||
return _cube.findSpherePenetration(center, radius, penetration);
|
||||
}
|
||||
|
||||
bool OctreeElement::findShapeCollisions(const Shape* shape, CollisionList& collisions) const {
|
||||
AACube cube = getAACube();
|
||||
cube.scale(TREE_SCALE);
|
||||
return ShapeCollider::collideShapeWithAACubeLegacy(shape, cube.calcCenter(), cube.getScale(), collisions);
|
||||
}
|
||||
|
||||
// TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)...
|
||||
OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) {
|
||||
OctreeElement* child = NULL;
|
||||
|
|
|
@ -128,8 +128,6 @@ public:
|
|||
virtual bool findSpherePenetration(const glm::vec3& center, float radius,
|
||||
glm::vec3& penetration, void** penetratedObject) const;
|
||||
|
||||
virtual bool findShapeCollisions(const Shape* shape, CollisionList& collisions) const;
|
||||
|
||||
// Base class methods you don't need to implement
|
||||
const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; }
|
||||
OctreeElement* getChildAtIndex(int childIndex) const;
|
||||
|
|
|
@ -213,7 +213,9 @@ void OctreePersistThread::persist() {
|
|||
}
|
||||
_tree->unlock();
|
||||
|
||||
qDebug() << "persist operation calling backup...";
|
||||
backup(); // handle backup if requested
|
||||
qDebug() << "persist operation DONE with backup...";
|
||||
|
||||
|
||||
// create our "lock" file to indicate we're saving.
|
||||
|
@ -347,6 +349,7 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) {
|
|||
|
||||
|
||||
void OctreePersistThread::backup() {
|
||||
qDebug() << "backup operation wantBackup:" << _wantBackup;
|
||||
if (_wantBackup) {
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
|
@ -354,10 +357,12 @@ void OctreePersistThread::backup() {
|
|||
BackupRule& rule = _backupRules[i];
|
||||
|
||||
quint64 sinceLastBackup = now - rule.lastBackup;
|
||||
|
||||
quint64 SECS_TO_USECS = 1000 * 1000;
|
||||
quint64 intervalToBackup = rule.interval * SECS_TO_USECS;
|
||||
|
||||
|
||||
qDebug() << "Checking [" << rule.name << "] - Time since last backup [" << sinceLastBackup << "] " <<
|
||||
"compared to backup interval [" << intervalToBackup << "]...";
|
||||
|
||||
if (sinceLastBackup > intervalToBackup) {
|
||||
qDebug() << "Time since last backup [" << sinceLastBackup << "] for rule [" << rule.name
|
||||
<< "] exceeds backup interval [" << intervalToBackup << "] doing backup now...";
|
||||
|
@ -379,15 +384,22 @@ void OctreePersistThread::backup() {
|
|||
}
|
||||
|
||||
|
||||
qDebug() << "backing up persist file " << _filename << "to" << backupFileName << "...";
|
||||
bool result = QFile::copy(_filename, backupFileName);
|
||||
if (result) {
|
||||
qDebug() << "DONE backing up persist file...";
|
||||
QFile persistFile(_filename);
|
||||
if (persistFile.exists()) {
|
||||
qDebug() << "backing up persist file " << _filename << "to" << backupFileName << "...";
|
||||
bool result = QFile::copy(_filename, backupFileName);
|
||||
if (result) {
|
||||
qDebug() << "DONE backing up persist file...";
|
||||
rule.lastBackup = now; // only record successful backup in this case.
|
||||
} else {
|
||||
qDebug() << "ERROR in backing up persist file...";
|
||||
}
|
||||
} else {
|
||||
qDebug() << "ERROR in backing up persist file...";
|
||||
qDebug() << "persist file " << _filename << " does not exist. " <<
|
||||
"nothing to backup for this rule ["<< rule.name << "]...";
|
||||
}
|
||||
|
||||
rule.lastBackup = now;
|
||||
} else {
|
||||
qDebug() << "Backup not needed for this rule ["<< rule.name << "]...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <Shape.h> // for FOO_SHAPE types
|
||||
#include <SharedUtil.h> // for MILLIMETERS_PER_METER
|
||||
|
||||
#include "ShapeInfoUtil.h"
|
||||
|
@ -18,36 +17,30 @@
|
|||
int ShapeInfoUtil::toBulletShapeType(int shapeInfoType) {
|
||||
int bulletShapeType = INVALID_SHAPE_PROXYTYPE;
|
||||
switch(shapeInfoType) {
|
||||
case BOX_SHAPE:
|
||||
case SHAPE_TYPE_BOX:
|
||||
bulletShapeType = BOX_SHAPE_PROXYTYPE;
|
||||
break;
|
||||
case SPHERE_SHAPE:
|
||||
case SHAPE_TYPE_SPHERE:
|
||||
bulletShapeType = SPHERE_SHAPE_PROXYTYPE;
|
||||
break;
|
||||
case CAPSULE_SHAPE:
|
||||
case SHAPE_TYPE_CAPSULE_Y:
|
||||
bulletShapeType = CAPSULE_SHAPE_PROXYTYPE;
|
||||
break;
|
||||
case CYLINDER_SHAPE:
|
||||
bulletShapeType = CYLINDER_SHAPE_PROXYTYPE;
|
||||
break;
|
||||
}
|
||||
return bulletShapeType;
|
||||
}
|
||||
|
||||
int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) {
|
||||
int shapeInfoType = INVALID_SHAPE;
|
||||
int shapeInfoType = SHAPE_TYPE_NONE;
|
||||
switch(bulletShapeType) {
|
||||
case BOX_SHAPE_PROXYTYPE:
|
||||
shapeInfoType = BOX_SHAPE;
|
||||
shapeInfoType = SHAPE_TYPE_BOX;
|
||||
break;
|
||||
case SPHERE_SHAPE_PROXYTYPE:
|
||||
shapeInfoType = SPHERE_SHAPE;
|
||||
shapeInfoType = SHAPE_TYPE_SPHERE;
|
||||
break;
|
||||
case CAPSULE_SHAPE_PROXYTYPE:
|
||||
shapeInfoType = CAPSULE_SHAPE;
|
||||
break;
|
||||
case CYLINDER_SHAPE_PROXYTYPE:
|
||||
shapeInfoType = CYLINDER_SHAPE;
|
||||
shapeInfoType = SHAPE_TYPE_CAPSULE_Y;
|
||||
break;
|
||||
}
|
||||
return shapeInfoType;
|
||||
|
@ -57,29 +50,16 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf
|
|||
if (shape) {
|
||||
int type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType());
|
||||
switch(type) {
|
||||
case BOX_SHAPE: {
|
||||
case SHAPE_TYPE_BOX: {
|
||||
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
|
||||
info.setBox(bulletToGLM(boxShape->getHalfExtentsWithMargin()));
|
||||
}
|
||||
break;
|
||||
case SPHERE_SHAPE: {
|
||||
case SHAPE_TYPE_SPHERE: {
|
||||
const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
|
||||
info.setSphere(sphereShape->getRadius());
|
||||
}
|
||||
break;
|
||||
case CYLINDER_SHAPE: {
|
||||
// NOTE: we only support cylinders along yAxis
|
||||
const btCylinderShape* cylinderShape = static_cast<const btCylinderShape*>(shape);
|
||||
btVector3 halfExtents = cylinderShape->getHalfExtentsWithMargin();
|
||||
info.setCylinder(halfExtents.getX(), halfExtents.getY());
|
||||
}
|
||||
break;
|
||||
case CAPSULE_SHAPE: {
|
||||
// NOTE: we only support capsules along yAxis
|
||||
const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
|
||||
info.setCapsule(capsuleShape->getRadius(), capsuleShape->getHalfHeight());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
info.clear();
|
||||
break;
|
||||
|
@ -91,77 +71,23 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf
|
|||
|
||||
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
||||
btCollisionShape* shape = NULL;
|
||||
const QVector<glm::vec3>& data = info.getData();
|
||||
switch(info.getType()) {
|
||||
case BOX_SHAPE: {
|
||||
// data[0] is halfExtents
|
||||
shape = new btBoxShape(glmToBullet(data[0]));
|
||||
case SHAPE_TYPE_BOX: {
|
||||
shape = new btBoxShape(glmToBullet(info.getHalfExtents()));
|
||||
}
|
||||
break;
|
||||
case SPHERE_SHAPE: {
|
||||
float radius = data[0].z;
|
||||
case SHAPE_TYPE_SPHERE: {
|
||||
float radius = info.getHalfExtents().x;
|
||||
shape = new btSphereShape(radius);
|
||||
}
|
||||
break;
|
||||
case CYLINDER_SHAPE: {
|
||||
// NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X
|
||||
// data[0] = btVector3(radius, halfHeight, unused)
|
||||
shape = new btCylinderShape(glmToBullet(data[0]));
|
||||
}
|
||||
break;
|
||||
case CAPSULE_SHAPE: {
|
||||
float radius = data[0].x;
|
||||
float height = 2.0f * data[0].y;
|
||||
case SHAPE_TYPE_CAPSULE_Y: {
|
||||
glm::vec3 halfExtents = info.getHalfExtents();
|
||||
float radius = halfExtents.x;
|
||||
float height = 2.0f * halfExtents.y;
|
||||
shape = new btCapsuleShape(radius, height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
DoubleHashKey ShapeInfoUtil::computeHash(const ShapeInfo& info) {
|
||||
DoubleHashKey key;
|
||||
// compute hash
|
||||
// scramble the bits of the type
|
||||
// TODO?: provide lookup table for hash of info._type rather than recompute?
|
||||
int primeIndex = 0;
|
||||
unsigned int hash = DoubleHashKey::hashFunction((unsigned int)info.getType(), primeIndex++);
|
||||
const QVector<glm::vec3>& data = info.getData();
|
||||
|
||||
glm::vec3 tmpData;
|
||||
int numData = data.size();
|
||||
for (int i = 0; i < numData; ++i) {
|
||||
tmpData = data[i];
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
unsigned int floatHash =
|
||||
DoubleHashKey::hashFunction((int)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++);
|
||||
hash ^= floatHash;
|
||||
}
|
||||
}
|
||||
key._hash = (int)hash;
|
||||
|
||||
// compute hash2
|
||||
// scramble the bits of the type
|
||||
// TODO?: provide lookup table for hash2 of info._type rather than recompute?
|
||||
hash = DoubleHashKey::hashFunction2((unsigned int)info.getType());
|
||||
|
||||
for (int i = 0; i < numData; ++i) {
|
||||
tmpData = data[i];
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
unsigned int floatHash =
|
||||
DoubleHashKey::hashFunction2((int)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f));
|
||||
hash += ~(floatHash << 17);
|
||||
hash ^= (floatHash >> 11);
|
||||
hash += (floatHash << 4);
|
||||
hash ^= (floatHash >> 7);
|
||||
hash += ~(floatHash << 10);
|
||||
hash = (hash << 16) | (hash >> 16);
|
||||
}
|
||||
}
|
||||
key._hash2 = (int)hash;
|
||||
return key;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "DoubleHashKey.h"
|
||||
|
||||
// translates between ShapeInfo and btShape
|
||||
|
||||
namespace ShapeInfoUtil {
|
||||
|
@ -26,8 +24,6 @@ namespace ShapeInfoUtil {
|
|||
|
||||
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
|
||||
|
||||
DoubleHashKey computeHash(const ShapeInfo& info);
|
||||
|
||||
// TODO? just use bullet shape types everywhere?
|
||||
int toBulletShapeType(int shapeInfoType);
|
||||
int fromBulletShapeType(int bulletShapeType);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue