mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 01:22:08 +02:00
merge with upstream/master
This commit is contained in:
commit
c110fcbfad
76 changed files with 2117 additions and 890 deletions
|
@ -40,7 +40,7 @@ if (WIN32)
|
|||
elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
|
||||
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-strict-aliasing -ggdb")
|
||||
endif(WIN32)
|
||||
|
||||
if (NOT MSVC12)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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",
|
||||
|
|
248
examples/controllers/oculus/goTo.js
Normal file
248
examples/controllers/oculus/goTo.js
Normal file
|
@ -0,0 +1,248 @@
|
|||
//
|
||||
// goTo.js
|
||||
// examples
|
||||
//
|
||||
// Created by Thijs Wenker on 12/28/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Control a virtual keyboard using your favorite HMD.
|
||||
// Usage: Enable VR-mode and go to First person mode,
|
||||
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
||||
//
|
||||
// Enter a location URL using your HMD. Press Enter to pop-up the virtual keyboard and location input.
|
||||
// Press Space on the keyboard or the X button on your gamepad to press a key that you have selected.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("../../libraries/globals.js");
|
||||
Script.include("../../libraries/virtualKeyboard.js");
|
||||
|
||||
const MAX_SHOW_INSTRUCTION_TIMES = 2;
|
||||
const INSTRUCTIONS_SETTING = "GoToInstructionsShowCounter"
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
|
||||
function Instructions(imageURL, originalWidth, originalHeight) {
|
||||
var tthis = this;
|
||||
this.originalSize = {w: originalWidth, h: originalHeight};
|
||||
this.visible = false;
|
||||
this.overlay = Overlays.addOverlay("image", {
|
||||
imageURL: imageURL,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: originalWidth,
|
||||
height: originalHeight,
|
||||
alpha: 1,
|
||||
visible: this.visible
|
||||
});
|
||||
|
||||
this.show = function() {
|
||||
var timesShown = Settings.getValue(INSTRUCTIONS_SETTING);
|
||||
timesShown = timesShown === "" ? 0 : parseInt(timesShown);
|
||||
print(timesShown);
|
||||
if (timesShown < MAX_SHOW_INSTRUCTION_TIMES) {
|
||||
Settings.setValue(INSTRUCTIONS_SETTING, timesShown + 1);
|
||||
tthis.visible = true;
|
||||
tthis.rescale();
|
||||
Overlays.editOverlay(tthis.overlay, {visible: tthis.visible});
|
||||
return;
|
||||
}
|
||||
tthis.remove();
|
||||
}
|
||||
|
||||
this.remove = function() {
|
||||
Overlays.deleteOverlay(tthis.overlay);
|
||||
tthis.visible = false;
|
||||
};
|
||||
|
||||
this.rescale = function() {
|
||||
var scale = Math.min(windowDimensions.x / tthis.originalSize.w, windowDimensions.y / tthis.originalSize.h);
|
||||
var newWidth = tthis.originalSize.w * scale;
|
||||
var newHeight = tthis.originalSize.h * scale;
|
||||
Overlays.editOverlay(tthis.overlay, {
|
||||
x: (windowDimensions.x / 2) - (newWidth / 2),
|
||||
y: (windowDimensions.y / 2) - (newHeight / 2),
|
||||
width: newWidth,
|
||||
height: newHeight
|
||||
});
|
||||
};
|
||||
this.rescale();
|
||||
};
|
||||
|
||||
var theInstruction = new Instructions(HIFI_PUBLIC_BUCKET + "images/tutorial-goTo.svg", 457, 284.1);
|
||||
|
||||
var firstControllerPlugged = false;
|
||||
|
||||
|
||||
var cursor = new Cursor({visible: false});
|
||||
var keyboard = new Keyboard({visible: false});
|
||||
var textFontSize = 9;
|
||||
var text = null;
|
||||
var locationURL = "";
|
||||
|
||||
function appendChar(char) {
|
||||
locationURL += char;
|
||||
updateTextOverlay();
|
||||
Overlays.editOverlay(text, {text: locationURL});
|
||||
}
|
||||
|
||||
function deleteChar() {
|
||||
if (locationURL.length > 0) {
|
||||
locationURL = locationURL.substring(0, locationURL.length - 1);
|
||||
updateTextOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function updateTextOverlay() {
|
||||
var maxLineWidth = Overlays.textSize(text, locationURL).width;
|
||||
var suggestedFontSize = (windowDimensions.x / maxLineWidth) * textFontSize * 0.90;
|
||||
var maxFontSize = 140;
|
||||
textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize;
|
||||
var topMargin = (250 - textFontSize) / 4;
|
||||
Overlays.editOverlay(text, {text: locationURL, font: {size: textFontSize}, topMargin: topMargin, visible: keyboard.visible});
|
||||
maxLineWidth = Overlays.textSize(text, locationURL).width;
|
||||
Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - maxLineWidth) / 2});
|
||||
}
|
||||
|
||||
keyboard.onKeyPress = function(event) {
|
||||
if (event.event == 'keypress') {
|
||||
appendChar(event.char);
|
||||
}
|
||||
};
|
||||
|
||||
keyboard.onKeyRelease = function(event) {
|
||||
// you can cancel a key by releasing its focusing before releasing it
|
||||
if (event.focus) {
|
||||
if (event.event == 'delete') {
|
||||
deleteChar();
|
||||
} else if (event.event == 'submit' || event.event == 'enter') {
|
||||
print("going to hifi://" + locationURL);
|
||||
location = "hifi://" + locationURL;
|
||||
locationURL = "";
|
||||
keyboard.hide();
|
||||
cursor.hide();
|
||||
updateTextOverlay();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
keyboard.onFullyLoaded = function() {
|
||||
print("Virtual-keyboard fully loaded.");
|
||||
var dimensions = Controller.getViewportDimensions();
|
||||
text = Overlays.addOverlay("text", {
|
||||
x: 0,
|
||||
y: dimensions.y - keyboard.height() - 260,
|
||||
width: dimensions.x,
|
||||
height: 250,
|
||||
backgroundColor: { red: 255, green: 255, blue: 255},
|
||||
color: { red: 0, green: 0, blue: 0},
|
||||
topMargin: 5,
|
||||
leftMargin: 0,
|
||||
font: {size: textFontSize},
|
||||
text: "",
|
||||
alpha: 0.8,
|
||||
visible: keyboard.visible
|
||||
});
|
||||
updateTextOverlay();
|
||||
// the cursor is being loaded after the keyboard, else it will be on the background of the keyboard
|
||||
cursor.initialize();
|
||||
cursor.updateVisibility(keyboard.visible);
|
||||
cursor.onUpdate = function(position) {
|
||||
keyboard.setFocusPosition(position.x, position.y);
|
||||
};
|
||||
};
|
||||
|
||||
function keyPressEvent(event) {
|
||||
if (theInstruction.visible) {
|
||||
return;
|
||||
}
|
||||
if (event.key === SPACEBAR_CHARCODE) {
|
||||
keyboard.pressFocussedKey();
|
||||
} else if (event.key === ENTER_CHARCODE || event.key === RETURN_CHARCODE) {
|
||||
keyboard.toggle();
|
||||
if (cursor !== undefined) {
|
||||
cursor.updateVisibility(keyboard.visible);
|
||||
}
|
||||
Overlays.editOverlay(text, {visible: keyboard.visible});
|
||||
}
|
||||
}
|
||||
|
||||
function keyReleaseEvent(event) {
|
||||
if (theInstruction.visible) {
|
||||
return;
|
||||
}
|
||||
if (event.key === SPACEBAR_CHARCODE) {
|
||||
keyboard.releaseKeys();
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
keyboard.remove();
|
||||
cursor.remove();
|
||||
Overlays.deleteOverlay(text);
|
||||
Overlays.deleteOverlay(textSizeMeasureOverlay);
|
||||
Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE});
|
||||
Controller.releaseKeyEvents({key: RETURN_CHARCODE});
|
||||
Controller.releaseKeyEvents({key: ENTER_CHARCODE});
|
||||
theInstruction.remove();
|
||||
}
|
||||
|
||||
function reportButtonValue(button, newValue, oldValue) {
|
||||
if (theInstruction.visible) {
|
||||
if (button == Joysticks.BUTTON_FACE_BOTTOM && newValue) {
|
||||
theInstruction.remove();
|
||||
}
|
||||
} else if (button == Joysticks.BUTTON_FACE_BOTTOM) {
|
||||
if (newValue) {
|
||||
keyboard.pressFocussedKey();
|
||||
} else {
|
||||
keyboard.releaseKeys();
|
||||
}
|
||||
} else if (button == Joysticks.BUTTON_FACE_RIGHT && newValue) {
|
||||
deleteChar();
|
||||
} else if (button == Joysticks.BUTTON_FACE_LEFT && newValue) {
|
||||
keyboard.hide();
|
||||
if (cursor !== undefined) {
|
||||
cursor.hide();
|
||||
}
|
||||
Overlays.editOverlay(text, {visible: false});
|
||||
} else if (button == Joysticks.BUTTON_RIGHT_SHOULDER && newValue) {
|
||||
if (keyboard.visible) {
|
||||
print("going to hifi://" + locationURL);
|
||||
location = "hifi://" + locationURL;
|
||||
locationURL = "";
|
||||
keyboard.hide();
|
||||
cursor.hide();
|
||||
updateTextOverlay();
|
||||
return;
|
||||
}
|
||||
keyboard.show();
|
||||
if (cursor !== undefined) {
|
||||
cursor.show();
|
||||
}
|
||||
Overlays.editOverlay(text, {visible: true});
|
||||
}
|
||||
}
|
||||
|
||||
function addJoystick(gamepad) {
|
||||
gamepad.buttonStateChanged.connect(reportButtonValue);
|
||||
if (!firstControllerPlugged) {
|
||||
firstControllerPlugged = true;
|
||||
theInstruction.show();
|
||||
}
|
||||
}
|
||||
|
||||
var allJoysticks = Joysticks.getAllJoysticks();
|
||||
for (var i = 0; i < allJoysticks.length; i++) {
|
||||
addJoystick(allJoysticks[i]);
|
||||
}
|
||||
|
||||
Joysticks.joystickAdded.connect(addJoystick);
|
||||
Controller.captureKeyEvents({key: RETURN_CHARCODE});
|
||||
Controller.captureKeyEvents({key: ENTER_CHARCODE});
|
||||
Controller.captureKeyEvents({key: SPACEBAR_CHARCODE});
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
183
examples/controllers/oculus/virtualKeyboardTextEntityExample.js
Normal file
183
examples/controllers/oculus/virtualKeyboardTextEntityExample.js
Normal file
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// virtualKeyboardTextEntityExample.js
|
||||
// examples
|
||||
//
|
||||
// Created by Thijs Wenker on 12/28/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Control a virtual keyboard using your favorite HMD.
|
||||
// Usage: Enable VR-mode and go to First person mode,
|
||||
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
||||
//
|
||||
// leased some code from newEditEntities.js for Text Entity example
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("../../libraries/globals.js");
|
||||
Script.include("../../libraries/virtualKeyboard.js");
|
||||
|
||||
const SPAWN_DISTANCE = 1;
|
||||
const DEFAULT_TEXT_DIMENSION_Z = 0.02;
|
||||
|
||||
const TEXT_MARGIN_TOP = 0.15;
|
||||
const TEXT_MARGIN_LEFT = 0.15;
|
||||
const TEXT_MARGIN_RIGHT = 0.17;
|
||||
const TEXT_MARGIN_BOTTOM = 0.17;
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var cursor = new Cursor();
|
||||
var keyboard = new Keyboard();
|
||||
var textFontSize = 9;
|
||||
var text = null;
|
||||
var textText = "";
|
||||
var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false});
|
||||
|
||||
function appendChar(char) {
|
||||
textText += char;
|
||||
updateTextOverlay();
|
||||
Overlays.editOverlay(text, {text: textText});
|
||||
}
|
||||
|
||||
function deleteChar() {
|
||||
if (textText.length > 0) {
|
||||
textText = textText.substring(0, textText.length - 1);
|
||||
updateTextOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function updateTextOverlay() {
|
||||
var textLines = textText.split("\n");
|
||||
var suggestedFontSize = (windowDimensions.x / Overlays.textSize(text, textText).width) * textFontSize * 0.90;
|
||||
var maxFontSize = 170 / textLines.length;
|
||||
textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize;
|
||||
var topMargin = (250 - (textFontSize * textLines.length)) / 4;
|
||||
Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin});
|
||||
Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - Overlays.textSize(text, textLines).width) / 2});
|
||||
}
|
||||
|
||||
keyboard.onKeyPress = function(event) {
|
||||
if (event.event == 'keypress') {
|
||||
appendChar(event.char);
|
||||
} else if (event.event == 'enter') {
|
||||
appendChar("\n");
|
||||
}
|
||||
};
|
||||
|
||||
keyboard.onKeyRelease = function(event) {
|
||||
print("Key release event test");
|
||||
// you can cancel a key by releasing its focusing before releasing it
|
||||
if (event.focus) {
|
||||
if (event.event == 'delete') {
|
||||
deleteChar();
|
||||
} else if (event.event == 'submit') {
|
||||
print(textText);
|
||||
|
||||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
var textLines = textText.split("\n");
|
||||
var maxLineWidth = Overlays.textSize(textSizeMeasureOverlay, textText).width;
|
||||
var usernameLine = "--" + GlobalServices.myUsername;
|
||||
var usernameWidth = Overlays.textSize(textSizeMeasureOverlay, usernameLine).width;
|
||||
if (maxLineWidth < usernameWidth) {
|
||||
maxLineWidth = usernameWidth;
|
||||
} else {
|
||||
var spaceableWidth = maxLineWidth - usernameWidth;
|
||||
//TODO: WORKAROUND WARNING BELOW Fix this when spaces are not trimmed out of the textsize calculation anymore
|
||||
var spaceWidth = Overlays.textSize(textSizeMeasureOverlay, "| |").width
|
||||
- Overlays.textSize(textSizeMeasureOverlay, "||").width;
|
||||
var numberOfSpaces = Math.floor(spaceableWidth / spaceWidth);
|
||||
for (var i = 0; i < numberOfSpaces; i++) {
|
||||
usernameLine = " " + usernameLine;
|
||||
}
|
||||
}
|
||||
var dimension_x = maxLineWidth + TEXT_MARGIN_RIGHT + TEXT_MARGIN_LEFT;
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
type: "Text",
|
||||
rotation: MyAvatar.orientation,
|
||||
position: position,
|
||||
dimensions: { x: dimension_x, y: (textLines.length + 1) * 0.14 + TEXT_MARGIN_TOP + TEXT_MARGIN_BOTTOM, z: DEFAULT_TEXT_DIMENSION_Z },
|
||||
backgroundColor: { red: 0, green: 0, blue: 0 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: textText + "\n" + usernameLine,
|
||||
lineHeight: 0.1
|
||||
});
|
||||
}
|
||||
textText = "";
|
||||
updateTextOverlay();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
keyboard.onFullyLoaded = function() {
|
||||
print("Virtual-keyboard fully loaded.");
|
||||
var dimensions = Controller.getViewportDimensions();
|
||||
text = Overlays.addOverlay("text", {
|
||||
x: 0,
|
||||
y: dimensions.y - keyboard.height() - 260,
|
||||
width: dimensions.x,
|
||||
height: 250,
|
||||
backgroundColor: { red: 255, green: 255, blue: 255},
|
||||
color: { red: 0, green: 0, blue: 0},
|
||||
topMargin: 5,
|
||||
leftMargin: 0,
|
||||
font: {size: textFontSize},
|
||||
text: "",
|
||||
alpha: 0.8
|
||||
});
|
||||
updateTextOverlay();
|
||||
// the cursor is being loaded after the keyboard, else it will be on the background of the keyboard
|
||||
cursor.initialize();
|
||||
cursor.onUpdate = function(position) {
|
||||
keyboard.setFocusPosition(position.x, position.y);
|
||||
};
|
||||
};
|
||||
|
||||
function keyPressEvent(event) {
|
||||
if (event.key === SPACEBAR_CHARCODE) {
|
||||
keyboard.pressFocussedKey();
|
||||
}
|
||||
}
|
||||
|
||||
function keyReleaseEvent(event) {
|
||||
if (event.key === SPACEBAR_CHARCODE) {
|
||||
keyboard.releaseKeys();
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
keyboard.remove();
|
||||
cursor.remove();
|
||||
Overlays.deleteOverlay(text);
|
||||
Overlays.deleteOverlay(textSizeMeasureOverlay);
|
||||
Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE});
|
||||
}
|
||||
|
||||
function reportButtonValue(button, newValue, oldValue) {
|
||||
if (button == Joysticks.BUTTON_FACE_BOTTOM) {
|
||||
if (newValue) {
|
||||
keyboard.pressFocussedKey();
|
||||
} else {
|
||||
keyboard.releaseKeys();
|
||||
}
|
||||
} else if (button == Joysticks.BUTTON_FACE_RIGHT && newValue) {
|
||||
deleteChar();
|
||||
}
|
||||
}
|
||||
|
||||
function addJoystick(gamepad) {
|
||||
gamepad.buttonStateChanged.connect(reportButtonValue);
|
||||
}
|
||||
|
||||
var allJoysticks = Joysticks.getAllJoysticks();
|
||||
for (var i = 0; i < allJoysticks.length; i++) {
|
||||
addJoystick(allJoysticks[i]);
|
||||
}
|
||||
|
||||
Joysticks.joystickAdded.connect(addJoystick);
|
||||
Controller.captureKeyEvents({key: SPACEBAR_CHARCODE});
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -127,7 +127,7 @@ var toolBar = (function () {
|
|||
height: toolHeight,
|
||||
alpha: 0.9,
|
||||
visible: true
|
||||
}, true, false);
|
||||
});
|
||||
|
||||
browseModelsButton = toolBar.addTool({
|
||||
imageURL: toolIconUrl + "list-icon.svg",
|
||||
|
@ -190,6 +190,7 @@ var toolBar = (function () {
|
|||
cameraManager.enable();
|
||||
entityListTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
Window.setFocus();
|
||||
}
|
||||
|
@ -261,6 +262,8 @@ var toolBar = (function () {
|
|||
toolBar.move(toolsX, toolsY);
|
||||
};
|
||||
|
||||
var newModelButtonDown = false;
|
||||
var browseModelsButtonDown = false;
|
||||
that.mousePressEvent = function (event) {
|
||||
var clickedOverlay,
|
||||
url,
|
||||
|
@ -273,19 +276,14 @@ var toolBar = (function () {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Handle these two buttons in the mouseRelease event handler so that we don't suppress a mouseRelease event from
|
||||
// occurring when showing a modal dialog.
|
||||
if (newModelButton === toolBar.clicked(clickedOverlay)) {
|
||||
url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]);
|
||||
if (url !== null && url !== "") {
|
||||
addModel(url);
|
||||
}
|
||||
newModelButtonDown = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (browseModelsButton === toolBar.clicked(clickedOverlay)) {
|
||||
url = Window.s3Browse(".*(fbx|FBX)");
|
||||
if (url !== null && url !== "") {
|
||||
addModel(url);
|
||||
}
|
||||
browseModelsButtonDown = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -347,6 +345,7 @@ var toolBar = (function () {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (newTextButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
|
@ -366,10 +365,37 @@ var toolBar = (function () {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
that.mouseReleaseEvent = function(event) {
|
||||
var handled = false;
|
||||
if (newModelButtonDown) {
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
||||
if (newModelButton === toolBar.clicked(clickedOverlay)) {
|
||||
url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]);
|
||||
if (url !== null && url !== "") {
|
||||
addModel(url);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
} else if (browseModelsButtonDown) {
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
||||
if (browseModelsButton === toolBar.clicked(clickedOverlay)) {
|
||||
url = Window.s3Browse(".*(fbx|FBX)");
|
||||
if (url !== null && url !== "") {
|
||||
addModel(url);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
newModelButtonDown = false;
|
||||
browseModelsButtonDown = false;
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
that.cleanup = function () {
|
||||
toolBar.cleanup();
|
||||
};
|
||||
|
@ -532,8 +558,13 @@ function highlightEntityUnderCursor(position, accurateRay) {
|
|||
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
if (toolBar.mouseReleaseEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
if (placingEntityID) {
|
||||
selectionManager.setSelections([placingEntityID]);
|
||||
if (isActive) {
|
||||
selectionManager.setSelections([placingEntityID]);
|
||||
}
|
||||
placingEntityID = null;
|
||||
}
|
||||
if (isActive && selectionManager.hasSelection()) {
|
||||
|
@ -956,9 +987,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();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -9,179 +9,50 @@
|
|||
// Usage: Enable VR-mode and go to First person mode,
|
||||
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
||||
//
|
||||
// leased some code from newEditEntities.js for Text Entity example
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
// experimental 3dmode
|
||||
THREE_D_MODE = false;
|
||||
|
||||
const KBD_UPPERCASE_DEFAULT = 0;
|
||||
const KBD_LOWERCASE_DEFAULT = 1;
|
||||
const KBD_UPPERCASE_HOVER = 2;
|
||||
const KBD_LOWERCASE_HOVER = 3;
|
||||
const KBD_BACKGROUND = 4;
|
||||
KBD_UPPERCASE_DEFAULT = 0;
|
||||
KBD_LOWERCASE_DEFAULT = 1;
|
||||
KBD_UPPERCASE_HOVER = 2;
|
||||
KBD_LOWERCASE_HOVER = 3;
|
||||
KBD_BACKGROUND = 4;
|
||||
|
||||
const KEYBOARD_URL = HIFI_PUBLIC_BUCKET + "images/keyboard.svg";
|
||||
const CURSOR_URL = HIFI_PUBLIC_BUCKET + "images/cursor.svg";
|
||||
KEYBOARD_URL = HIFI_PUBLIC_BUCKET + "images/keyboard.svg";
|
||||
CURSOR_URL = HIFI_PUBLIC_BUCKET + "images/cursor.svg";
|
||||
|
||||
const SPACEBAR_CHARCODE = 32;
|
||||
RETURN_CHARCODE = 0x01000004;
|
||||
ENTER_CHARCODE = 0x01000005;
|
||||
SPACEBAR_CHARCODE = 32;
|
||||
|
||||
const KEYBOARD_WIDTH = 1174.7;
|
||||
const KEYBOARD_HEIGHT = 434.1;
|
||||
KEYBOARD_WIDTH = 1174.7;
|
||||
KEYBOARD_HEIGHT = 434.1;
|
||||
|
||||
const CURSOR_WIDTH = 33.9;
|
||||
const CURSOR_HEIGHT = 33.9;
|
||||
CURSOR_WIDTH = 33.9;
|
||||
CURSOR_HEIGHT = 33.9;
|
||||
|
||||
KEYBOARD_SCALE_MULTIPLIER = 0.50;
|
||||
|
||||
// VIEW_ANGLE can be adjusted to your likings, the smaller the faster movement.
|
||||
// Try setting it to 60 if it goes too fast for you.
|
||||
const VIEW_ANGLE = 40.0;
|
||||
const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2;
|
||||
|
||||
const SPAWN_DISTANCE = 1;
|
||||
const DEFAULT_TEXT_DIMENSION_Z = 0.02;
|
||||
|
||||
const BOUND_X = 0;
|
||||
const BOUND_Y = 1;
|
||||
const BOUND_W = 2;
|
||||
const BOUND_H = 3;
|
||||
|
||||
const KEY_STATE_LOWER = 0;
|
||||
const KEY_STATE_UPPER = 1;
|
||||
|
||||
const TEXT_MARGIN_TOP = 0.15;
|
||||
const TEXT_MARGIN_LEFT = 0.15;
|
||||
const TEXT_MARGIN_RIGHT = 0.17;
|
||||
const TEXT_MARGIN_BOTTOM = 0.17;
|
||||
KEY_STATE_LOWER = 0;
|
||||
KEY_STATE_UPPER = 1;
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var cursor = null;
|
||||
var keyboard = new Keyboard();
|
||||
var textFontSize = 9;
|
||||
var text = null;
|
||||
var textText = "";
|
||||
var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false});
|
||||
|
||||
function appendChar(char) {
|
||||
textText += char;
|
||||
updateTextOverlay();
|
||||
Overlays.editOverlay(text, {text: textText});
|
||||
}
|
||||
|
||||
function deleteChar() {
|
||||
if (textText.length > 0) {
|
||||
textText = textText.substring(0, textText.length - 1);
|
||||
updateTextOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function updateTextOverlay() {
|
||||
var textLines = textText.split("\n");
|
||||
var maxLineWidth = 0;
|
||||
for (textLine in textLines) {
|
||||
var lineWidth = Overlays.textSize(text, textLines[textLine]).width;
|
||||
if (lineWidth > maxLineWidth) {
|
||||
maxLineWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
var suggestedFontSize = (windowDimensions.x / maxLineWidth) * textFontSize * 0.90;
|
||||
var maxFontSize = 190 / textLines.length;
|
||||
textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize;
|
||||
var topMargin = (250 - (textFontSize * textLines.length)) / 4;
|
||||
Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin});
|
||||
var maxLineWidth = 0;
|
||||
for (textLine in textLines) {
|
||||
var lineWidth = Overlays.textSize(text, textLines[textLine]).width;
|
||||
if (lineWidth > maxLineWidth) {
|
||||
maxLineWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - maxLineWidth) / 2});
|
||||
}
|
||||
|
||||
keyboard.onKeyPress = function(event) {
|
||||
if (event.event == 'keypress') {
|
||||
appendChar(event.char);
|
||||
} else if (event.event == 'enter') {
|
||||
appendChar("\n");
|
||||
}
|
||||
};
|
||||
|
||||
keyboard.onKeyRelease = function(event) {
|
||||
print("Key release event test");
|
||||
// you can cancel a key by releasing its focusing before releasing it
|
||||
if (event.focus) {
|
||||
if (event.event == 'delete') {
|
||||
deleteChar();
|
||||
} else if (event.event == 'submit') {
|
||||
print(textText);
|
||||
|
||||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
var textLines = textText.split("\n");
|
||||
var maxLineWidth = 0;
|
||||
for (textLine in textLines) {
|
||||
var lineWidth = Overlays.textSize(textSizeMeasureOverlay, textLines[textLine]).width;
|
||||
if (lineWidth > maxLineWidth) {
|
||||
maxLineWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
var usernameLine = "--" + GlobalServices.myUsername;
|
||||
var usernameWidth = Overlays.textSize(textSizeMeasureOverlay, usernameLine).width;
|
||||
if (maxLineWidth < usernameWidth) {
|
||||
maxLineWidth = usernameWidth;
|
||||
} else {
|
||||
var spaceableWidth = maxLineWidth - usernameWidth;
|
||||
var spaceWidth = Overlays.textSize(textSizeMeasureOverlay, " ").width;
|
||||
var numberOfSpaces = Math.floor(spaceableWidth / spaceWidth);
|
||||
for (var i = 0; i < numberOfSpaces; i++) {
|
||||
usernameLine = " " + usernameLine;
|
||||
}
|
||||
}
|
||||
var dimension_x = maxLineWidth + TEXT_MARGIN_RIGHT + TEXT_MARGIN_LEFT;
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
type: "Text",
|
||||
rotation: MyAvatar.orientation,
|
||||
position: position,
|
||||
dimensions: { x: dimension_x, y: (textLines.length + 1) * 0.14 + TEXT_MARGIN_TOP + TEXT_MARGIN_BOTTOM, z: DEFAULT_TEXT_DIMENSION_Z },
|
||||
backgroundColor: { red: 0, green: 0, blue: 0 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: textText + "\n" + usernameLine
|
||||
});
|
||||
}
|
||||
textText = "";
|
||||
updateTextOverlay();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
keyboard.onFullyLoaded = function() {
|
||||
print("Virtual-keyboard fully loaded.");
|
||||
var dimensions = Controller.getViewportDimensions();
|
||||
text = Overlays.addOverlay("text", {
|
||||
x: 0,
|
||||
y: dimensions.y - keyboard.height() - 260,
|
||||
width: dimensions.x,
|
||||
height: 250,
|
||||
backgroundColor: { red: 255, green: 255, blue: 255},
|
||||
color: { red: 0, green: 0, blue: 0},
|
||||
topMargin: 5,
|
||||
leftMargin: 0,
|
||||
font: {size: textFontSize},
|
||||
text: "",
|
||||
alpha: 0.8
|
||||
});
|
||||
updateTextOverlay();
|
||||
// the cursor is being loaded after the keyboard, else it will be on the background of the keyboard
|
||||
cursor = new Cursor();
|
||||
cursor.onUpdate = function(position) {
|
||||
keyboard.setFocusPosition(position.x, position.y);
|
||||
};
|
||||
};
|
||||
|
||||
function KeyboardKey(keyboard, keyProperties) {
|
||||
KeyboardKey = (function(keyboard, keyProperties) {
|
||||
var tthis = this;
|
||||
this._focus = false;
|
||||
this._beingPressed = false;
|
||||
|
@ -247,6 +118,11 @@ function KeyboardKey(keyboard, keyProperties) {
|
|||
});
|
||||
}
|
||||
};
|
||||
this.updateVisibility = function() {
|
||||
for (var i = 0; i < tthis.bounds.length; i++) {
|
||||
Overlays.editOverlay(tthis.overlays[i], {visible: tthis.keyboard.visible});
|
||||
}
|
||||
};
|
||||
this.rescale = function() {
|
||||
for (var i = 0; i < tthis.bounds.length; i++) {
|
||||
Overlays.editOverlay(tthis.overlays[i], {
|
||||
|
@ -271,24 +147,48 @@ function KeyboardKey(keyboard, keyProperties) {
|
|||
return true;
|
||||
};
|
||||
for (var i = 0; i < this.bounds.length; i++) {
|
||||
var newOverlay = Overlays.cloneOverlay(this.keyboard.background);
|
||||
Overlays.editOverlay(newOverlay, {
|
||||
x: this.keyboard.getX() + this.bounds[i][BOUND_X] * keyboard.scale,
|
||||
y: this.keyboard.getY() + this.bounds[i][BOUND_Y] * keyboard.scale,
|
||||
width: this.bounds[i][BOUND_W] * keyboard.scale,
|
||||
height: this.bounds[i][BOUND_H] * keyboard.scale,
|
||||
subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]},
|
||||
alpha: 1
|
||||
});
|
||||
this.overlays.push(newOverlay);
|
||||
if (THREE_D_MODE) {
|
||||
this.overlays.push(Overlays.addOverlay("billboard", {
|
||||
scale: 1,
|
||||
rotation: MyAvatar.rotation,
|
||||
isFacingAvatar: false,
|
||||
url: KEYBOARD_URL,
|
||||
alpha: 1,
|
||||
position: {
|
||||
x: MyAvatar.position.x,// + this.bounds[i][BOUND_X] * 0.01,// /*+ this.keyboard.getX()*/ + this.bounds[i][BOUND_X] * keyboard.scale,
|
||||
y: MyAvatar.position.y,// - this.bounds[i][BOUND_Y] * 0.01,// /*+ this.keyboard.getY()*/ + this.bounds[i][BOUND_Y] * keyboard.scale,
|
||||
z: MyAvatar.position.z
|
||||
},
|
||||
width: this.bounds[i][BOUND_W] * keyboard.scale,
|
||||
height: this.bounds[i][BOUND_H] * keyboard.scale,
|
||||
subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]},
|
||||
alpha: 1,
|
||||
visible: tthis.keyboard.visible
|
||||
}));
|
||||
} else {
|
||||
this.overlays.push(Overlays.addOverlay("image", {
|
||||
imageURL: KEYBOARD_URL,
|
||||
x: this.keyboard.getX() + this.bounds[i][BOUND_X] * keyboard.scale,
|
||||
y: this.keyboard.getY() + this.bounds[i][BOUND_Y] * keyboard.scale,
|
||||
width: this.bounds[i][BOUND_W] * keyboard.scale,
|
||||
height: this.bounds[i][BOUND_H] * keyboard.scale,
|
||||
subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]},
|
||||
alpha: 1,
|
||||
visible: tthis.keyboard.visible
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function Keyboard() {
|
||||
Keyboard = (function(params) {
|
||||
if (params === undefined) {
|
||||
params = {};
|
||||
}
|
||||
var tthis = this;
|
||||
this.focussed_key = -1;
|
||||
this.scale = windowDimensions.x / KEYBOARD_WIDTH;
|
||||
this.scale = (windowDimensions.x / KEYBOARD_WIDTH) * KEYBOARD_SCALE_MULTIPLIER;
|
||||
this.shift = false;
|
||||
this.visible = params.visible != undefined ? params.visible : true;
|
||||
this.width = function() {
|
||||
return KEYBOARD_WIDTH * tthis.scale;
|
||||
};
|
||||
|
@ -301,17 +201,33 @@ function Keyboard() {
|
|||
this.getY = function() {
|
||||
return windowDimensions.y - this.height();
|
||||
};
|
||||
this.background = Overlays.addOverlay("image", {
|
||||
x: this.getX(),
|
||||
y: this.getY(),
|
||||
width: this.width(),
|
||||
height: this.height(),
|
||||
subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND},
|
||||
imageURL: KEYBOARD_URL,
|
||||
alpha: 1
|
||||
});
|
||||
if (THREE_D_MODE) {
|
||||
this.background = Overlays.addOverlay("billboard", {
|
||||
scale: 1,
|
||||
position: MyAvatar.position,
|
||||
rotation: MyAvatar.rotation,
|
||||
width: this.width(),
|
||||
height: this.height(),
|
||||
subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND},
|
||||
isFacingAvatar: false,
|
||||
url: KEYBOARD_URL,
|
||||
alpha: 1,
|
||||
visible: this.visible
|
||||
});
|
||||
} else {
|
||||
this.background = Overlays.addOverlay("image", {
|
||||
x: this.getX(),
|
||||
y: this.getY(),
|
||||
width: this.width(),
|
||||
height: this.height(),
|
||||
subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND},
|
||||
imageURL: KEYBOARD_URL,
|
||||
alpha: 1,
|
||||
visible: this.visible
|
||||
});
|
||||
}
|
||||
this.rescale = function() {
|
||||
this.scale = windowDimensions.x / KEYBOARD_WIDTH;
|
||||
this.scale = (windowDimensions.x / KEYBOARD_WIDTH) * KEYBOARD_SCALE_MULTIPLIER;
|
||||
Overlays.editOverlay(tthis.background, {
|
||||
x: this.getX(),
|
||||
y: this.getY(),
|
||||
|
@ -349,6 +265,9 @@ function Keyboard() {
|
|||
};
|
||||
|
||||
this.pressFocussedKey = function() {
|
||||
if (!tthis.visible) {
|
||||
return tthis;
|
||||
}
|
||||
if (tthis.focussed_key != -1) {
|
||||
if (tthis.keys[tthis.focussed_key].event == 'shift') {
|
||||
tthis.toggleShift();
|
||||
|
@ -402,6 +321,32 @@ function Keyboard() {
|
|||
for (var i = 0; i < this.keys.length; i++) {
|
||||
this.keys[i].remove();
|
||||
}
|
||||
// resets the cursor and magnifier
|
||||
this.updateVisibility(false);
|
||||
};
|
||||
|
||||
this.show = function() {
|
||||
tthis.updateVisibility(true);
|
||||
};
|
||||
|
||||
this.hide = function() {
|
||||
tthis.updateVisibility(false);
|
||||
};
|
||||
|
||||
this.toggle = function() {
|
||||
tthis.updateVisibility(!tthis.visible);
|
||||
};
|
||||
|
||||
this.updateVisibility = function(visible) {
|
||||
tthis.visible = visible;
|
||||
if (HMD.magnifier == visible) {
|
||||
HMD.toggleMagnifier();
|
||||
}
|
||||
Window.cursorVisible = !visible;
|
||||
Overlays.editOverlay(tthis.background, { visible: tthis.visible });
|
||||
for (var i = 0; i < this.keys.length; i++) {
|
||||
this.keys[i].updateVisibility();
|
||||
}
|
||||
};
|
||||
|
||||
this.onKeyPress = null;
|
||||
|
@ -502,97 +447,94 @@ function Keyboard() {
|
|||
|
||||
{bounds: [[899, 355, 263, 67]], event: 'submit'}
|
||||
];
|
||||
|
||||
for (var i = 0; i < keyProperties.length; i++) {
|
||||
this.keys.push(new KeyboardKey(this, keyProperties[i]));
|
||||
}
|
||||
this.keyboardTextureLoaded = function() {
|
||||
if (Overlays.isLoaded(tthis.background)) {
|
||||
Script.clearInterval(tthis.keyboardTextureLoaded_timer);
|
||||
for (var i = 0; i < keyProperties.length; i++) {
|
||||
tthis.keys.push(new KeyboardKey(tthis, keyProperties[i]));
|
||||
}
|
||||
if (keyboard.onFullyLoaded != null) {
|
||||
tthis.onFullyLoaded();
|
||||
}
|
||||
}
|
||||
};
|
||||
this.keyboardTextureLoaded_timer = Script.setInterval(this.keyboardTextureLoaded, 250);
|
||||
}
|
||||
});
|
||||
|
||||
function Cursor() {
|
||||
Cursor = (function(params) {
|
||||
if (params === undefined) {
|
||||
params = {};
|
||||
}
|
||||
var tthis = this;
|
||||
this.x = windowDimensions.x / 2;
|
||||
this.y = windowDimensions.y / 2;
|
||||
this.overlay = Overlays.addOverlay("image", {
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
width: CURSOR_WIDTH,
|
||||
height: CURSOR_HEIGHT,
|
||||
imageURL: CURSOR_URL,
|
||||
alpha: 1
|
||||
});
|
||||
this.remove = function() {
|
||||
Overlays.deleteOverlay(this.overlay);
|
||||
this.initialize = function() {
|
||||
this.visible = params.visible != undefined ? params.visible : true;
|
||||
this.x = windowDimensions.x / 2;
|
||||
this.y = windowDimensions.y / 2;
|
||||
this.overlay = Overlays.addOverlay("image", {
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
width: CURSOR_WIDTH,
|
||||
height: CURSOR_HEIGHT,
|
||||
imageURL: CURSOR_URL,
|
||||
alpha: 1,
|
||||
visible: this.visible
|
||||
});
|
||||
this.remove = function() {
|
||||
Overlays.deleteOverlay(this.overlay);
|
||||
};
|
||||
this.getPosition = function() {
|
||||
return {x: tthis.getX(), y: tthis.getY()};
|
||||
};
|
||||
this.getX = function() {
|
||||
return tthis.x;
|
||||
};
|
||||
this.getY = function() {
|
||||
return tthis.y;
|
||||
};
|
||||
this.show = function() {
|
||||
tthis.updateVisibility(true);
|
||||
};
|
||||
this.hide = function() {
|
||||
tthis.updateVisibility(false);
|
||||
};
|
||||
this.toggle = function() {
|
||||
tthis.updateVisibility(!tthis.visible);
|
||||
};
|
||||
this.updateVisibility = function(visible) {
|
||||
tthis.visible = visible;
|
||||
Overlays.editOverlay(this.overlay, { visible: tthis.visible });
|
||||
};
|
||||
this.onUpdate = null;
|
||||
this.update = function() {
|
||||
var newWindowDimensions = Controller.getViewportDimensions();
|
||||
if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) {
|
||||
windowDimensions = newWindowDimensions;
|
||||
keyboard.rescale();
|
||||
Overlays.editOverlay(text, {
|
||||
y: windowDimensions.y - keyboard.height() - 260,
|
||||
width: windowDimensions.x
|
||||
});
|
||||
}
|
||||
var editobject = {};
|
||||
var hudLookatPosition = HMD.getHUDLookAtPosition2D();
|
||||
if (hudLookatPosition === null) {
|
||||
return;
|
||||
}
|
||||
if (tthis.x !== hudLookatPosition.x) {
|
||||
tthis.x = hudLookatPosition.x;
|
||||
editobject.x = tthis.x - (CURSOR_WIDTH / 2);
|
||||
}
|
||||
if (tthis.y !== hudLookatPosition.y) {
|
||||
tthis.y = hudLookatPosition.y;
|
||||
editobject.y = tthis.y - (CURSOR_HEIGHT / 2);
|
||||
}
|
||||
if (Object.keys(editobject).length > 0) {
|
||||
Overlays.editOverlay(tthis.overlay, editobject);
|
||||
if (tthis.onUpdate != null) {
|
||||
tthis.onUpdate(tthis.getPosition());
|
||||
}
|
||||
}
|
||||
};
|
||||
Script.update.connect(this.update);
|
||||
};
|
||||
this.getPosition = function() {
|
||||
return {x: tthis.getX(), y: tthis.getY()};
|
||||
};
|
||||
this.getX = function() {
|
||||
return tthis.x;
|
||||
};
|
||||
this.getY = function() {
|
||||
return tthis.y;
|
||||
};
|
||||
this.onUpdate = null;
|
||||
this.update = function() {
|
||||
var newWindowDimensions = Controller.getViewportDimensions();
|
||||
if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) {
|
||||
windowDimensions = newWindowDimensions;
|
||||
keyboard.rescale();
|
||||
Overlays.editOverlay(text, {
|
||||
y: windowDimensions.y - keyboard.height() - 260,
|
||||
width: windowDimensions.x
|
||||
});
|
||||
}
|
||||
var editobject = {};
|
||||
if (MyAvatar.getHeadFinalYaw() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalYaw() >= -1 * VIEW_ANGLE_BY_TWO) {
|
||||
angle = ((-1 * MyAvatar.getHeadFinalYaw()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE;
|
||||
tthis.x = angle * windowDimensions.x;
|
||||
editobject.x = tthis.x - (CURSOR_WIDTH / 2);
|
||||
}
|
||||
if (MyAvatar.getHeadFinalPitch() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalPitch() >= -1 * VIEW_ANGLE_BY_TWO) {
|
||||
angle = ((-1 * MyAvatar.getHeadFinalPitch()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE;
|
||||
tthis.y = angle * windowDimensions.y;
|
||||
editobject.y = tthis.y - (CURSOR_HEIGHT / 2);
|
||||
}
|
||||
if (Object.keys(editobject).length > 0) {
|
||||
Overlays.editOverlay(tthis.overlay, editobject);
|
||||
if (tthis.onUpdate != null) {
|
||||
tthis.onUpdate(tthis.getPosition());
|
||||
}
|
||||
}
|
||||
};
|
||||
Script.update.connect(this.update);
|
||||
}
|
||||
|
||||
function keyPressEvent(event) {
|
||||
if (event.key === SPACEBAR_CHARCODE) {
|
||||
keyboard.pressFocussedKey();
|
||||
}
|
||||
}
|
||||
|
||||
function keyReleaseEvent(event) {
|
||||
if (event.key === SPACEBAR_CHARCODE) {
|
||||
keyboard.releaseKeys();
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
keyboard.remove();
|
||||
cursor.remove();
|
||||
Overlays.deleteOverlay(text);
|
||||
Overlays.deleteOverlay(textSizeMeasureOverlay);
|
||||
Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE});
|
||||
}
|
||||
Controller.captureKeyEvents({key: SPACEBAR_CHARCODE});
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
});
|
|
@ -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>
|
||||
|
@ -110,6 +111,7 @@
|
|||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||
#include "scripting/ClipboardScriptingInterface.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/JoystickScriptingInterface.h"
|
||||
#include "scripting/GlobalServicesScriptingInterface.h"
|
||||
#include "scripting/LocationScriptingInterface.h"
|
||||
|
@ -211,6 +213,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>();
|
||||
|
@ -328,7 +332,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>();
|
||||
|
@ -338,7 +342,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();
|
||||
|
||||
|
@ -516,53 +522,65 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
void Application::aboutToQuit() {
|
||||
_aboutToQuit = true;
|
||||
|
||||
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();
|
||||
|
||||
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() {
|
||||
|
@ -2599,6 +2617,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)
|
||||
|
@ -2613,6 +2634,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) {
|
||||
|
@ -2819,7 +2841,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();
|
||||
|
@ -3457,7 +3479,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);
|
||||
|
||||
|
@ -3471,6 +3493,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
|
||||
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
|
||||
|
||||
QScriptValue hmdInterface = scriptEngine->registerGlobalObject("HMD", &HMDScriptingInterface::getInstance());
|
||||
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition2D", HMDScriptingInterface::getHUDLookAtPosition2D, 0);
|
||||
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
||||
|
||||
#ifdef HAVE_RTMIDI
|
||||
scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance());
|
||||
#endif
|
||||
|
|
|
@ -410,6 +410,8 @@ private:
|
|||
|
||||
void initDisplay();
|
||||
void init();
|
||||
|
||||
void cleanupBeforeQuit();
|
||||
|
||||
void update(float deltaTime);
|
||||
|
||||
|
|
|
@ -129,12 +129,12 @@ void DatagramProcessor::processDatagrams() {
|
|||
|
||||
if (incomingType == PacketTypeMuteEnvironment) {
|
||||
glm::vec3 position;
|
||||
float radius, distance;
|
||||
float radius;
|
||||
|
||||
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment);
|
||||
memcpy(&position, incomingPacket.constData() + headerSize, sizeof(glm::vec3));
|
||||
memcpy(&radius, incomingPacket.constData() + headerSize + sizeof(glm::vec3), sizeof(float));
|
||||
distance = glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(),
|
||||
float distance = glm::distance(DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition(),
|
||||
position);
|
||||
|
||||
mute = mute && (distance < radius);
|
||||
|
|
|
@ -688,7 +688,7 @@ void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
|
|||
roll = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 OculusManager::getRelativePosition() {
|
||||
#if (defined(__APPLE__) || defined(_WIN32)) && HAVE_LIBOVR
|
||||
ovrTrackingState trackingState = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
|
||||
|
|
56
interface/src/scripting/HMDScriptingInterface.cpp
Normal file
56
interface/src/scripting/HMDScriptingInterface.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// HMDScriptingInterface.cpp
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Thijs Wenker on 1/12/15.
|
||||
// Copyright 2015 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 "HMDScriptingInterface.h"
|
||||
|
||||
#include <avatar/AvatarManager.h>
|
||||
|
||||
HMDScriptingInterface& HMDScriptingInterface::getInstance() {
|
||||
static HMDScriptingInterface sharedInstance;
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const {
|
||||
Camera* camera = Application::getInstance()->getCamera();
|
||||
glm::vec3 position = camera->getPosition();
|
||||
glm::quat orientation = camera->getOrientation();
|
||||
|
||||
glm::vec3 direction = orientation * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
|
||||
|
||||
return applicationOverlay.calculateRayUICollisionPoint(position, direction, result);
|
||||
}
|
||||
|
||||
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
|
||||
|
||||
glm::vec3 hudIntersection;
|
||||
|
||||
if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(hudIntersection)) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
glm::vec3 sphereCenter = myAvatar->getDefaultEyePosition();
|
||||
glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * (hudIntersection - sphereCenter);
|
||||
glm::quat rotation = ::rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), direction);
|
||||
glm::vec3 eulers = ::safeEulerAngles(rotation);
|
||||
return qScriptValueFromValue<glm::vec2>(engine, Application::getInstance()->getApplicationOverlay()
|
||||
.sphericalToOverlay(glm::vec2(eulers.y, -eulers.x)));
|
||||
}
|
||||
return QScriptValue::NullValue;
|
||||
}
|
||||
|
||||
QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) {
|
||||
glm::vec3 result;
|
||||
HMDScriptingInterface* hmdInterface = &HMDScriptingInterface::getInstance();
|
||||
if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) {
|
||||
return qScriptValueFromValue<glm::vec3>(engine, result);
|
||||
}
|
||||
return QScriptValue::NullValue;
|
||||
}
|
42
interface/src/scripting/HMDScriptingInterface.h
Normal file
42
interface/src/scripting/HMDScriptingInterface.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// HMDScriptingInterface.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Thijs Wenker on 1/12/15.
|
||||
// Copyright 2015 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_HMDScriptingInterface_h
|
||||
#define hifi_HMDScriptingInterface_h
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "devices/OculusManager.h"
|
||||
|
||||
class HMDScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool magnifier READ getMagnifier)
|
||||
Q_PROPERTY(bool active READ isHMDMode)
|
||||
public:
|
||||
static HMDScriptingInterface& getInstance();
|
||||
|
||||
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
|
||||
static QScriptValue getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine);
|
||||
|
||||
public slots:
|
||||
void toggleMagnifier() { Application::getInstance()->getApplicationOverlay().toggleMagnifier(); };
|
||||
|
||||
private:
|
||||
HMDScriptingInterface() {};
|
||||
bool getMagnifier() const { return Application::getInstance()->getApplicationOverlay().hasMagnifier(); };
|
||||
bool isHMDMode() const { return Application::getInstance()->isHMDMode(); }
|
||||
|
||||
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_HMDScriptingInterface_h
|
|
@ -139,6 +139,7 @@ ApplicationOverlay::ApplicationOverlay() :
|
|||
_alpha(1.0f),
|
||||
_oculusUIRadius(1.0f),
|
||||
_crosshairTexture(0),
|
||||
_magnifier(true),
|
||||
_previousBorderWidth(-1),
|
||||
_previousBorderHeight(-1),
|
||||
_previousMagnifierBottomLeft(),
|
||||
|
@ -559,7 +560,7 @@ void ApplicationOverlay::renderPointers() {
|
|||
|
||||
_reticlePosition[MOUSE] = position;
|
||||
_reticleActive[MOUSE] = true;
|
||||
_magActive[MOUSE] = true;
|
||||
_magActive[MOUSE] = _magnifier;
|
||||
_reticleActive[LEFT_CONTROLLER] = false;
|
||||
_reticleActive[RIGHT_CONTROLLER] = false;
|
||||
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) {
|
||||
|
@ -718,6 +719,9 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
|
|||
|
||||
//Renders a small magnification of the currently bound texture at the coordinates
|
||||
void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
|
||||
if (!_magnifier) {
|
||||
return;
|
||||
}
|
||||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
|
||||
const int widgetWidth = glCanvas->width();
|
||||
|
@ -788,13 +792,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();
|
||||
|
@ -846,8 +849,8 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
audioMeterY += AUDIO_METER_HEIGHT;
|
||||
|
||||
// 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));
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X, audioMeterY, AUDIO_METER_WIDTH, AUDIO_METER_HEIGHT,
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
if (audioLevel > AUDIO_RED_START) {
|
||||
glm::vec4 quadColor;
|
||||
|
@ -857,10 +860,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 +877,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() {
|
||||
|
|
|
@ -37,6 +37,9 @@ public:
|
|||
QPoint getPalmClickLocation(const PalmData *palm) const;
|
||||
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
|
||||
|
||||
bool hasMagnifier() const { return _magnifier; }
|
||||
void toggleMagnifier() { _magnifier = !_magnifier; }
|
||||
|
||||
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
|
||||
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; }
|
||||
|
||||
|
@ -109,7 +112,8 @@ private:
|
|||
bool _magActive[NUMBER_OF_RETICLES];
|
||||
float _magSizeMult[NUMBER_OF_RETICLES];
|
||||
quint64 _lastMouseMove;
|
||||
|
||||
bool _magnifier;
|
||||
|
||||
float _alpha;
|
||||
float _oculusUIRadius;
|
||||
float _trailingAudioLoudness;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ LoginDialog::LoginDialog(QWidget* parent) :
|
|||
this, &LoginDialog::handleLoginClicked);
|
||||
connect(_ui->closeButton, &QPushButton::clicked,
|
||||
this, &LoginDialog::close);
|
||||
|
||||
// Initialize toggle connection
|
||||
toggleQAction();
|
||||
};
|
||||
|
||||
LoginDialog::~LoginDialog() {
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
#include "Line3DOverlay.h"
|
||||
|
||||
|
||||
Line3DOverlay::Line3DOverlay() {
|
||||
Line3DOverlay::Line3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
}
|
||||
|
||||
Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) :
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() {
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) :
|
||||
|
|
|
@ -141,6 +141,8 @@ AudioClient::AudioClient() :
|
|||
}
|
||||
|
||||
AudioClient::~AudioClient() {
|
||||
stop();
|
||||
|
||||
if (_gverbLocal) {
|
||||
gverb_free(_gverbLocal);
|
||||
}
|
||||
|
@ -494,7 +496,6 @@ void AudioClient::start() {
|
|||
}
|
||||
|
||||
void AudioClient::stop() {
|
||||
|
||||
_inputFrameBuffer.finalize();
|
||||
_inputGain.finalize();
|
||||
_sourceGain.finalize();
|
||||
|
@ -892,13 +893,14 @@ void AudioClient::processReceivedSamples(const QByteArray& inputBuffer, QByteArr
|
|||
|
||||
void AudioClient::sendMuteEnvironmentPacket() {
|
||||
QByteArray mutePacket = byteArrayWithPopulatedHeader(PacketTypeMuteEnvironment);
|
||||
QDataStream mutePacketStream(&mutePacket, QIODevice::Append);
|
||||
int headerSize = mutePacket.size();
|
||||
|
||||
const float MUTE_RADIUS = 50;
|
||||
|
||||
glm::vec3 currentSourcePosition = _positionGetter();
|
||||
mutePacketStream.writeBytes(reinterpret_cast<const char *>(¤tSourcePosition), sizeof(glm::vec3));
|
||||
mutePacketStream.writeBytes(reinterpret_cast<const char *>(&MUTE_RADIUS), sizeof(float));
|
||||
mutePacket.resize(mutePacket.size() + sizeof(glm::vec3) + sizeof(float));
|
||||
memcpy(mutePacket.data() + headerSize, ¤tSourcePosition, sizeof(glm::vec3));
|
||||
memcpy(mutePacket.data() + headerSize + sizeof(glm::vec3), &MUTE_RADIUS, sizeof(float));
|
||||
|
||||
// grab our audio mixer from the NodeList, if it exists
|
||||
auto nodelist = DependencyManager::get<NodeList>();
|
||||
|
|
|
@ -186,6 +186,10 @@ protected:
|
|||
AudioClient();
|
||||
~AudioClient();
|
||||
|
||||
virtual void customDeleter() {
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
private:
|
||||
void outputFormatChanged();
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -194,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; }
|
||||
|
@ -256,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;
|
||||
}
|
||||
|
|
|
@ -321,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
|
||||
|
|
|
@ -163,16 +163,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
|
||||
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();
|
||||
|
|
|
@ -1127,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;
|
||||
|
@ -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>());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -39,6 +39,7 @@ const char SOLO_NODE_TYPES[2] = {
|
|||
const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://metaverse.highfidelity.io");
|
||||
|
||||
LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) :
|
||||
linkedDataCreateCallback(NULL),
|
||||
_sessionUUID(),
|
||||
_nodeHash(),
|
||||
_nodeMutex(QReadWriteLock::Recursive),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -49,14 +49,32 @@ void OctreePersistThread::parseSettings(const QJsonObject& settings) {
|
|||
qDebug() << "BACKUP RULES:";
|
||||
|
||||
foreach (const QJsonValue& value, backupRules) {
|
||||
|
||||
QJsonObject obj = value.toObject();
|
||||
|
||||
int interval = 0;
|
||||
int count = 0;
|
||||
|
||||
QJsonValue intervalVal = obj["backupInterval"];
|
||||
if (intervalVal.isString()) {
|
||||
interval = intervalVal.toString().toInt();
|
||||
} else {
|
||||
interval = intervalVal.toInt();
|
||||
}
|
||||
|
||||
QJsonValue countVal = obj["maxBackupVersions"];
|
||||
if (countVal.isString()) {
|
||||
count = countVal.toString().toInt();
|
||||
} else {
|
||||
count = countVal.toInt();
|
||||
}
|
||||
|
||||
qDebug() << " Name:" << obj["Name"].toString();
|
||||
qDebug() << " format:" << obj["format"].toString();
|
||||
qDebug() << " interval:" << obj["backupInterval"].toInt();
|
||||
qDebug() << " count:" << obj["maxBackupVersions"].toInt();
|
||||
qDebug() << " interval:" << interval;
|
||||
qDebug() << " count:" << count;
|
||||
|
||||
BackupRule newRule = { obj["Name"].toString(), obj["backupInterval"].toInt(),
|
||||
obj["format"].toString(), obj["maxBackupVersions"].toInt(), 0};
|
||||
BackupRule newRule = { obj["Name"].toString(), interval, obj["format"].toString(), count, 0};
|
||||
|
||||
newRule.lastBackup = getMostRecentBackupTimeInUsecs(obj["format"].toString());
|
||||
|
||||
|
@ -213,7 +231,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.
|
||||
|
@ -319,34 +339,41 @@ bool OctreePersistThread::getMostRecentBackup(const QString& format,
|
|||
void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) {
|
||||
|
||||
if (rule.extensionFormat.contains("%N")) {
|
||||
qDebug() << "Rolling old backup versions for rule" << rule.name << "...";
|
||||
for(int n = rule.maxBackupVersions - 1; n > 0; n--) {
|
||||
QString backupExtensionN = rule.extensionFormat;
|
||||
QString backupExtensionNplusOne = rule.extensionFormat;
|
||||
backupExtensionN.replace(QString("%N"), QString::number(n));
|
||||
backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1));
|
||||
if (rule.maxBackupVersions > 0) {
|
||||
qDebug() << "Rolling old backup versions for rule" << rule.name << "...";
|
||||
for(int n = rule.maxBackupVersions - 1; n > 0; n--) {
|
||||
QString backupExtensionN = rule.extensionFormat;
|
||||
QString backupExtensionNplusOne = rule.extensionFormat;
|
||||
backupExtensionN.replace(QString("%N"), QString::number(n));
|
||||
backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1));
|
||||
|
||||
QString backupFilenameN = _filename + backupExtensionN;
|
||||
QString backupFilenameNplusOne = _filename + backupExtensionNplusOne;
|
||||
QString backupFilenameN = _filename + backupExtensionN;
|
||||
QString backupFilenameNplusOne = _filename + backupExtensionNplusOne;
|
||||
|
||||
QFile backupFileN(backupFilenameN);
|
||||
QFile backupFileN(backupFilenameN);
|
||||
|
||||
if (backupFileN.exists()) {
|
||||
qDebug() << "rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "...";
|
||||
int result = rename(qPrintable(backupFilenameN), qPrintable(backupFilenameNplusOne));
|
||||
if (result == 0) {
|
||||
qDebug() << "DONE rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "...";
|
||||
} else {
|
||||
qDebug() << "ERROR in rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "...";
|
||||
if (backupFileN.exists()) {
|
||||
qDebug() << "rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "...";
|
||||
int result = rename(qPrintable(backupFilenameN), qPrintable(backupFilenameNplusOne));
|
||||
if (result == 0) {
|
||||
qDebug() << "DONE rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "...";
|
||||
} else {
|
||||
qDebug() << "ERROR in rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << "Done rolling old backup versions...";
|
||||
} else {
|
||||
qDebug() << "Rolling backups for rule" << rule.name << "."
|
||||
<< " Max Rolled Backup Versions less than 1 [" << rule.maxBackupVersions << "]."
|
||||
<< " No need to roll backups...";
|
||||
}
|
||||
qDebug() << "Done rolling old backup versions...";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreePersistThread::backup() {
|
||||
qDebug() << "backup operation wantBackup:" << _wantBackup;
|
||||
if (_wantBackup) {
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
|
@ -354,10 +381,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 +408,28 @@ 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...";
|
||||
if (rule.maxBackupVersions > 0) {
|
||||
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() << "persist file " << _filename << " does not exist. " <<
|
||||
"nothing to backup for this rule ["<< rule.name << "]...";
|
||||
}
|
||||
} else {
|
||||
qDebug() << "ERROR in backing up persist file...";
|
||||
qDebug() << "This backup rule" << rule.name
|
||||
<< " has Max Rolled Backup Versions less than 1 [" << rule.maxBackupVersions << "]."
|
||||
<< " There are no backups to be done...";
|
||||
}
|
||||
|
||||
rule.lastBackup = now;
|
||||
} else {
|
||||
qDebug() << "Backup not needed for this rule ["<< rule.name << "]...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
117
libraries/render-utils/src/DeferredGlobalLight.slh
Executable file
117
libraries/render-utils/src/DeferredGlobalLight.slh
Executable file
|
@ -0,0 +1,117 @@
|
|||
<!
|
||||
// DeferredGlobalLight.slh
|
||||
// libraries/render-utils/src
|
||||
//
|
||||
// Created by Sam Gateau on 2/5/15.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
!>
|
||||
<@if not DEFERRED_GLOBAL_LIGHT_SLH@>
|
||||
<@def DEFERRED_GLOBAL_LIGHT_SLH@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
|
||||
struct SphericalHarmonics {
|
||||
vec4 L00;
|
||||
vec4 L1m1;
|
||||
vec4 L10;
|
||||
vec4 L11;
|
||||
vec4 L2m2;
|
||||
vec4 L2m1;
|
||||
vec4 L20;
|
||||
vec4 L21;
|
||||
vec4 L22;
|
||||
};
|
||||
|
||||
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
|
||||
|
||||
const float C1 = 0.429043;
|
||||
const float C2 = 0.511664;
|
||||
const float C3 = 0.743125;
|
||||
const float C4 = 0.886227;
|
||||
const float C5 = 0.247708;
|
||||
|
||||
vec4 value = C1 * sh.L22 * (direction.x * direction.x - direction.y * direction.y) +
|
||||
C3 * sh.L20 * direction.z * direction.z +
|
||||
C4 * sh.L00 - C5 * sh.L20 +
|
||||
2.0 * C1 * ( sh.L2m2 * direction.x * direction.y +
|
||||
sh.L21 * direction.x * direction.z +
|
||||
sh.L2m1 * direction.y * direction.z ) +
|
||||
2.0 * C2 * ( sh.L11 * direction.x +
|
||||
sh.L1m1 * direction.y +
|
||||
sh.L10 * direction.z ) ;
|
||||
return value;
|
||||
}
|
||||
|
||||
// Need one SH
|
||||
uniform SphericalHarmonics ambientSphere;
|
||||
|
||||
// Everything about light
|
||||
<@include Light.slh@>
|
||||
|
||||
// The view Matrix
|
||||
uniform mat4 invViewMat;
|
||||
|
||||
vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||
|
||||
// Need the light now
|
||||
Light light = getLight();
|
||||
|
||||
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
|
||||
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
vec3 color = diffuse.rgb * getLightColor(light) * 0.5;
|
||||
|
||||
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||
|
||||
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||
|
||||
return color;
|
||||
}
|
||||
vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||
// Need the light now
|
||||
Light light = getLight();
|
||||
|
||||
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
|
||||
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
|
||||
// TODO: The world space normal doesn;t seem to work properly with the current SH definitions
|
||||
// FoOr now, we use the normal in view space
|
||||
vec3 ambientNormal = normal;
|
||||
|
||||
vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz;
|
||||
|
||||
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
|
||||
|
||||
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) {
|
||||
|
||||
Light light = getLight();
|
||||
float diffuseDot = dot(normal, getLightDirection(light));
|
||||
|
||||
// need to catch normals perpendicular to the projection plane hence the magic number for the threshold
|
||||
// it should be just 0, but we have innacurracy so we need to overshoot
|
||||
const float PERPENDICULAR_THRESHOLD = -0.005;
|
||||
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
|
||||
|
||||
// evaluate the shadow test but only relevant for light facing fragments
|
||||
float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation;
|
||||
|
||||
// diffuse light is the lightmap dimmed by shadow
|
||||
vec3 diffuseLight = lightAttenuation * lightmap;
|
||||
|
||||
// ambient is a tiny percentage of the lightmap and only when in the shadow
|
||||
vec3 ambientLight = (1 - lightAttenuation) * 0.5 * lightmap;
|
||||
|
||||
return diffuse * (ambientLight + diffuseLight);
|
||||
}
|
||||
|
||||
<@endif@>
|
|
@ -11,86 +11,51 @@
|
|||
<@if not DEFERRED_LIGHTING_SLH@>
|
||||
<@def DEFERRED_LIGHTING_SLH@>
|
||||
|
||||
struct SphericalHarmonics {
|
||||
vec4 L00;
|
||||
vec4 L1m1;
|
||||
vec4 L10;
|
||||
vec4 L11;
|
||||
vec4 L2m2;
|
||||
vec4 L2m1;
|
||||
vec4 L20;
|
||||
vec4 L21;
|
||||
vec4 L22;
|
||||
};
|
||||
|
||||
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
|
||||
|
||||
const float C1 = 0.429043;
|
||||
const float C2 = 0.511664;
|
||||
const float C3 = 0.743125;
|
||||
const float C4 = 0.886227;
|
||||
const float C5 = 0.247708;
|
||||
|
||||
vec4 value = C1 * sh.L22 * (direction.x * direction.x - direction.y * direction.y) +
|
||||
C3 * sh.L20 * direction.z * direction.z +
|
||||
C4 * sh.L00 - C5 * sh.L20 +
|
||||
2.0 * C1 * ( sh.L2m2 * direction.x * direction.y +
|
||||
sh.L21 * direction.x * direction.z +
|
||||
sh.L2m1 * direction.y * direction.z ) +
|
||||
2.0 * C2 * ( sh.L11 * direction.x +
|
||||
sh.L1m1 * direction.y +
|
||||
sh.L10 * direction.z ) ;
|
||||
return value;
|
||||
}
|
||||
|
||||
uniform SphericalHarmonics ambientSphere;
|
||||
|
||||
vec3 evalAmbientColor(vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||
return diffuse.rgb * gl_FrontLightProduct[0].ambient.rgb;
|
||||
}
|
||||
|
||||
vec3 evalAmbientSphereColor(vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||
vec3 ambientLight = 0.5 * evalSphericalLight(ambientSphere, normal).xyz;
|
||||
|
||||
return diffuse.rgb * ambientLight;
|
||||
}
|
||||
|
||||
vec3 evalDirectionalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
|
||||
// Frag Shading returns the diffuse amount as W and the specular rgb as xyz
|
||||
vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
|
||||
// Diffuse Lighting
|
||||
float diffuseDot = dot(normal, gl_LightSource[0].position.xyz);
|
||||
float facingLight = step(0.0, diffuseDot) * shadowAttenuation;
|
||||
vec3 diffuseColor = diffuse * (gl_FrontLightProduct[0].diffuse.rgb * (diffuseDot * facingLight));
|
||||
|
||||
// compute the specular multiplier (sans exponent)
|
||||
float specularPower = facingLight * max(0.0,
|
||||
dot(normalize(gl_LightSource[0].position.xyz - normalize(position)), normal));
|
||||
vec3 specularColor = pow(specularPower, gloss * 128.0) * specular;
|
||||
float diffuseDot = dot(fragNormal, fragLightDir);
|
||||
float facingLight = step(0.0, diffuseDot);
|
||||
float diffuse = diffuseDot * facingLight;
|
||||
|
||||
// Specular Lighting depends on the half vector and the gloss
|
||||
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
|
||||
|
||||
// add specular contribution
|
||||
return vec3(diffuseColor + specularColor);
|
||||
// float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
|
||||
float specularPower = pow(max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
|
||||
specularPower *= (gloss * 128.0 * 0.125 + 0.25);
|
||||
|
||||
float shlickPower = (1.0 - dot(fragLightDir,halfDir));
|
||||
float shlickPower2 = shlickPower * shlickPower;
|
||||
float shlickPower5 = shlickPower2 * shlickPower2 * shlickPower;
|
||||
vec3 schlick = specular * (1.0 - shlickPower5) + vec3(shlickPower5);
|
||||
vec3 reflect = specularPower * schlick;
|
||||
|
||||
return vec4(reflect, diffuse);
|
||||
}
|
||||
|
||||
vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
|
||||
// Diffuse Lighting
|
||||
float diffuseDot = dot(fragNormal, fragLightDir);
|
||||
float facingLight = step(0.0, diffuseDot);
|
||||
float diffuse = diffuseDot * facingLight;
|
||||
|
||||
// Specular Lighting depends on the half vector and the gloss
|
||||
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
|
||||
|
||||
vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) {
|
||||
|
||||
float diffuseDot = dot(normal, gl_LightSource[0].position.xyz);
|
||||
|
||||
// need to catch normals perpendicular to the projection plane hence the magic number for the threshold
|
||||
// it should be just 0, but we have innacurracy so we need to overshoot
|
||||
const float PERPENDICULAR_THRESHOLD = -0.005;
|
||||
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
|
||||
|
||||
// evaluate the shadow test but only relevant for light facing fragments
|
||||
float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation;
|
||||
|
||||
// diffuse light is the lightmap dimmed by shadow
|
||||
vec3 diffuseLight = lightAttenuation * lightmap;
|
||||
float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
|
||||
vec3 reflect = specularPower * specular;
|
||||
|
||||
// ambient is a tiny percentage of the lightmap and only when in the shadow
|
||||
vec3 ambientLight = (1 - lightAttenuation) * 0.5 * lightmap;
|
||||
|
||||
return diffuse * (ambientLight + diffuseLight);
|
||||
return vec4(reflect, diffuse);
|
||||
}
|
||||
|
||||
vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
|
||||
|
||||
/*if (gl_FragCoord.x > 1000) {
|
||||
return evalBlinnShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss);
|
||||
} else {*/
|
||||
return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss);
|
||||
//}
|
||||
}
|
||||
|
||||
<@endif@>
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include "RenderUtil.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
#include "gpu/Batch.h"
|
||||
#include "gpu/GLBackend.h"
|
||||
|
||||
#include "simple_vert.h"
|
||||
#include "simple_frag.h"
|
||||
|
||||
|
@ -42,146 +45,6 @@
|
|||
#include "point_light_frag.h"
|
||||
#include "spot_light_frag.h"
|
||||
|
||||
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;
|
||||
|
||||
void assignPreset(int p) {
|
||||
switch (p) {
|
||||
case DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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 DeferredLightingEffect::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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
||||
_viewState = viewState;
|
||||
_simpleProgram.addShaderFromSourceCode(QGLShader::Vertex, simple_vert);
|
||||
|
@ -206,6 +69,18 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
|||
|
||||
loadLightProgram(point_light_frag, true, _pointLight, _pointLightLocations);
|
||||
loadLightProgram(spot_light_frag, true, _spotLight, _spotLightLocations);
|
||||
|
||||
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
|
||||
_globalLights.push_back(0);
|
||||
_allocatedLights.push_back(model::LightPointer(new model::Light()));
|
||||
|
||||
model::LightPointer lp = _allocatedLights[0];
|
||||
|
||||
lp->setDirection(-glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
lp->setColor(glm::vec3(1.0f));
|
||||
lp->setIntensity(1.0f);
|
||||
lp->setType(model::Light::SUN);
|
||||
lp->setAmbientSpherePreset(model::SphericalHarmonics::Preset(_ambientLightMode % model::SphericalHarmonics::NUM_PRESET));
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::bindSimpleProgram() {
|
||||
|
@ -260,30 +135,29 @@ void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radi
|
|||
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
|
||||
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, float linearAttenuation,
|
||||
float quadraticAttenuation, const glm::vec3& direction, float exponent, float cutoff) {
|
||||
|
||||
int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
|
||||
if (lightID >= _allocatedLights.size()) {
|
||||
_allocatedLights.push_back(model::LightPointer(new model::Light()));
|
||||
}
|
||||
model::LightPointer lp = _allocatedLights[lightID];
|
||||
|
||||
lp->setPosition(position);
|
||||
lp->setMaximumRadius(radius);
|
||||
lp->setColor(diffuse);
|
||||
lp->setIntensity(1.0f);
|
||||
//lp->setShowContour(quadraticAttenuation);
|
||||
|
||||
if (exponent == 0.0f && cutoff == PI) {
|
||||
PointLight light;
|
||||
light.position = glm::vec4(position, 1.0f);
|
||||
light.radius = radius;
|
||||
light.ambient = glm::vec4(ambient, 1.0f);
|
||||
light.diffuse = glm::vec4(diffuse, 1.0f);
|
||||
light.specular = glm::vec4(specular, 1.0f);
|
||||
light.constantAttenuation = constantAttenuation;
|
||||
light.linearAttenuation = linearAttenuation;
|
||||
_pointLights.append(light);
|
||||
lp->setType(model::Light::POINT);
|
||||
_pointLights.push_back(lightID);
|
||||
|
||||
} else {
|
||||
SpotLight light;
|
||||
light.position = glm::vec4(position, 1.0f);
|
||||
light.radius = radius;
|
||||
light.ambient = glm::vec4(ambient, 1.0f);
|
||||
light.diffuse = glm::vec4(diffuse, 1.0f);
|
||||
light.specular = glm::vec4(specular, 1.0f);
|
||||
light.constantAttenuation = constantAttenuation;
|
||||
light.linearAttenuation = linearAttenuation;
|
||||
light.direction = direction;
|
||||
light.exponent = exponent;
|
||||
light.cutoff = cutoff;
|
||||
_spotLights.append(light);
|
||||
lp->setDirection(direction);
|
||||
lp->setSpotAngle(cutoff);
|
||||
lp->setSpotExponent(exponent);
|
||||
lp->setType(model::Light::SPOT);
|
||||
_spotLights.push_back(lightID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +191,7 @@ void DeferredLightingEffect::render() {
|
|||
QOpenGLFramebufferObject* freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebufferObject();
|
||||
freeFBO->bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
// glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
|
||||
|
||||
|
@ -342,6 +216,10 @@ void DeferredLightingEffect::render() {
|
|||
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height();
|
||||
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height();
|
||||
|
||||
// Fetch the ViewMatrix;
|
||||
glm::mat4 invViewMat;
|
||||
_viewState->getViewTransform().getMatrix(invViewMat);
|
||||
|
||||
ProgramObject* program = &_directionalLight;
|
||||
const LightLocations* locations = &_directionalLightLocations;
|
||||
bool shadowsEnabled = _viewState->getShadowsEnabled();
|
||||
|
@ -379,19 +257,24 @@ void DeferredLightingEffect::render() {
|
|||
program->bind();
|
||||
}
|
||||
|
||||
if (locations->ambientSphere >= 0) {
|
||||
SphericalHarmonics sh;
|
||||
if (_ambientLightMode < NUM_PRESET) {
|
||||
sh.assignPreset(_ambientLightMode);
|
||||
} else {
|
||||
sh.assignPreset(0);
|
||||
}
|
||||
|
||||
for (int i =0; i <SphericalHarmonics::NUM_COEFFICIENTS; i++) {
|
||||
program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i));
|
||||
}
|
||||
}
|
||||
{
|
||||
auto globalLight = _allocatedLights[_globalLights.front()];
|
||||
|
||||
if (locations->ambientSphere >= 0) {
|
||||
auto sh = globalLight->getAmbientSphere();
|
||||
for (int i =0; i <model::SphericalHarmonics::NUM_COEFFICIENTS; i++) {
|
||||
program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i));
|
||||
}
|
||||
}
|
||||
|
||||
if (locations->lightBufferUnit >= 0) {
|
||||
gpu::Batch batch;
|
||||
batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer());
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat));
|
||||
}
|
||||
|
||||
float left, right, bottom, top, nearVal, farVal;
|
||||
glm::vec4 nearClipPlane, farClipPlane;
|
||||
_viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
|
@ -434,27 +317,27 @@ void DeferredLightingEffect::render() {
|
|||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
if (!_pointLights.isEmpty()) {
|
||||
if (!_pointLights.empty()) {
|
||||
_pointLight.bind();
|
||||
_pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal);
|
||||
_pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale);
|
||||
_pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
|
||||
_pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
|
||||
|
||||
foreach (const PointLight& light, _pointLights) {
|
||||
_pointLight.setUniformValue(_pointLightLocations.radius, light.radius);
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f));
|
||||
|
||||
for (auto lightID : _pointLights) {
|
||||
auto light = _allocatedLights[lightID];
|
||||
|
||||
if (_pointLightLocations.lightBufferUnit >= 0) {
|
||||
gpu::Batch batch;
|
||||
batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer());
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat));
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION);
|
||||
if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius + nearRadius) {
|
||||
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
|
||||
if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) {
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0f, 0.0f, -1.0f);
|
||||
|
||||
|
@ -468,7 +351,7 @@ void DeferredLightingEffect::render() {
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
} else {
|
||||
glTranslatef(light.position.x, light.position.y, light.position.z);
|
||||
glTranslatef(light->getPosition().x, light->getPosition().y, light->getPosition().z);
|
||||
geometryCache->renderSphere(expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
|
@ -479,31 +362,28 @@ void DeferredLightingEffect::render() {
|
|||
_pointLight.release();
|
||||
}
|
||||
|
||||
if (!_spotLights.isEmpty()) {
|
||||
if (!_spotLights.empty()) {
|
||||
_spotLight.bind();
|
||||
_spotLight.setUniformValue(_spotLightLocations.nearLocation, nearVal);
|
||||
_spotLight.setUniformValue(_spotLightLocations.depthScale, depthScale);
|
||||
_spotLight.setUniformValue(_spotLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
|
||||
_spotLight.setUniformValue(_spotLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
|
||||
|
||||
foreach (const SpotLight& light, _spotLights) {
|
||||
_spotLight.setUniformValue(_spotLightLocations.radius, light.radius);
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f));
|
||||
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));
|
||||
|
||||
for (auto lightID : _spotLights) {
|
||||
auto light = _allocatedLights[lightID];
|
||||
|
||||
if (_spotLightLocations.lightBufferUnit >= 0) {
|
||||
gpu::Batch batch;
|
||||
batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer());
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
}
|
||||
glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat));
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION);
|
||||
float edgeRadius = expandedRadius / glm::cos(light.cutoff);
|
||||
if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius + nearRadius) {
|
||||
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
|
||||
float edgeRadius = expandedRadius / glm::cos(light->getSpotAngle());
|
||||
if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < edgeRadius + nearRadius) {
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0f, 0.0f, -1.0f);
|
||||
|
||||
|
@ -517,12 +397,12 @@ void DeferredLightingEffect::render() {
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
} else {
|
||||
glTranslatef(light.position.x, light.position.y, light.position.z);
|
||||
glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light.direction);
|
||||
glTranslatef(light->getPosition().x, light->getPosition().y, light->getPosition().z);
|
||||
glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light->getDirection());
|
||||
glm::vec3 axis = glm::axis(spotRotation);
|
||||
glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z);
|
||||
glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f));
|
||||
geometryCache->renderCone(expandedRadius * glm::tan(light.cutoff),
|
||||
glTranslatef(0.0f, 0.0f, -light->getMaximumRadius() * (1.0f + SCALE_EXPANSION * 0.5f));
|
||||
geometryCache->renderCone(expandedRadius * glm::tan(light->getSpotAngle()),
|
||||
expandedRadius, 32, 1);
|
||||
}
|
||||
|
||||
|
@ -545,7 +425,7 @@ void DeferredLightingEffect::render() {
|
|||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
freeFBO->release();
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
// glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
|
@ -607,11 +487,46 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit
|
|||
locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale");
|
||||
locations.radius = program.uniformLocation("radius");
|
||||
locations.ambientSphere = program.uniformLocation("ambientSphere.L00");
|
||||
locations.invViewMat = program.uniformLocation("invViewMat");
|
||||
|
||||
GLint loc = -1;
|
||||
#if defined(Q_OS_MAC)
|
||||
loc = program.uniformLocation("lightBuffer");
|
||||
if (loc >= 0) {
|
||||
locations.lightBufferUnit = loc;
|
||||
} else {
|
||||
locations.lightBufferUnit = -1;
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
loc = glGetUniformBlockIndex(program.programId(), "lightBuffer");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(program.programId(), loc, 0);
|
||||
locations.lightBufferUnit = 0;
|
||||
} else {
|
||||
locations.lightBufferUnit = -1;
|
||||
}
|
||||
#else
|
||||
loc = program.uniformLocation("lightBuffer");
|
||||
if (loc >= 0) {
|
||||
locations.lightBufferUnit = loc;
|
||||
} else {
|
||||
locations.lightBufferUnit = -1;
|
||||
}
|
||||
#endif
|
||||
program.release();
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::setAmbientLightMode(int preset) {
|
||||
if ((preset >= -1) && (preset < NUM_PRESET)) {
|
||||
if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
|
||||
_ambientLightMode = preset;
|
||||
auto light = _allocatedLights.front();
|
||||
light->setAmbientSpherePreset(model::SphericalHarmonics::Preset(preset % model::SphericalHarmonics::NUM_PRESET));
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity) {
|
||||
auto light = _allocatedLights.front();
|
||||
light->setDirection(direction);
|
||||
light->setColor(diffuse);
|
||||
light->setIntensity(intensity);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "ProgramObject.h"
|
||||
|
||||
#include "model/Light.h"
|
||||
|
||||
class AbstractViewStateInterface;
|
||||
class PostLightingRenderable;
|
||||
|
||||
|
@ -71,25 +73,12 @@ public:
|
|||
void prepare();
|
||||
void render();
|
||||
|
||||
enum AmbientLightPreset {
|
||||
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,
|
||||
};
|
||||
|
||||
// update global lighting
|
||||
void setAmbientLightMode(int preset);
|
||||
void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity);
|
||||
|
||||
private:
|
||||
DeferredLightingEffect() { }
|
||||
DeferredLightingEffect() {}
|
||||
virtual ~DeferredLightingEffect() { }
|
||||
|
||||
class LightLocations {
|
||||
|
@ -102,6 +91,8 @@ private:
|
|||
int depthTexCoordScale;
|
||||
int radius;
|
||||
int ambientSphere;
|
||||
int lightBufferUnit;
|
||||
int invViewMat;
|
||||
};
|
||||
|
||||
static void loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations);
|
||||
|
@ -146,9 +137,13 @@ private:
|
|||
float exponent;
|
||||
float cutoff;
|
||||
};
|
||||
|
||||
QVector<PointLight> _pointLights;
|
||||
QVector<SpotLight> _spotLights;
|
||||
|
||||
typedef std::vector< model::LightPointer > Lights;
|
||||
|
||||
Lights _allocatedLights;
|
||||
std::vector<int> _globalLights;
|
||||
std::vector<int> _pointLights;
|
||||
std::vector<int> _spotLights;
|
||||
QVector<PostLightingRenderable*> _postLightingRenderables;
|
||||
|
||||
AbstractViewStateInterface* _viewState;
|
||||
|
|
|
@ -1154,7 +1154,7 @@ void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxC
|
|||
|
||||
gpu::Batch batch;
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
// glEnable(GL_TEXTURE_2D);
|
||||
//glBindTexture(GL_TEXTURE_2D, _currentTextureID); // this is quad specific...
|
||||
|
||||
batch.setInputFormat(details.streamFormat);
|
||||
|
@ -1168,8 +1168,8 @@ void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxC
|
|||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
// glBindTexture(GL_TEXTURE_2D, 0);
|
||||
// glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
|
||||
|
|
107
libraries/render-utils/src/Light.slh
Executable file
107
libraries/render-utils/src/Light.slh
Executable file
|
@ -0,0 +1,107 @@
|
|||
<!
|
||||
// Light.slh
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 1/25/14.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
!>
|
||||
<@if not LIGHT_SLH@>
|
||||
<@def LIGHT_SLH@>
|
||||
|
||||
struct Light {
|
||||
vec4 _position;
|
||||
vec4 _direction;
|
||||
vec4 _color;
|
||||
vec4 _attenuation;
|
||||
vec4 _spot;
|
||||
|
||||
vec4 _shadow;
|
||||
|
||||
vec4 _control;
|
||||
};
|
||||
|
||||
vec3 getLightPosition(Light l) { return l._position.xyz; }
|
||||
vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis
|
||||
|
||||
vec3 getLightColor(Light l) { return l._color.rgb; }
|
||||
float getLightIntensity(Light l) { return l._color.w; }
|
||||
|
||||
float evalLightAttenuation(Light l, float r) {
|
||||
float d = max(r - l._attenuation.x, 0.0);
|
||||
float denom = d * l._attenuation.y + 1.0;
|
||||
float attenuation = 1.0 / (denom * denom);
|
||||
return max((attenuation - l._attenuation.z)/(1.0 - l._attenuation.z), 0.0);
|
||||
// return clamp(1.0/(l._attenuation.x + l._attenuation.y * r + l._attenuation.z * r * r), 0.0, 1.0);
|
||||
}
|
||||
|
||||
float getLightSpotAngleCos(Light l) {
|
||||
return l._spot.x;
|
||||
}
|
||||
|
||||
vec2 getLightSpotOutsideNormal2(Light l) {
|
||||
return vec2(-l._spot.y, l._spot.x);
|
||||
}
|
||||
|
||||
float evalLightSpotAttenuation(Light l, float cosA) {
|
||||
return pow(cosA, l._spot.w);
|
||||
}
|
||||
|
||||
float getLightSquareRadius(Light l) {
|
||||
return l._attenuation.w * l._attenuation.w;
|
||||
}
|
||||
|
||||
float getLightRadius(Light l) {
|
||||
return l._attenuation.w;
|
||||
}
|
||||
|
||||
float getLightAttenuationCutoff(Light l) {
|
||||
return l._attenuation.z;
|
||||
}
|
||||
|
||||
float getLightShowContour(Light l) {
|
||||
return l._control.w;
|
||||
}
|
||||
|
||||
<@if GLPROFILE == PC_GL@>
|
||||
uniform lightBuffer {
|
||||
Light light;
|
||||
};
|
||||
Light getLight() {
|
||||
return light;
|
||||
}
|
||||
<@elif GLPROFILE == MAC_GL@>
|
||||
uniform vec4 lightBuffer[9];
|
||||
Light getLight() {
|
||||
Light light;
|
||||
light._position = lightBuffer[0];
|
||||
light._direction = lightBuffer[1];
|
||||
light._color = lightBuffer[2];
|
||||
light._attenuation = lightBuffer[3];
|
||||
light._spot = lightBuffer[4];
|
||||
light._shadow = lightBuffer[5];
|
||||
light._control = lightBuffer[6];
|
||||
|
||||
return light;
|
||||
}
|
||||
<@else@>
|
||||
uniform vec4 lightBuffer[9];
|
||||
Light getLight() {
|
||||
Light light;
|
||||
light._position = lightBuffer[0];
|
||||
light._direction = lightBuffer[1];
|
||||
light._color = lightBuffer[2];
|
||||
light._attenuation = lightBuffer[3];
|
||||
light._spot = lightBuffer[4];
|
||||
light._shadow = lightBuffer[5];
|
||||
light._control = lightBuffer[6];
|
||||
|
||||
return light;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
|
||||
|
||||
<@endif@>
|
|
@ -511,6 +511,10 @@ TextRenderer::TextRenderer(const char* family, float pointSize, int weight,
|
|||
bool italic, EffectType effect, int effectThickness,
|
||||
const QColor& color) :
|
||||
_effectType(effect), _effectThickness(effectThickness), _pointSize(pointSize), _color(color), _font(loadFont(family)) {
|
||||
if (!_font) {
|
||||
qWarning() << "Unable to load font with family " << family;
|
||||
_font = loadFont("Courier");
|
||||
}
|
||||
if (1 != _effectThickness) {
|
||||
qWarning() << "Effect thickness not current supported";
|
||||
}
|
||||
|
@ -524,7 +528,10 @@ TextRenderer::~TextRenderer() {
|
|||
|
||||
glm::vec2 TextRenderer::computeExtent(const QString & str) const {
|
||||
float scale = (_pointSize / DEFAULT_POINT_SIZE) * 0.25f;
|
||||
return _font->computeExtent(str) * scale;
|
||||
if (_font) {
|
||||
return _font->computeExtent(str) * scale;
|
||||
}
|
||||
return glm::vec2(0.1f,0.1f);
|
||||
}
|
||||
|
||||
float TextRenderer::draw(float x, float y, const QString & str,
|
||||
|
@ -544,7 +551,9 @@ float TextRenderer::draw(float x, float y, const QString & str,
|
|||
// scale at all.
|
||||
mv.translate(glm::vec2(x, y)).scale(glm::vec3(scale, -scale, scale));
|
||||
// The font does all the OpenGL work
|
||||
result = _font->drawString(x, y, str, actualColor, _effectType, bounds / scale);
|
||||
if (_font) {
|
||||
result = _font->drawString(x, y, str, actualColor, _effectType, bounds / scale);
|
||||
}
|
||||
});
|
||||
return result.x;
|
||||
}
|
||||
|
|
|
@ -15,22 +15,23 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
void main(void) {
|
||||
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
|
||||
|
||||
|
||||
// Light mapped or not ?
|
||||
if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
|
||||
gl_FragColor = vec4( evalLightmappedColor(
|
||||
vec3 color = evalLightmappedColor(
|
||||
1.0,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
frag.specularVal.xyz);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
} else {
|
||||
vec3 color = evalAmbientSphereColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
|
||||
+ evalDirectionalColor(1.0,
|
||||
vec3 color = evalAmbienSphereGlobalColor(1.0,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
// Everything about shadow
|
||||
<@include Shadow.slh@>
|
||||
|
@ -36,8 +36,7 @@ void main(void) {
|
|||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalAmbientSphereColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
|
||||
+ evalDirectionalColor(shadowAttenuation,
|
||||
vec3 color = evalAmbienSphereGlobalColor(shadowAttenuation,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
// Everything about shadow
|
||||
<@include Shadow.slh@>
|
||||
|
@ -37,8 +37,7 @@ void main(void) {
|
|||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalAmbientSphereColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
|
||||
+ evalDirectionalColor(shadowAttenuation,
|
||||
vec3 color = evalAmbienSphereGlobalColor(shadowAttenuation,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
void main(void) {
|
||||
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
|
||||
|
@ -29,8 +29,7 @@ void main(void) {
|
|||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalAmbientColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
|
||||
+ evalDirectionalColor(1.0,
|
||||
vec3 color = evalAmbienGlobalColor(1.0,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
// Everything about shadow
|
||||
<@include Shadow.slh@>
|
||||
|
@ -36,8 +36,7 @@ void main(void) {
|
|||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalAmbientColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
|
||||
+ evalDirectionalColor(shadowAttenuation,
|
||||
vec3 color = evalAmbienGlobalColor(shadowAttenuation,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
<@include DeferredLighting.slh@>
|
||||
<@include DeferredGlobalLight.slh@>
|
||||
|
||||
// Everything about shadow
|
||||
<@include Shadow.slh@>
|
||||
|
@ -37,8 +37,7 @@ void main(void) {
|
|||
frag.specularVal.xyz),
|
||||
1.0);
|
||||
} else {
|
||||
vec3 color = evalAmbientColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
|
||||
+ evalDirectionalColor(shadowAttenuation,
|
||||
vec3 color = evalAmbienGlobalColor(shadowAttenuation,
|
||||
frag.position.xyz,
|
||||
frag.normal,
|
||||
frag.diffuse,
|
||||
|
|
|
@ -33,8 +33,9 @@ void main(void) {
|
|||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||
// interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0)).xy;
|
||||
interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy;
|
||||
|
||||
|
||||
// use standard pipeline transform
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
|
|
@ -15,41 +15,61 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
// the radius (hard cutoff) of the light effect
|
||||
uniform float radius;
|
||||
//Everything about deferred lighting
|
||||
<@include DeferredLighting.slh@>
|
||||
|
||||
// Everything about light
|
||||
<@include Light.slh@>
|
||||
|
||||
// The view Matrix
|
||||
uniform mat4 invViewMat;
|
||||
|
||||
void main(void) {
|
||||
// get the depth and exit early if it doesn't pass the test
|
||||
// Grab the fragment data from the uv
|
||||
vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q;
|
||||
float depth = texture2D(depthMap, texCoord).r;
|
||||
DeferredFragment frag = unpackDeferredFragment(texCoord);
|
||||
|
||||
// Kill if in front of the light volume
|
||||
float depth = frag.depthVal;
|
||||
if (depth < gl_FragCoord.z) {
|
||||
discard;
|
||||
}
|
||||
// compute the view space position using the depth
|
||||
float z = near / (depth * depthScale - 1.0);
|
||||
vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0);
|
||||
|
||||
// get the normal from the map
|
||||
vec4 normal = texture2D(normalMap, texCoord);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 lightVector = gl_LightSource[1].position - position;
|
||||
float lightDistance = length(lightVector);
|
||||
lightVector = lightVector / lightDistance;
|
||||
float diffuse = dot(normalizedNormal, lightVector);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient +
|
||||
gl_FrontLightProduct[1].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute attenuation based on distance, etc.
|
||||
float attenuation = step(lightDistance, radius) / dot(vec3(gl_LightSource[1].constantAttenuation,
|
||||
gl_LightSource[1].linearAttenuation, gl_LightSource[1].quadraticAttenuation),
|
||||
vec3(1.0, lightDistance, lightDistance * lightDistance));
|
||||
|
||||
// add base to specular, modulate by attenuation
|
||||
float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
vec4 specularColor = texture2D(specularMap, texCoord);
|
||||
gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0);
|
||||
|
||||
// Need the light now
|
||||
Light light = getLight();
|
||||
|
||||
// Make the Light vector going from fragment to light center in world space
|
||||
vec4 fragPos = invViewMat * frag.position;
|
||||
vec3 fragLightVec = getLightPosition(light) - fragPos.xyz;
|
||||
|
||||
// Kill if too far from the light center
|
||||
if (dot(fragLightVec, fragLightVec) > getLightSquareRadius(light)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Allright we re valid in the volume
|
||||
float fragLightDistance = length(fragLightVec);
|
||||
vec3 fragLightDir = fragLightVec / fragLightDistance;
|
||||
|
||||
// Eval shading
|
||||
vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0));
|
||||
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss);
|
||||
|
||||
// Eval attenuation
|
||||
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);
|
||||
|
||||
// Final Lighting color
|
||||
vec3 fragColor = shading.w * (frag.diffuse + shading.xyz);
|
||||
gl_FragColor = vec4(fragColor * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0);
|
||||
|
||||
if (getLightShowContour(light) > 0.0) {
|
||||
// Show edge
|
||||
float edge = abs(2.0 * ((getLightRadius(light) - fragLightDistance) / (0.1)) - 1.0);
|
||||
if (edge < 1) {
|
||||
float edgeCoord = exp2(-8.0*edge*edge);
|
||||
gl_FragColor = vec4(edgeCoord * edgeCoord * getLightShowContour(light) * getLightColor(light), 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,43 +15,73 @@
|
|||
// Everything about deferred buffer
|
||||
<@include DeferredBuffer.slh@>
|
||||
|
||||
// the radius (hard cutoff) of the light effect
|
||||
uniform float radius;
|
||||
//Everything about deferred lighting
|
||||
<@include DeferredLighting.slh@>
|
||||
|
||||
// Everything about light
|
||||
<@include Light.slh@>
|
||||
|
||||
// The view Matrix
|
||||
uniform mat4 invViewMat;
|
||||
|
||||
void main(void) {
|
||||
// get the depth and exit early if it doesn't pass the test
|
||||
// Grab the fragment data from the uv
|
||||
vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q;
|
||||
float depth = texture2D(depthMap, texCoord).r;
|
||||
DeferredFragment frag = unpackDeferredFragment(texCoord);
|
||||
|
||||
// Kill if in front of the light volume
|
||||
float depth = frag.depthVal;
|
||||
if (depth < gl_FragCoord.z) {
|
||||
discard;
|
||||
}
|
||||
// compute the view space position using the depth
|
||||
float z = near / (depth * depthScale - 1.0);
|
||||
vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0);
|
||||
|
||||
// get the normal from the map
|
||||
vec4 normal = texture2D(normalMap, texCoord);
|
||||
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
|
||||
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 lightVector = gl_LightSource[1].position - position;
|
||||
float lightDistance = length(lightVector);
|
||||
lightVector = lightVector / lightDistance;
|
||||
float diffuse = dot(normalizedNormal, lightVector);
|
||||
float facingLight = step(0.0, diffuse);
|
||||
vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient +
|
||||
gl_FrontLightProduct[1].diffuse * (diffuse * facingLight));
|
||||
|
||||
// compute attenuation based on spot angle, distance, etc.
|
||||
float cosSpotAngle = max(-dot(lightVector.xyz, gl_LightSource[1].spotDirection), 0.0);
|
||||
float attenuation = step(lightDistance, radius) * step(gl_LightSource[1].spotCosCutoff, cosSpotAngle) *
|
||||
pow(cosSpotAngle, gl_LightSource[1].spotExponent) / dot(vec3(gl_LightSource[1].constantAttenuation,
|
||||
gl_LightSource[1].linearAttenuation, gl_LightSource[1].quadraticAttenuation),
|
||||
vec3(1.0, lightDistance, lightDistance * lightDistance));
|
||||
|
||||
// add base to specular, modulate by attenuation
|
||||
float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))),
|
||||
normalizedNormal));
|
||||
vec4 specularColor = texture2D(specularMap, texCoord);
|
||||
gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0);
|
||||
|
||||
// Need the light now
|
||||
Light light = getLight();
|
||||
|
||||
// Make the Light vector going from fragment to light center in world space
|
||||
vec4 fragPos = invViewMat * frag.position;
|
||||
vec3 fragLightVec = getLightPosition(light) - fragPos.xyz;
|
||||
|
||||
// Kill if too far from the light center
|
||||
if (dot(fragLightVec, fragLightVec) > getLightSquareRadius(light)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Allright we re valid in the volume
|
||||
float fragLightDistance = length(fragLightVec);
|
||||
vec3 fragLightDir = fragLightVec / fragLightDistance;
|
||||
|
||||
// Kill if not in the spot light (ah ah !)
|
||||
vec3 lightSpotDir = getLightDirection(light);
|
||||
float cosSpotAngle = max(-dot(fragLightDir, lightSpotDir), 0.0);
|
||||
if (cosSpotAngle < getLightSpotAngleCos(light)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Eval shading
|
||||
vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0));
|
||||
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
|
||||
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
|
||||
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss);
|
||||
|
||||
// Eval attenuation
|
||||
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);
|
||||
float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle);
|
||||
|
||||
// Final Lighting color
|
||||
vec3 fragColor = shading.w * (frag.diffuse + shading.xyz);
|
||||
gl_FragColor = vec4(fragColor * angularAttenuation * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0);
|
||||
|
||||
if (getLightShowContour(light) > 0.0) {
|
||||
// Show edges
|
||||
float edgeDistR = (getLightRadius(light) - fragLightDistance);
|
||||
float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -getLightSpotOutsideNormal2(light));
|
||||
float edgeDist = min(edgeDistR, edgeDistS);
|
||||
float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);
|
||||
if (edge < 1) {
|
||||
float edgeCoord = exp2(-8.0*edge*edge);
|
||||
gl_FragColor = vec4(edgeCoord * edgeCoord * getLightColor(light), 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,44 +31,41 @@ AudioScriptingInterface::AudioScriptingInterface() :
|
|||
}
|
||||
|
||||
ScriptAudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||
AudioInjector* injector = NULL;
|
||||
QMetaObject::invokeMethod(this, "invokedPlaySound", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(AudioInjector*, injector),
|
||||
Q_ARG(Sound*, sound), Q_ARG(const AudioInjectorOptions&, injectorOptions));
|
||||
if (injector) {
|
||||
return new ScriptAudioInjector(injector);
|
||||
} else {
|
||||
return NULL;
|
||||
if (QThread::currentThread() != thread()) {
|
||||
ScriptAudioInjector* injector = NULL;
|
||||
|
||||
QMetaObject::invokeMethod(this, "playSound", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(ScriptAudioInjector*, injector),
|
||||
Q_ARG(Sound*, sound), Q_ARG(const AudioInjectorOptions&, injectorOptions));
|
||||
return injector;
|
||||
}
|
||||
}
|
||||
|
||||
AudioInjector* AudioScriptingInterface::invokedPlaySound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||
|
||||
if (sound) {
|
||||
// stereo option isn't set from script, this comes from sound metadata or filename
|
||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
||||
optionsCopy.stereo = sound->isStereo();
|
||||
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
injectorThread->setObjectName("Audio Injector Thread");
|
||||
|
||||
|
||||
AudioInjector* injector = new AudioInjector(sound, optionsCopy);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
|
||||
injector->moveToThread(injectorThread);
|
||||
|
||||
|
||||
// start injecting when the injector thread starts
|
||||
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
||||
|
||||
|
||||
// connect the right slots and signals for AudioInjector and thread cleanup
|
||||
connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit);
|
||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||
|
||||
|
||||
injectorThread->start();
|
||||
|
||||
return injector;
|
||||
|
||||
|
||||
return new ScriptAudioInjector(injector);
|
||||
|
||||
} else {
|
||||
qDebug() << "AudioScriptingInterface::playSound called with null Sound object.";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,9 +32,6 @@ protected:
|
|||
signals:
|
||||
void mutedByMixer();
|
||||
void environmentMuted();
|
||||
|
||||
private slots:
|
||||
AudioInjector* invokedPlaySound(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
||||
|
||||
private:
|
||||
AudioScriptingInterface();
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
|
||||
QScriptValue injectorToScriptValue(QScriptEngine* engine, ScriptAudioInjector* const& in) {
|
||||
// when the script goes down we want to cleanup the injector
|
||||
QObject::connect(engine, &QScriptEngine::destroyed, in, &ScriptAudioInjector::stopInjectorImmediately);
|
||||
|
||||
QObject::connect(engine, &QScriptEngine::destroyed, in, &ScriptAudioInjector::stopInjectorImmediately,
|
||||
Qt::DirectConnection);
|
||||
|
||||
return engine->newQObject(in, QScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
@ -36,5 +38,6 @@ ScriptAudioInjector::~ScriptAudioInjector() {
|
|||
}
|
||||
|
||||
void ScriptAudioInjector::stopInjectorImmediately() {
|
||||
qDebug() << "ScriptAudioInjector::stopInjectorImmediately called to stop audio injector immediately.";
|
||||
_injector->stopAndDeleteLater();
|
||||
}
|
||||
|
|
|
@ -272,8 +272,12 @@ QScriptValue ScriptEngine::registerGlobalObject(const QString& name, QObject* ob
|
|||
}
|
||||
|
||||
void ScriptEngine::registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments) {
|
||||
registerFunction(globalObject(), name, fun, numArguments);
|
||||
}
|
||||
|
||||
void ScriptEngine::registerFunction(QScriptValue parent, const QString& name, QScriptEngine::FunctionSignature fun, int numArguments) {
|
||||
QScriptValue scriptFun = newFunction(fun, numArguments);
|
||||
globalObject().setProperty(name, scriptFun);
|
||||
parent.setProperty(name, scriptFun);
|
||||
}
|
||||
|
||||
void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
||||
QScriptEngine::FunctionSignature setter, QScriptValue object = QScriptValue::NullValue);
|
||||
void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
|
||||
void registerFunction(QScriptValue parent, const QString& name, QScriptEngine::FunctionSignature fun,
|
||||
int numArguments = -1);
|
||||
|
||||
Q_INVOKABLE void setIsAvatar(bool isAvatar);
|
||||
bool isAvatar() const { return _isAvatar; }
|
||||
|
|
|
@ -100,6 +100,8 @@ public:
|
|||
// Left will be inversed before the multiplication
|
||||
static Transform& inverseMult(Transform& result, const Transform& left, const Transform& right);
|
||||
|
||||
Vec4 transform(const Vec4& pos) const;
|
||||
|
||||
protected:
|
||||
|
||||
enum Flag {
|
||||
|
@ -414,6 +416,13 @@ inline Transform& Transform::inverseMult( Transform& result, const Transform& le
|
|||
return result;
|
||||
}
|
||||
|
||||
inline Transform::Vec4 Transform::transform(const Vec4& pos) const {
|
||||
Mat4 m;
|
||||
getMatrix(m);
|
||||
return m * pos;
|
||||
}
|
||||
|
||||
|
||||
inline Transform::Mat4& Transform::getCachedMatrix(Transform::Mat4& result) const {
|
||||
updateCache();
|
||||
result = (*_matrix);
|
||||
|
|
|
@ -219,14 +219,14 @@ static QScriptValue createRandomScriptValue(bool complex = false, bool ensureHas
|
|||
|
||||
case 4: {
|
||||
int length = randIntInRange(2, 6);
|
||||
QScriptValue value = ScriptCache::getInstance()->getEngine()->newArray(length);
|
||||
QScriptValue value = DependencyManager::get<ScriptCache>()->getEngine()->newArray(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
value.setProperty(i, createRandomScriptValue());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
default: {
|
||||
QScriptValue value = ScriptCache::getInstance()->getEngine()->newObject();
|
||||
QScriptValue value = DependencyManager::get<ScriptCache>()->getEngine()->newObject();
|
||||
if (ensureHashOrder) {
|
||||
// we can't depend on the iteration order, so if we need it to be the same (as when comparing bytes), we
|
||||
// can only have one property
|
||||
|
@ -747,7 +747,7 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) {
|
|||
case 3: {
|
||||
SharedObjectPointer newState = state->clone(true);
|
||||
QScriptValue oldValue = static_cast<TestSharedObjectA*>(newState.data())->getBizzle();
|
||||
QScriptValue newValue = ScriptCache::getInstance()->getEngine()->newObject();
|
||||
QScriptValue newValue = DependencyManager::get<ScriptCache>()->getEngine()->newObject();
|
||||
for (QScriptValueIterator it(oldValue); it.hasNext(); ) {
|
||||
it.next();
|
||||
newValue.setProperty(it.scriptName(), it.value());
|
||||
|
@ -755,8 +755,8 @@ static SharedObjectPointer mutate(const SharedObjectPointer& state) {
|
|||
switch (randIntInRange(0, 2)) {
|
||||
case 0: {
|
||||
QScriptValue oldArray = oldValue.property("foo");
|
||||
int oldLength = oldArray.property(ScriptCache::getInstance()->getLengthString()).toInt32();
|
||||
QScriptValue newArray = ScriptCache::getInstance()->getEngine()->newArray(oldLength);
|
||||
int oldLength = oldArray.property(DependencyManager::get<ScriptCache>()->getLengthString()).toInt32();
|
||||
QScriptValue newArray = DependencyManager::get<ScriptCache>()->getEngine()->newArray(oldLength);
|
||||
for (int i = 0; i < oldLength; i++) {
|
||||
newArray.setProperty(i, oldArray.property(i));
|
||||
}
|
||||
|
@ -1203,8 +1203,8 @@ TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) :
|
|||
_bong(bong) {
|
||||
sharedObjectsCreated++;
|
||||
|
||||
_bizzle = ScriptCache::getInstance()->getEngine()->newObject();
|
||||
_bizzle.setProperty("foo", ScriptCache::getInstance()->getEngine()->newArray(4));
|
||||
_bizzle = DependencyManager::get<ScriptCache>()->getEngine()->newObject();
|
||||
_bizzle.setProperty("foo", DependencyManager::get<ScriptCache>()->getEngine()->newArray(4));
|
||||
}
|
||||
|
||||
TestSharedObjectA::~TestSharedObjectA() {
|
||||
|
|
Loading…
Reference in a new issue