mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-16 05:51:07 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
ba2ab7e83a
36 changed files with 830 additions and 250 deletions
|
@ -48,6 +48,15 @@ function checkController() {
|
|||
|
||||
function keyPressEvent(event) {
|
||||
print("keyPressEvent event.key=" + event.key);
|
||||
print("keyPressEvent event.text=" + event.text);
|
||||
|
||||
print("keyPressEvent event.isShifted=" + event.isShifted);
|
||||
print("keyPressEvent event.isControl=" + event.isControl);
|
||||
print("keyPressEvent event.isMeta=" + event.isMeta);
|
||||
print("keyPressEvent event.isAlt=" + event.isAlt);
|
||||
print("keyPressEvent event.isKeypad=" + event.isKeypad);
|
||||
|
||||
|
||||
if (event.key == "A".charCodeAt(0)) {
|
||||
print("the A key was pressed");
|
||||
}
|
||||
|
@ -77,14 +86,102 @@ Agent.willSendVisualDataCallback.connect(checkController);
|
|||
|
||||
// Map keyPress and mouse move events to our callbacks
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
var AKeyEvent = {
|
||||
var KeyEvent_A = {
|
||||
key: "A".charCodeAt(0),
|
||||
text: "A",
|
||||
isShifted: false,
|
||||
isMeta: false
|
||||
};
|
||||
|
||||
var KeyEvent_a = {
|
||||
text: "a",
|
||||
isShifted: false,
|
||||
isMeta: false
|
||||
};
|
||||
|
||||
var KeyEvent_a2 = {
|
||||
key: "a".charCodeAt(0),
|
||||
isShifted: false,
|
||||
isMeta: false
|
||||
};
|
||||
|
||||
var KeyEvent_a3 = {
|
||||
text: "a"
|
||||
};
|
||||
|
||||
var KeyEvent_A2 = {
|
||||
text: "A"
|
||||
};
|
||||
|
||||
|
||||
var KeyEvent_9 = {
|
||||
text: "9"
|
||||
};
|
||||
|
||||
var KeyEvent_Num = {
|
||||
text: "#"
|
||||
};
|
||||
|
||||
var KeyEvent_At = {
|
||||
text: "@"
|
||||
};
|
||||
|
||||
var KeyEvent_MetaAt = {
|
||||
text: "@",
|
||||
isMeta: true
|
||||
};
|
||||
|
||||
var KeyEvent_Up = {
|
||||
text: "up"
|
||||
};
|
||||
var KeyEvent_Down = {
|
||||
text: "down"
|
||||
};
|
||||
var KeyEvent_Left = {
|
||||
text: "left"
|
||||
};
|
||||
var KeyEvent_Right = {
|
||||
text: "right"
|
||||
};
|
||||
|
||||
// prevent the A key from going through to the application
|
||||
Controller.captureKeyEvents(AKeyEvent);
|
||||
print("KeyEvent_A");
|
||||
Controller.captureKeyEvents(KeyEvent_A);
|
||||
|
||||
print("KeyEvent_A2");
|
||||
Controller.captureKeyEvents(KeyEvent_A2);
|
||||
|
||||
print("KeyEvent_a");
|
||||
Controller.captureKeyEvents(KeyEvent_a);
|
||||
|
||||
print("KeyEvent_a2");
|
||||
Controller.captureKeyEvents(KeyEvent_a2);
|
||||
|
||||
print("KeyEvent_a3");
|
||||
Controller.captureKeyEvents(KeyEvent_a3);
|
||||
|
||||
print("KeyEvent_9");
|
||||
Controller.captureKeyEvents(KeyEvent_9);
|
||||
|
||||
print("KeyEvent_Num");
|
||||
Controller.captureKeyEvents(KeyEvent_Num);
|
||||
|
||||
print("KeyEvent_At");
|
||||
Controller.captureKeyEvents(KeyEvent_At);
|
||||
|
||||
print("KeyEvent_MetaAt");
|
||||
Controller.captureKeyEvents(KeyEvent_MetaAt);
|
||||
|
||||
print("KeyEvent_Up");
|
||||
Controller.captureKeyEvents(KeyEvent_Up);
|
||||
print("KeyEvent_Down");
|
||||
Controller.captureKeyEvents(KeyEvent_Down);
|
||||
print("KeyEvent_Left");
|
||||
Controller.captureKeyEvents(KeyEvent_Left);
|
||||
print("KeyEvent_Right");
|
||||
Controller.captureKeyEvents(KeyEvent_Right);
|
||||
|
||||
|
||||
|
||||
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// editParticleExample.js
|
||||
// findParticleExample.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 1/24/14.
|
||||
|
|
133
examples/gameoflife.js
Normal file
133
examples/gameoflife.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
// Add your JavaScript for assignment below this line
|
||||
|
||||
// The following is an example of Conway's Game of Life (http://en.wikipedia.org/wiki/Conway's_Game_of_Life)
|
||||
|
||||
var NUMBER_OF_CELLS_EACH_DIMENSION = 64;
|
||||
var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIMENSION;
|
||||
|
||||
var currentCells = [];
|
||||
var nextCells = [];
|
||||
|
||||
var METER_LENGTH = 1;
|
||||
var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION;
|
||||
|
||||
// randomly populate the cell start values
|
||||
for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
// create the array to hold this row
|
||||
currentCells[i] = [];
|
||||
|
||||
// create the array to hold this row in the nextCells array
|
||||
nextCells[i] = [];
|
||||
|
||||
for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
currentCells[i][j] = Math.floor(Math.random() * 2);
|
||||
|
||||
// put the same value in the nextCells array for first board draw
|
||||
nextCells[i][j] = currentCells[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
function isNeighbourAlive(i, j) {
|
||||
if (i < 0 || i >= NUMBER_OF_CELLS_EACH_DIMENSION
|
||||
|| i < 0 || j >= NUMBER_OF_CELLS_EACH_DIMENSION) {
|
||||
return 0;
|
||||
} else {
|
||||
return currentCells[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
function updateCells() {
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
// figure out the number of live neighbours for the i-j cell
|
||||
var liveNeighbours =
|
||||
isNeighbourAlive(i + 1, j - 1) + isNeighbourAlive(i + 1, j) + isNeighbourAlive(i + 1, j + 1) +
|
||||
isNeighbourAlive(i, j - 1) + isNeighbourAlive(i, j + 1) +
|
||||
isNeighbourAlive(i - 1, j - 1) + isNeighbourAlive(i - 1, j) + isNeighbourAlive(i - 1, j + 1);
|
||||
|
||||
if (currentCells[i][j]) {
|
||||
// live cell
|
||||
|
||||
if (liveNeighbours < 2) {
|
||||
// rule #1 - under-population - this cell will die
|
||||
// mark it zero to mark the change
|
||||
nextCells[i][j] = 0;
|
||||
} else if (liveNeighbours < 4) {
|
||||
// rule #2 - this cell lives
|
||||
// mark it -1 to mark no change
|
||||
nextCells[i][j] = -1;
|
||||
} else {
|
||||
// rule #3 - overcrowding - this cell dies
|
||||
// mark it zero to mark the change
|
||||
nextCells[i][j] = 0;
|
||||
}
|
||||
} else {
|
||||
// dead cell
|
||||
if (liveNeighbours == 3) {
|
||||
// rule #4 - reproduction - this cell revives
|
||||
// mark it one to mark the change
|
||||
nextCells[i][j] = 1;
|
||||
} else {
|
||||
// this cell stays dead
|
||||
// mark it -1 for no change
|
||||
nextCells[i][j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.random() < 0.001) {
|
||||
// Random mutation to keep things interesting in there.
|
||||
nextCells[i][j] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
if (nextCells[i][j] != -1) {
|
||||
// there has been a change to this cell, change the value in the currentCells array
|
||||
currentCells[i][j] = nextCells[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendNextCells() {
|
||||
for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
if (nextCells[i][j] != -1) {
|
||||
// there has been a change to the state of this cell, send it
|
||||
|
||||
// find the x and y position for this voxel, z = 0
|
||||
var x = j * cellScale;
|
||||
var y = i * cellScale;
|
||||
|
||||
// queue a packet to add a voxel for the new cell
|
||||
var color = (nextCells[i][j] == 1) ? 255 : 1;
|
||||
Voxels.setVoxel(x, y, 0, cellScale, color, color, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sentFirstBoard = false;
|
||||
|
||||
function step() {
|
||||
print("step()...");
|
||||
if (sentFirstBoard) {
|
||||
// we've already sent the first full board, perform a step in time
|
||||
updateCells();
|
||||
} else {
|
||||
// this will be our first board send
|
||||
sentFirstBoard = true;
|
||||
}
|
||||
|
||||
sendNextCells();
|
||||
}
|
||||
|
||||
print("here");
|
||||
Agent.willSendVisualDataCallback.connect(step);
|
||||
Voxels.setPacketsPerSecond(200);
|
||||
print("now here");
|
26
examples/globalCollisionsExample.js
Normal file
26
examples/globalCollisionsExample.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// globalCollisionsExample.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 1/29/14.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that demonstrates use of the Controller class
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
function particleCollisionWithVoxel(particle, voxel) {
|
||||
print("particleCollisionWithVoxel()..");
|
||||
print(" particle.getID()=" + particle.id);
|
||||
print(" voxel color...=" + voxel.red + ", " + voxel.green + ", " + voxel.blue);
|
||||
}
|
||||
|
||||
function particleCollisionWithParticle(particleA, particleB) {
|
||||
print("particleCollisionWithParticle()..");
|
||||
print(" particleA.getID()=" + particleA.id);
|
||||
print(" particleB.getID()=" + particleB.id);
|
||||
}
|
||||
|
||||
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
|
||||
Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle);
|
|
@ -72,13 +72,13 @@ function checkController() {
|
|||
" function collisionWithVoxel(voxel) { " +
|
||||
" print('collisionWithVoxel(voxel)... '); " +
|
||||
" print('myID=' + Particle.getID() + '\\n'); " +
|
||||
" var voxelColor = voxel.getColor();" +
|
||||
" print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " +
|
||||
" var voxelColor = { red: voxel.red, green: voxel.green, blue: voxel.blue };" +
|
||||
" var voxelAt = { x: voxel.x, y: voxel.y, z: voxel.z };" +
|
||||
" var voxelScale = voxel.s;" +
|
||||
" print('voxelColor=' + voxel.red + ', ' + voxel.green + ', ' + voxel.blue + '\\n'); " +
|
||||
" var myColor = Particle.getColor();" +
|
||||
" print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " +
|
||||
" Particle.setColor(voxelColor); " +
|
||||
" var voxelAt = voxel.getPosition();" +
|
||||
" var voxelScale = voxel.getScale();" +
|
||||
" Voxels.eraseVoxel(voxelAt.x, voxelAt.y, voxelAt.z, voxelScale); " +
|
||||
" print('Voxels.eraseVoxel(' + voxelAt.x + ', ' + voxelAt.y + ', ' + voxelAt.z + ', ' + voxelScale + ')... \\n'); " +
|
||||
" } " +
|
||||
|
|
|
@ -65,13 +65,13 @@ function checkController() {
|
|||
" function collisionWithVoxel(voxel) { " +
|
||||
" print('collisionWithVoxel(voxel)... '); " +
|
||||
" print('myID=' + Particle.getID() + '\\n'); " +
|
||||
" var voxelColor = voxel.getColor();" +
|
||||
" var voxelColor = { red: voxel.red, green: voxel.green, blue: voxel.blue };" +
|
||||
" var voxelAt = { x: voxel.x, y: voxel.y, z: voxel.z };" +
|
||||
" var voxelScale = voxel.s;" +
|
||||
" print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " +
|
||||
" var myColor = Particle.getColor();" +
|
||||
" print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " +
|
||||
" Particle.setColor(voxelColor); " +
|
||||
" var voxelAt = voxel.getPosition();" +
|
||||
" var voxelScale = voxel.getScale();" +
|
||||
" Voxels.setVoxel(voxelAt.x, voxelAt.y, voxelAt.z, voxelScale, 255, 255, 0); " +
|
||||
" print('Voxels.setVoxel(' + voxelAt.x + ', ' + voxelAt.y + ', ' + voxelAt.z + ', ' + voxelScale + ')... \\n'); " +
|
||||
" } " +
|
||||
|
|
50
examples/rideAlongWithAParticleExample.js
Normal file
50
examples/rideAlongWithAParticleExample.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// rideAlongWithAParticleExample.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 1/24/14.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that demonstrates "finding" particles
|
||||
//
|
||||
|
||||
var iteration = 0;
|
||||
var lengthOfRide = 2000; // in iterations
|
||||
|
||||
var particleA = Particles.addParticle(
|
||||
{
|
||||
position: { x: 10, y: 0, z: 10 },
|
||||
velocity: { x: 5, y: 0, z: 5 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
radius : 0.1,
|
||||
color: { red: 0, green: 255, blue: 0 },
|
||||
damping: 0,
|
||||
lifetime: (lengthOfRide * 60) + 1
|
||||
});
|
||||
|
||||
function rideWithParticle() {
|
||||
|
||||
if (iteration <= lengthOfRide) {
|
||||
|
||||
// Check to see if we've been notified of the actual identity of the particles we created
|
||||
if (!particleA.isKnownID) {
|
||||
particleA = Particles.identifyParticle(particleA);
|
||||
}
|
||||
|
||||
var propertiesA = Particles.getParticleProperties(particleA);
|
||||
var newPosition = propertiesA.position;
|
||||
MyAvatar.position = { x: propertiesA.position.x,
|
||||
y: propertiesA.position.y + 2,
|
||||
z: propertiesA.position.z };
|
||||
} else {
|
||||
Agent.stop();
|
||||
}
|
||||
|
||||
iteration++;
|
||||
print("iteration="+iteration);
|
||||
}
|
||||
|
||||
|
||||
// register the call back so it fires before each data send
|
||||
Agent.willSendVisualDataCallback.connect(rideWithParticle);
|
||||
|
|
@ -1093,7 +1093,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
_swatch.handleEvent(event->key(), Menu::getInstance()->isOptionChecked(MenuOption::VoxelGetColorMode));
|
||||
break;
|
||||
case Qt::Key_At:
|
||||
Menu::getInstance()->goToUser();
|
||||
Menu::getInstance()->goTo();
|
||||
break;
|
||||
default:
|
||||
event->ignore();
|
||||
|
@ -1413,10 +1413,10 @@ void Application::wheelEvent(QWheelEvent* event) {
|
|||
|
||||
void Application::sendPingPackets() {
|
||||
QByteArray pingPacket = NodeList::getInstance()->constructPingPacket();
|
||||
getInstance()->controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::VoxelServer
|
||||
<< NodeType::ParticleServer
|
||||
<< NodeType::AudioMixer << NodeType::AvatarMixer
|
||||
<< NodeType::MetavoxelServer);
|
||||
controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::VoxelServer
|
||||
<< NodeType::ParticleServer
|
||||
<< NodeType::AudioMixer << NodeType::AvatarMixer
|
||||
<< NodeType::MetavoxelServer);
|
||||
}
|
||||
|
||||
// Every second, check the frame rates and other stuff
|
||||
|
@ -1878,6 +1878,17 @@ void Application::init() {
|
|||
|
||||
_particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_avatarManager);
|
||||
|
||||
// connect the _particleCollisionSystem to our script engine's ParticleScriptingInterface
|
||||
connect(&_particleCollisionSystem,
|
||||
SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&)),
|
||||
ScriptEngine::getParticlesScriptingInterface(),
|
||||
SLOT(forwardParticleCollisionWithVoxel(const ParticleID&, const VoxelDetail&)));
|
||||
|
||||
connect(&_particleCollisionSystem,
|
||||
SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&)),
|
||||
ScriptEngine::getParticlesScriptingInterface(),
|
||||
SLOT(forwardParticleCollisionWithParticle(const ParticleID&, const ParticleID&)));
|
||||
|
||||
_palette.init(_glWidget->width(), _glWidget->height());
|
||||
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0);
|
||||
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelDeleteMode), 0, 1);
|
||||
|
|
|
@ -264,7 +264,7 @@ private:
|
|||
void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true);
|
||||
|
||||
static bool sendVoxelsOperation(OctreeElement* node, void* extraData);
|
||||
static void sendPingPackets();
|
||||
void sendPingPackets();
|
||||
|
||||
void initDisplay();
|
||||
void init();
|
||||
|
|
|
@ -539,7 +539,7 @@ void Audio::toggleMute() {
|
|||
}
|
||||
|
||||
void Audio::render(int screenWidth, int screenHeight) {
|
||||
if (_audioInput) {
|
||||
if (_audioInput && _audioOutput) {
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(.93f, .93f, .93f);
|
||||
|
|
|
@ -116,10 +116,10 @@ Menu::Menu() :
|
|||
this,
|
||||
SLOT(goToLocation()));
|
||||
addActionToQMenuAndActionHash(fileMenu,
|
||||
MenuOption::GoToUser,
|
||||
MenuOption::GoTo,
|
||||
Qt::Key_At,
|
||||
this,
|
||||
SLOT(goToUser()));
|
||||
SLOT(goTo()));
|
||||
|
||||
|
||||
addDisabledActionAndSeparator(fileMenu, "Settings");
|
||||
|
@ -910,6 +910,60 @@ void Menu::goToDomain() {
|
|||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::goTo() {
|
||||
|
||||
QInputDialog gotoDialog(Application::getInstance()->getWindow());
|
||||
gotoDialog.setWindowTitle("Go to");
|
||||
gotoDialog.setLabelText("Destination:");
|
||||
QString destination = Application::getInstance()->getProfile()->getUsername();
|
||||
gotoDialog.setTextValue(destination);
|
||||
gotoDialog.setWindowFlags(Qt::Sheet);
|
||||
gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height());
|
||||
|
||||
int dialogReturn = gotoDialog.exec();
|
||||
if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) {
|
||||
|
||||
destination = gotoDialog.textValue();
|
||||
|
||||
QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts);
|
||||
|
||||
const int NUMBER_OF_COORDINATE_ITEMS = 3;
|
||||
const int X_ITEM = 0;
|
||||
const int Y_ITEM = 1;
|
||||
const int Z_ITEM = 2;
|
||||
if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) {
|
||||
|
||||
double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble();
|
||||
double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble();
|
||||
double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble();
|
||||
|
||||
glm::vec3 newAvatarPos(x, y, z);
|
||||
|
||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||
glm::vec3 avatarPos = myAvatar->getPosition();
|
||||
if (newAvatarPos != avatarPos) {
|
||||
// send a node kill request, indicating to other clients that they should play the "disappeared" effect
|
||||
MyAvatar::sendKillAvatar();
|
||||
|
||||
qDebug("Going To Location: %f, %f, %f...", x, y, z);
|
||||
myAvatar->setPosition(newAvatarPos);
|
||||
}
|
||||
|
||||
} else {
|
||||
// there's a username entered by the user, make a request to the data-server
|
||||
DataServerClient::getValuesForKeysAndUserString(
|
||||
QStringList()
|
||||
<< DataServerKey::Domain
|
||||
<< DataServerKey::Position
|
||||
<< DataServerKey::Orientation,
|
||||
destination, Application::getInstance()->getProfile());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::goToLocation() {
|
||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||
glm::vec3 avatarPos = myAvatar->getPosition();
|
||||
|
@ -954,26 +1008,6 @@ void Menu::goToLocation() {
|
|||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::goToUser() {
|
||||
QInputDialog userDialog(Application::getInstance()->getWindow());
|
||||
userDialog.setWindowTitle("Go to User");
|
||||
userDialog.setLabelText("Destination user:");
|
||||
QString username = Application::getInstance()->getProfile()->getUsername();
|
||||
userDialog.setTextValue(username);
|
||||
userDialog.setWindowFlags(Qt::Sheet);
|
||||
userDialog.resize(userDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, userDialog.size().height());
|
||||
|
||||
int dialogReturn = userDialog.exec();
|
||||
if (dialogReturn == QDialog::Accepted && !userDialog.textValue().isEmpty()) {
|
||||
// there's a username entered by the user, make a request to the data-server
|
||||
DataServerClient::getValuesForKeysAndUserString(
|
||||
QStringList() << DataServerKey::Domain << DataServerKey::Position << DataServerKey::Orientation,
|
||||
userDialog.textValue(), Application::getInstance()->getProfile());
|
||||
}
|
||||
|
||||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::pasteToVoxel() {
|
||||
QInputDialog pasteToOctalCodeDialog(Application::getInstance()->getWindow());
|
||||
pasteToOctalCodeDialog.setWindowTitle("Paste to Voxel");
|
||||
|
@ -1137,3 +1171,14 @@ void Menu::updateFrustumRenderModeAction() {
|
|||
}
|
||||
}
|
||||
|
||||
QString Menu::replaceLastOccurrence(QChar search, QChar replace, QString string) {
|
||||
int lastIndex;
|
||||
lastIndex = string.lastIndexOf(search);
|
||||
if (lastIndex > 0) {
|
||||
lastIndex = string.lastIndexOf(search);
|
||||
string.replace(lastIndex, 1, replace);
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ public slots:
|
|||
void saveSettings(QSettings* settings = NULL);
|
||||
void importSettings();
|
||||
void exportSettings();
|
||||
void goToUser();
|
||||
void goTo();
|
||||
void pasteToVoxel();
|
||||
|
||||
private slots:
|
||||
|
@ -152,6 +152,7 @@ private:
|
|||
QAction* _useVoxelShader;
|
||||
int _maxVoxelPacketsPerSecond;
|
||||
QMenu* _activeScriptsMenu;
|
||||
QString replaceLastOccurrence(QChar search, QChar replace, QString string);
|
||||
};
|
||||
|
||||
namespace MenuOption {
|
||||
|
@ -209,7 +210,7 @@ namespace MenuOption {
|
|||
const QString GlowMode = "Cycle Glow Mode";
|
||||
const QString GoToDomain = "Go To Domain...";
|
||||
const QString GoToLocation = "Go To Location...";
|
||||
const QString GoToUser = "Go To User...";
|
||||
const QString GoTo = "Go To...";
|
||||
const QString ImportVoxels = "Import Voxels";
|
||||
const QString ImportVoxelsClipboard = "Import Voxels to Clipboard";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
|
|
|
@ -170,6 +170,7 @@ public:
|
|||
const QByteArray& getDatum() const { return _datum; }
|
||||
|
||||
void pushBackToken(int token) { _pushedBackToken = token; }
|
||||
void ungetChar(char ch) { _device->ungetChar(ch); }
|
||||
|
||||
private:
|
||||
|
||||
|
@ -221,7 +222,7 @@ int Tokenizer::nextToken() {
|
|||
_datum.append(ch);
|
||||
while (_device->getChar(&ch)) {
|
||||
if (QChar(ch).isSpace() || ch == ';' || ch == ':' || ch == '{' || ch == '}' || ch == ',' || ch == '\"') {
|
||||
_device->ungetChar(ch); // read until we encounter a special character, then replace it
|
||||
ungetChar(ch); // read until we encounter a special character, then replace it
|
||||
break;
|
||||
}
|
||||
_datum.append(ch);
|
||||
|
@ -257,9 +258,17 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) {
|
|||
expectingDatum = true;
|
||||
|
||||
} else if (token == Tokenizer::DATUM_TOKEN && expectingDatum) {
|
||||
node.properties.append(tokenizer.getDatum());
|
||||
expectingDatum = false;
|
||||
|
||||
QByteArray datum = tokenizer.getDatum();
|
||||
if ((token = tokenizer.nextToken()) == ':') {
|
||||
tokenizer.ungetChar(':');
|
||||
tokenizer.pushBackToken(Tokenizer::DATUM_TOKEN);
|
||||
return node;
|
||||
|
||||
} else {
|
||||
tokenizer.pushBackToken(token);
|
||||
node.properties.append(datum);
|
||||
expectingDatum = false;
|
||||
}
|
||||
} else {
|
||||
tokenizer.pushBackToken(token);
|
||||
return node;
|
||||
|
@ -377,6 +386,9 @@ glm::mat4 createMat4(const QVector<double>& doubleVector) {
|
|||
}
|
||||
|
||||
QVector<int> getIntVector(const QVariantList& properties, int index) {
|
||||
if (index >= properties.size()) {
|
||||
return QVector<int>();
|
||||
}
|
||||
QVector<int> vector = properties.at(index).value<QVector<int> >();
|
||||
if (!vector.isEmpty()) {
|
||||
return vector;
|
||||
|
@ -388,6 +400,9 @@ QVector<int> getIntVector(const QVariantList& properties, int index) {
|
|||
}
|
||||
|
||||
QVector<double> getDoubleVector(const QVariantList& properties, int index) {
|
||||
if (index >= properties.size()) {
|
||||
return QVector<double>();
|
||||
}
|
||||
QVector<double> vector = properties.at(index).value<QVector<double> >();
|
||||
if (!vector.isEmpty()) {
|
||||
return vector;
|
||||
|
@ -1106,6 +1121,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
QVector<QString> modelIDs;
|
||||
QSet<QString> remainingModels;
|
||||
for (QHash<QString, FBXModel>::const_iterator model = models.constBegin(); model != models.constEnd(); model++) {
|
||||
// make sure the parent is in the child map
|
||||
QString parent = parentMap.value(model.key());
|
||||
if (!childMap.contains(parent, model.key())) {
|
||||
childMap.insert(parent, model.key());
|
||||
}
|
||||
remainingModels.insert(model.key());
|
||||
}
|
||||
while (!remainingModels.isEmpty()) {
|
||||
|
|
|
@ -172,105 +172,102 @@ int AvatarData::parseData(const QByteArray& packet) {
|
|||
_handData = new HandData(this);
|
||||
}
|
||||
|
||||
QDataStream packetStream(packet);
|
||||
packetStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
// increment to push past the packet header
|
||||
const unsigned char* sourceBuffer = reinterpret_cast<const unsigned char*>(packet.data());
|
||||
const unsigned char* startPosition = sourceBuffer + numBytesForPacketHeader(packet);
|
||||
|
||||
packetStream.readRawData(reinterpret_cast<char*>(&_position), sizeof(_position));
|
||||
// Body world position
|
||||
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
|
||||
sourceBuffer += sizeof(float) * 3;
|
||||
|
||||
// Body rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
uint16_t twoByteHolder;
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatAngleFromTwoByte(&twoByteHolder, &_bodyYaw);
|
||||
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyYaw);
|
||||
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyPitch);
|
||||
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyRoll);
|
||||
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatAngleFromTwoByte(&twoByteHolder, &_bodyPitch);
|
||||
// Body scale
|
||||
sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _targetScale);
|
||||
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatAngleFromTwoByte(&twoByteHolder, &_bodyRoll);
|
||||
|
||||
// body scale
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatRatioFromTwoByte(reinterpret_cast<const unsigned char*>(&twoByteHolder), _targetScale);
|
||||
|
||||
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
float headYaw, headPitch, headRoll;
|
||||
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatAngleFromTwoByte(&twoByteHolder, &headYaw);
|
||||
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatAngleFromTwoByte(&twoByteHolder, &headPitch);
|
||||
|
||||
packetStream >> twoByteHolder;
|
||||
unpackFloatAngleFromTwoByte(&twoByteHolder, &headRoll);
|
||||
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headYaw);
|
||||
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headPitch);
|
||||
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headRoll);
|
||||
|
||||
_headData->setYaw(headYaw);
|
||||
_headData->setPitch(headPitch);
|
||||
_headData->setRoll(headRoll);
|
||||
|
||||
|
||||
// Head position relative to pelvis
|
||||
packetStream >> _headData->_leanSideways;
|
||||
packetStream >> _headData->_leanForward;
|
||||
|
||||
memcpy(&_headData->_leanSideways, sourceBuffer, sizeof(_headData->_leanSideways));
|
||||
sourceBuffer += sizeof(float);
|
||||
memcpy(&_headData->_leanForward, sourceBuffer, sizeof(_headData->_leanForward));
|
||||
sourceBuffer += sizeof(_headData->_leanForward);
|
||||
|
||||
// Hand Position - is relative to body position
|
||||
glm::vec3 handPositionRelative;
|
||||
packetStream.readRawData(reinterpret_cast<char*>(&handPositionRelative), sizeof(handPositionRelative));
|
||||
memcpy(&handPositionRelative, sourceBuffer, sizeof(float) * 3);
|
||||
_handPosition = _position + handPositionRelative;
|
||||
sourceBuffer += sizeof(float) * 3;
|
||||
|
||||
// Lookat Position
|
||||
memcpy(&_headData->_lookAtPosition, sourceBuffer, sizeof(_headData->_lookAtPosition));
|
||||
sourceBuffer += sizeof(_headData->_lookAtPosition);
|
||||
|
||||
packetStream.readRawData(reinterpret_cast<char*>(&_headData->_lookAtPosition), sizeof(_headData->_lookAtPosition));
|
||||
|
||||
// Instantaneous audio loudness (used to drive facial animation)
|
||||
//sourceBuffer += unpackFloatFromByte(sourceBuffer, _audioLoudness, MAX_AUDIO_LOUDNESS);
|
||||
packetStream >> _headData->_audioLoudness;
|
||||
|
||||
// the rest is a chat message
|
||||
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
// the rest is a chat message
|
||||
int chatMessageSize = *sourceBuffer++;
|
||||
_chatMessage = string((char*)sourceBuffer, chatMessageSize);
|
||||
sourceBuffer += chatMessageSize * sizeof(char);
|
||||
|
||||
quint8 chatMessageSize;
|
||||
packetStream >> chatMessageSize;
|
||||
_chatMessage = string(packet.data() + packetStream.device()->pos(), chatMessageSize);
|
||||
packetStream.skipRawData(chatMessageSize);
|
||||
|
||||
// voxel sending features...
|
||||
unsigned char bitItems = 0;
|
||||
packetStream >> bitItems;
|
||||
bitItems = (unsigned char)*sourceBuffer++;
|
||||
|
||||
// key state, stored as a semi-nibble in the bitItems
|
||||
_keyState = (KeyState)getSemiNibbleAt(bitItems,KEY_STATE_START_BIT);
|
||||
|
||||
|
||||
// hand state, stored as a semi-nibble in the bitItems
|
||||
_handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT);
|
||||
|
||||
|
||||
_headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED);
|
||||
|
||||
|
||||
_isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED);
|
||||
|
||||
|
||||
// If it is connected, pack up the data
|
||||
if (_headData->_isFaceshiftConnected) {
|
||||
packetStream >> _headData->_leftEyeBlink;
|
||||
packetStream >> _headData->_rightEyeBlink;
|
||||
packetStream >> _headData->_averageLoudness;
|
||||
packetStream >> _headData->_browAudioLift;
|
||||
memcpy(&_headData->_leftEyeBlink, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
quint8 numBlendshapeCoefficients;
|
||||
packetStream >> numBlendshapeCoefficients;
|
||||
memcpy(&_headData->_rightEyeBlink, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
_headData->_blendshapeCoefficients.resize(numBlendshapeCoefficients);
|
||||
packetStream.readRawData(reinterpret_cast<char*>(_headData->_blendshapeCoefficients.data()),
|
||||
numBlendshapeCoefficients * sizeof(float));
|
||||
memcpy(&_headData->_averageLoudness, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
memcpy(&_headData->_browAudioLift, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
_headData->_blendshapeCoefficients.resize(*sourceBuffer++);
|
||||
memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer,
|
||||
_headData->_blendshapeCoefficients.size() * sizeof(float));
|
||||
sourceBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float);
|
||||
}
|
||||
|
||||
// pupil dilation
|
||||
quint8 pupilByte;
|
||||
packetStream >> pupilByte;
|
||||
unpackFloatFromByte(&pupilByte, _headData->_pupilDilation, 1.0f);
|
||||
sourceBuffer += unpackFloatFromByte(sourceBuffer, _headData->_pupilDilation, 1.0f);
|
||||
|
||||
// leap hand data
|
||||
if (packetStream.device()->pos() < packet.size()) {
|
||||
if (sourceBuffer - startPosition < packet.size()) {
|
||||
// check passed, bytes match
|
||||
packetStream.skipRawData(_handData->decodeRemoteData(packet.mid(packetStream.device()->pos())));
|
||||
sourceBuffer += _handData->decodeRemoteData(packet.mid(sourceBuffer - startPosition));
|
||||
}
|
||||
|
||||
return packetStream.device()->pos();
|
||||
|
||||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
void AvatarData::setClampedTargetScale(float targetScale) {
|
||||
|
|
|
@ -45,8 +45,7 @@ bool JurisdictionListener::queueJurisdictionRequest() {
|
|||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||
if (nodeList->getNodeActiveSocketOrPing(node.data()) &&
|
||||
node->getType() == getNodeType()) {
|
||||
if (nodeList->getNodeActiveSocketOrPing(node.data()) && node->getType() == getNodeType()) {
|
||||
const HifiSockAddr* nodeAddress = node->getActiveSocket();
|
||||
_packetSender.queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast<char*>(bufferOut), sizeOut));
|
||||
nodeCount++;
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // usecTimestampNow()
|
||||
#include <VoxelsScriptingInterface.h>
|
||||
#include <VoxelDetail.h>
|
||||
|
||||
|
||||
// This is not ideal, but adding script-engine as a linked library, will cause a circular reference
|
||||
// I'm open to other potential solutions. Could we change cmake to allow libraries to reference each others
|
||||
|
@ -830,7 +832,7 @@ void Particle::update(const quint64& now) {
|
|||
bool shouldDie = (getAge() > getLifetime()) || getShouldDie() || (!isInHand && isStopped && isReallyOld);
|
||||
setShouldDie(shouldDie);
|
||||
|
||||
runUpdateScript(); // allow the javascript to alter our state
|
||||
executeUpdateScripts(); // allow the javascript to alter our state
|
||||
|
||||
// If the ball is in hand, it doesn't move or have gravity effect it
|
||||
if (!isInHand) {
|
||||
|
@ -852,106 +854,62 @@ void Particle::update(const quint64& now) {
|
|||
}
|
||||
}
|
||||
|
||||
void Particle::runUpdateScript() {
|
||||
void Particle::startParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable) {
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the "this" Particle object
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
engine.evaluate();
|
||||
}
|
||||
|
||||
void Particle::endParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable) {
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
}
|
||||
|
||||
void Particle::executeUpdateScripts() {
|
||||
// Only run this particle script if there's a script attached directly to the particle.
|
||||
if (!_script.isEmpty()) {
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
ScriptEngine engine(_script);
|
||||
ParticleScriptObject particleScriptable(this);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
startParticleScriptContext(engine, particleScriptable);
|
||||
particleScriptable.emitUpdate();
|
||||
|
||||
// it seems like we may need to send out particle edits if the state of our particle was changed.
|
||||
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
endParticleScriptContext(engine, particleScriptable);
|
||||
}
|
||||
}
|
||||
|
||||
void Particle::collisionWithParticle(Particle* other) {
|
||||
// Only run this particle script if there's a script attached directly to the particle.
|
||||
if (!_script.isEmpty()) {
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
ScriptEngine engine(_script);
|
||||
ParticleScriptObject particleScriptable(this);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
startParticleScriptContext(engine, particleScriptable);
|
||||
ParticleScriptObject otherParticleScriptable(other);
|
||||
particleScriptable.emitCollisionWithParticle(&otherParticleScriptable);
|
||||
|
||||
// it seems like we may need to send out particle edits if the state of our particle was changed.
|
||||
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
endParticleScriptContext(engine, particleScriptable);
|
||||
}
|
||||
}
|
||||
|
||||
void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) {
|
||||
// Only run this particle script if there's a script attached directly to the particle.
|
||||
if (!_script.isEmpty()) {
|
||||
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
// we can use the same ones as our context.
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
ScriptEngine engine(_script);
|
||||
ParticleScriptObject particleScriptable(this);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
VoxelDetailScriptObject voxelDetailsScriptable(voxelDetails);
|
||||
particleScriptable.emitCollisionWithVoxel(&voxelDetailsScriptable);
|
||||
|
||||
// it seems like we may need to send out particle edits if the state of our particle was changed.
|
||||
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
startParticleScriptContext(engine, particleScriptable);
|
||||
particleScriptable.emitCollisionWithVoxel(*voxelDetails);
|
||||
endParticleScriptContext(engine, particleScriptable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Particle::setAge(float age) {
|
||||
quint64 ageInUsecs = age * USECS_PER_SECOND;
|
||||
_created = usecTimestampNow() - ageInUsecs;
|
||||
|
|
|
@ -20,13 +20,16 @@
|
|||
#include <SharedUtil.h>
|
||||
#include <OctreePacketData.h>
|
||||
|
||||
class VoxelsScriptingInterface;
|
||||
class ParticlesScriptingInterface;
|
||||
class VoxelEditPacketSender;
|
||||
class Particle;
|
||||
class ParticleEditPacketSender;
|
||||
class ParticleProperties;
|
||||
class Particle;
|
||||
class ParticlesScriptingInterface;
|
||||
class ParticleScriptObject;
|
||||
class ParticleTree;
|
||||
class ScriptEngine;
|
||||
class VoxelEditPacketSender;
|
||||
class VoxelsScriptingInterface;
|
||||
struct VoxelDetail;
|
||||
|
||||
const uint32_t NEW_PARTICLE = 0xFFFFFFFF;
|
||||
const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF;
|
||||
|
@ -227,7 +230,8 @@ public:
|
|||
const glm::vec3& getModelTranslation() const { return _modelTranslation; }
|
||||
const glm::quat& getModelRotation() const { return _modelRotation; }
|
||||
float getModelScale() const { return _modelScale; }
|
||||
|
||||
|
||||
ParticleID getParticleID() const { return ParticleID(getID(), getCreatorTokenID(), getID() != UNKNOWN_PARTICLE_ID); }
|
||||
ParticleProperties getProperties() const;
|
||||
|
||||
/// The last updated/simulated time of this particle from the time perspective of the authoritative server/source
|
||||
|
@ -318,11 +322,9 @@ protected:
|
|||
static VoxelEditPacketSender* _voxelEditSender;
|
||||
static ParticleEditPacketSender* _particleEditSender;
|
||||
|
||||
void runUpdateScript();
|
||||
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
||||
static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||
static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color);
|
||||
static void xColorFromScriptValue(const QScriptValue &object, xColor& color);
|
||||
void startParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable);
|
||||
void endParticleScriptContext(ScriptEngine& engine, ParticleScriptObject& particleScriptable);
|
||||
void executeUpdateScripts();
|
||||
|
||||
void setAge(float age);
|
||||
|
||||
|
@ -366,10 +368,11 @@ class ParticleScriptObject : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ParticleScriptObject(Particle* particle) { _particle = particle; }
|
||||
//~ParticleScriptObject() { qDebug() << "~ParticleScriptObject() this=" << this; }
|
||||
|
||||
void emitUpdate() { emit update(); }
|
||||
void emitCollisionWithParticle(QObject* other) { emit collisionWithParticle(other); }
|
||||
void emitCollisionWithVoxel(QObject* voxel) { emit collisionWithVoxel(voxel); }
|
||||
void emitCollisionWithVoxel(const VoxelDetail& voxel) { emit collisionWithVoxel(voxel); }
|
||||
|
||||
public slots:
|
||||
unsigned int getID() const { return _particle->getID(); }
|
||||
|
@ -414,7 +417,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
void update();
|
||||
void collisionWithVoxel(QObject* voxel);
|
||||
void collisionWithVoxel(const VoxelDetail& voxel);
|
||||
void collisionWithParticle(QObject* other);
|
||||
|
||||
private:
|
||||
|
|
|
@ -68,6 +68,17 @@ void ParticleCollisionSystem::checkParticle(Particle* particle) {
|
|||
updateCollisionWithAvatars(particle);
|
||||
}
|
||||
|
||||
void ParticleCollisionSystem::emitGlobalParicleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails) {
|
||||
ParticleID particleID = particle->getParticleID();
|
||||
emit particleCollisionWithVoxel(particleID, *voxelDetails);
|
||||
}
|
||||
|
||||
void ParticleCollisionSystem::emitGlobalParicleCollisionWithParticle(Particle* particleA, Particle* particleB) {
|
||||
ParticleID idA = particleA->getParticleID();
|
||||
ParticleID idB = particleB->getParticleID();
|
||||
emit particleCollisionWithParticle(idA, idB);
|
||||
}
|
||||
|
||||
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
|
||||
float radius = particle->getRadius() * (float)(TREE_SCALE);
|
||||
|
@ -83,6 +94,9 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
|||
// let the particles run their collision scripts if they have them
|
||||
particle->collisionWithVoxel(voxelDetails);
|
||||
|
||||
// let the global script run their collision scripts for particles if they have them
|
||||
emitGlobalParicleCollisionWithVoxel(particle, voxelDetails);
|
||||
|
||||
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
|
||||
collisionInfo._penetration /= (float)(TREE_SCALE);
|
||||
particle->applyHardCollision(collisionInfo);
|
||||
|
@ -110,6 +124,7 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
|
|||
if (glm::dot(relativeVelocity, penetration) > 0.0f) {
|
||||
particleA->collisionWithParticle(particleB);
|
||||
particleB->collisionWithParticle(particleA);
|
||||
emitGlobalParicleCollisionWithParticle(particleA, particleB);
|
||||
|
||||
glm::vec3 axis = glm::normalize(penetration);
|
||||
glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
|
||||
|
|
|
@ -31,7 +31,8 @@ class VoxelTree;
|
|||
|
||||
const glm::vec3 NO_ADDED_VELOCITY = glm::vec3(0);
|
||||
|
||||
class ParticleCollisionSystem {
|
||||
class ParticleCollisionSystem : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ParticleCollisionSystem(ParticleEditPacketSender* packetSender = NULL, ParticleTree* particles = NULL,
|
||||
VoxelTree* voxels = NULL, AbstractAudioInterface* audio = NULL,
|
||||
|
@ -51,9 +52,14 @@ public:
|
|||
void queueParticlePropertiesUpdate(Particle* particle);
|
||||
void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency);
|
||||
|
||||
signals:
|
||||
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel);
|
||||
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB);
|
||||
|
||||
private:
|
||||
static bool updateOperation(OctreeElement* element, void* extraData);
|
||||
|
||||
void emitGlobalParicleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails);
|
||||
void emitGlobalParicleCollisionWithParticle(Particle* particleA, Particle* particleB);
|
||||
|
||||
ParticleEditPacketSender* _packetSender;
|
||||
ParticleTree* _particles;
|
||||
|
|
|
@ -190,7 +190,6 @@ void ParticleTree::handleAddParticleResponse(const QByteArray& packet) {
|
|||
int numBytesPacketHeader = numBytesForPacketHeader(packet);
|
||||
|
||||
const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader;
|
||||
dataAt += numBytesPacketHeader;
|
||||
|
||||
uint32_t creatorTokenID;
|
||||
memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID));
|
||||
|
|
|
@ -53,7 +53,19 @@ public slots:
|
|||
/// finds particles within the search sphere specified by the center point and radius
|
||||
/// this function will not find any particles in script engine contexts which don't have access to particles
|
||||
QVector<ParticleID> findParticles(const glm::vec3& center, float radius) const;
|
||||
|
||||
/// inbound slots for external collision systems
|
||||
void forwardParticleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel) {
|
||||
emit particleCollisionWithVoxel(particleID, voxel);
|
||||
}
|
||||
|
||||
void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB) {
|
||||
emit particleCollisionWithParticle(idA, idB);
|
||||
}
|
||||
|
||||
signals:
|
||||
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel);
|
||||
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB);
|
||||
|
||||
private:
|
||||
void queueParticleMessage(PacketType packetType, ParticleID particleID, const ParticleProperties& properties);
|
||||
|
|
|
@ -8,22 +8,72 @@
|
|||
// Used to register meta-types with Qt for very various event types so that they can be exposed to our
|
||||
// scripting engine
|
||||
|
||||
#include <QDebug>
|
||||
#include "EventTypes.h"
|
||||
|
||||
|
||||
KeyEvent::KeyEvent() {
|
||||
key = 0;
|
||||
text = QString("");
|
||||
isShifted = false;
|
||||
isMeta = false;
|
||||
isControl = false;
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
|
||||
KeyEvent::KeyEvent(const QKeyEvent& event) {
|
||||
key = event.key();
|
||||
text = event.text();
|
||||
isShifted = event.modifiers().testFlag(Qt::ShiftModifier);
|
||||
isMeta = event.modifiers().testFlag(Qt::ControlModifier);
|
||||
isMeta = event.modifiers().testFlag(Qt::MetaModifier);
|
||||
isControl = event.modifiers().testFlag(Qt::ControlModifier);
|
||||
isAlt = event.modifiers().testFlag(Qt::AltModifier);
|
||||
isKeypad = event.modifiers().testFlag(Qt::KeypadModifier);
|
||||
isValid = true;
|
||||
|
||||
// handle special text for special characters...
|
||||
if (key == Qt::Key_F1) {
|
||||
text = "F1";
|
||||
} else if (key == Qt::Key_F2) {
|
||||
text = "F2";
|
||||
} else if (key == Qt::Key_F3) {
|
||||
text = "F3";
|
||||
} else if (key == Qt::Key_F4) {
|
||||
text = "F4";
|
||||
} else if (key == Qt::Key_F5) {
|
||||
text = "F5";
|
||||
} else if (key == Qt::Key_F6) {
|
||||
text = "F6";
|
||||
} else if (key == Qt::Key_F7) {
|
||||
text = "F7";
|
||||
} else if (key == Qt::Key_F8) {
|
||||
text = "F8";
|
||||
} else if (key == Qt::Key_F9) {
|
||||
text = "F9";
|
||||
} else if (key == Qt::Key_F10) {
|
||||
text = "F10";
|
||||
} else if (key == Qt::Key_F11) {
|
||||
text = "F11";
|
||||
} else if (key == Qt::Key_F12) {
|
||||
text = "F12";
|
||||
} else if (key == Qt::Key_Up) {
|
||||
text = "UP";
|
||||
} else if (key == Qt::Key_Down) {
|
||||
text = "DOWN";
|
||||
} else if (key == Qt::Key_Left) {
|
||||
text = "LEFT";
|
||||
} else if (key == Qt::Key_Right) {
|
||||
text = "RIGHT";
|
||||
} else if (key == Qt::Key_Escape) {
|
||||
text = "ESC";
|
||||
} else if (key == Qt::Key_Tab) {
|
||||
text = "TAB";
|
||||
} else if (key == Qt::Key_Delete) {
|
||||
text = "DELETE";
|
||||
} else if (key == Qt::Key_Backspace) {
|
||||
text = "BACKSPACE";
|
||||
}
|
||||
}
|
||||
|
||||
MouseEvent::MouseEvent(const QMouseEvent& event) {
|
||||
|
@ -65,16 +115,113 @@ void registerEventTypes(QScriptEngine* engine) {
|
|||
QScriptValue keyEventToScriptValue(QScriptEngine* engine, const KeyEvent& event) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("key", event.key);
|
||||
obj.setProperty("text", event.text);
|
||||
obj.setProperty("isShifted", event.isShifted);
|
||||
obj.setProperty("isMeta", event.isMeta);
|
||||
obj.setProperty("isControl", event.isControl);
|
||||
obj.setProperty("isAlt", event.isAlt);
|
||||
obj.setProperty("isKeypad", event.isKeypad);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void keyEventFromScriptValue(const QScriptValue &object, KeyEvent& event) {
|
||||
event.key = object.property("key").toVariant().toInt();
|
||||
event.isShifted = object.property("isShifted").toVariant().toBool();
|
||||
|
||||
event.isValid = false; // assume the worst
|
||||
event.isMeta = object.property("isMeta").toVariant().toBool();
|
||||
event.isValid = object.property("key").isValid();
|
||||
event.isControl = object.property("isControl").toVariant().toBool();
|
||||
event.isAlt = object.property("isAlt").toVariant().toBool();
|
||||
event.isKeypad = object.property("isKeypad").toVariant().toBool();
|
||||
|
||||
QScriptValue key = object.property("key");
|
||||
if (key.isValid()) {
|
||||
event.key = key.toVariant().toInt();
|
||||
event.text = QString(QChar(event.key));
|
||||
event.isValid = true;
|
||||
} else {
|
||||
QScriptValue text = object.property("text");
|
||||
if (text.isValid()) {
|
||||
event.text = object.property("text").toVariant().toString();
|
||||
|
||||
// if the text is a special command, then map it here...
|
||||
// TODO: come up with more elegant solution here, a map? is there a Qt function that gives nice names for keys?
|
||||
if (event.text.toUpper() == "F1") {
|
||||
event.key = Qt::Key_F1;
|
||||
} else if (event.text.toUpper() == "F2") {
|
||||
event.key = Qt::Key_F2;
|
||||
} else if (event.text.toUpper() == "F3") {
|
||||
event.key = Qt::Key_F3;
|
||||
} else if (event.text.toUpper() == "F4") {
|
||||
event.key = Qt::Key_F4;
|
||||
} else if (event.text.toUpper() == "F5") {
|
||||
event.key = Qt::Key_F5;
|
||||
} else if (event.text.toUpper() == "F6") {
|
||||
event.key = Qt::Key_F6;
|
||||
} else if (event.text.toUpper() == "F7") {
|
||||
event.key = Qt::Key_F7;
|
||||
} else if (event.text.toUpper() == "F8") {
|
||||
event.key = Qt::Key_F8;
|
||||
} else if (event.text.toUpper() == "F9") {
|
||||
event.key = Qt::Key_F9;
|
||||
} else if (event.text.toUpper() == "F10") {
|
||||
event.key = Qt::Key_F10;
|
||||
} else if (event.text.toUpper() == "F11") {
|
||||
event.key = Qt::Key_F11;
|
||||
} else if (event.text.toUpper() == "F12") {
|
||||
event.key = Qt::Key_F12;
|
||||
} else if (event.text.toUpper() == "UP") {
|
||||
event.key = Qt::Key_Up;
|
||||
event.isKeypad = true;
|
||||
} else if (event.text.toUpper() == "DOWN") {
|
||||
event.key = Qt::Key_Down;
|
||||
event.isKeypad = true;
|
||||
} else if (event.text.toUpper() == "LEFT") {
|
||||
event.key = Qt::Key_Left;
|
||||
event.isKeypad = true;
|
||||
} else if (event.text.toUpper() == "RIGHT") {
|
||||
event.key = Qt::Key_Right;
|
||||
event.isKeypad = true;
|
||||
} else if (event.text.toUpper() == "ESC") {
|
||||
event.key = Qt::Key_Escape;
|
||||
} else if (event.text.toUpper() == "TAB") {
|
||||
event.key = Qt::Key_Tab;
|
||||
} else if (event.text.toUpper() == "DELETE") {
|
||||
event.key = Qt::Key_Delete;
|
||||
} else if (event.text.toUpper() == "BACKSPACE") {
|
||||
event.key = Qt::Key_Backspace;
|
||||
} else {
|
||||
event.key = event.text.at(0).unicode();
|
||||
}
|
||||
event.isValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue isShifted = object.property("isShifted");
|
||||
if (isShifted.isValid()) {
|
||||
event.isShifted = isShifted.toVariant().toBool();
|
||||
} else {
|
||||
// if no isShifted was included, get it from the text
|
||||
QChar character = event.text.at(0);
|
||||
if (character.isLetter() && character.isUpper()) {
|
||||
event.isShifted = true;
|
||||
} else {
|
||||
// if it's a symbol, then attempt to detect shifted-ness
|
||||
if (QString("~!@#$%^&*()_+{}|:\"<>?").contains(character)) {
|
||||
event.isShifted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
qDebug() << "event.key=" << event.key
|
||||
<< " event.text=" << event.text
|
||||
<< " event.isShifted=" << event.isShifted
|
||||
<< " event.isControl=" << event.isControl
|
||||
<< " event.isMeta=" << event.isMeta
|
||||
<< " event.isAlt=" << event.isAlt
|
||||
<< " event.isKeypad=" << event.isKeypad;
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) {
|
||||
|
|
|
@ -24,10 +24,19 @@ public:
|
|||
KeyEvent();
|
||||
KeyEvent(const QKeyEvent& event);
|
||||
inline bool operator==(const KeyEvent& other) const {
|
||||
return other.key == key && other.isShifted == isShifted && other.isMeta == isMeta; }
|
||||
return other.key == key
|
||||
&& other.isShifted == isShifted
|
||||
&& other.isControl == isControl
|
||||
&& other.isMeta == isMeta
|
||||
&& other.isAlt == isAlt
|
||||
&& other.isKeypad == isKeypad; }
|
||||
int key;
|
||||
QString text;
|
||||
bool isShifted;
|
||||
bool isControl;
|
||||
bool isMeta;
|
||||
bool isAlt;
|
||||
bool isKeypad;
|
||||
bool isValid;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <VoxelDetail.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
|
||||
#include <Sound.h>
|
||||
|
@ -41,6 +42,7 @@ static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* eng
|
|||
|
||||
ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, const QString& fileNameString, AbstractMenuInterface* menu,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface) :
|
||||
_isAvatar(false),
|
||||
_dataServerScriptingInterface(),
|
||||
_avatarData(NULL)
|
||||
{
|
||||
|
@ -114,10 +116,12 @@ void ScriptEngine::init() {
|
|||
_voxelsScriptingInterface.init();
|
||||
_particlesScriptingInterface.init();
|
||||
|
||||
// register meta-type for glm::vec3 conversions
|
||||
// register various meta-types
|
||||
registerMetaTypes(&_engine);
|
||||
|
||||
registerVoxelMetaTypes(&_engine);
|
||||
//registerParticleMetaTypes(&_engine);
|
||||
registerEventTypes(&_engine);
|
||||
|
||||
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
|
||||
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
||||
qScriptRegisterSequenceMetaType<QVector<ParticleID> >(&_engine);
|
||||
|
|
|
@ -41,10 +41,10 @@ public:
|
|||
~ScriptEngine();
|
||||
|
||||
/// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; }
|
||||
static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; }
|
||||
|
||||
/// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; }
|
||||
static ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; }
|
||||
|
||||
/// Access the DataServerScriptingInterface for access to its underlying UUID
|
||||
const DataServerScriptingInterface& getDataServerScriptingInterface() { return _dataServerScriptingInterface; }
|
||||
|
|
|
@ -119,13 +119,13 @@ void NodeList::timePingReply(const QByteArray& packet) {
|
|||
|
||||
if (matchingNode) {
|
||||
QDataStream packetStream(packet);
|
||||
packetStream.device()->seek(numBytesForPacketHeader(packet));
|
||||
packetStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
||||
qint64 ourOriginalTime, othersReplyTime;
|
||||
quint64 ourOriginalTime, othersReplyTime;
|
||||
|
||||
packetStream >> ourOriginalTime >> othersReplyTime;
|
||||
|
||||
qint64 now = usecTimestampNow();
|
||||
quint64 now = usecTimestampNow();
|
||||
int pingTime = now - ourOriginalTime;
|
||||
int oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight
|
||||
|
||||
|
@ -554,8 +554,11 @@ QByteArray NodeList::constructPingPacket() {
|
|||
}
|
||||
|
||||
QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) {
|
||||
QDataStream pingPacketStream(pingPacket);
|
||||
pingPacketStream.skipRawData(numBytesForPacketHeader(pingPacket));
|
||||
|
||||
quint64 timeFromOriginalPing;
|
||||
memcpy(&timeFromOriginalPing, pingPacket.data() + numBytesForPacketHeader(pingPacket), sizeof(timeFromOriginalPing));
|
||||
pingPacketStream >> timeFromOriginalPing;
|
||||
|
||||
QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypePingReply);
|
||||
QDataStream packetStream(&replyPacket, QIODevice::Append);
|
||||
|
@ -621,8 +624,7 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType,
|
|||
}
|
||||
}
|
||||
|
||||
unsigned NodeList::broadcastToNodes(const QByteArray& packet,
|
||||
const NodeSet& destinationNodeTypes) {
|
||||
unsigned NodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) {
|
||||
unsigned n = 0;
|
||||
|
||||
foreach (const SharedNodePointer& node, getNodeHash()) {
|
||||
|
|
|
@ -80,7 +80,7 @@ bool packetVersionMatch(const QByteArray& packet) {
|
|||
// currently this just checks if the version in the packet matches our return from versionForPacketType
|
||||
// may need to be expanded in the future for types and versions that take > than 1 byte
|
||||
|
||||
if (packet[1] == versionForPacketType(packetTypeForPacket(packet)) || packet[0] == PacketTypeStunResponse) {
|
||||
if (packet[1] == versionForPacketType(packetTypeForPacket(packet)) || packetTypeForPacket(packet) == PacketTypeStunResponse) {
|
||||
return true;
|
||||
} else {
|
||||
PacketType mismatchType = packetTypeForPacket(packet);
|
||||
|
|
|
@ -22,6 +22,7 @@ Q_DECLARE_METATYPE(glm::vec2)
|
|||
Q_DECLARE_METATYPE(glm::quat)
|
||||
Q_DECLARE_METATYPE(xColor)
|
||||
|
||||
|
||||
void registerMetaTypes(QScriptEngine* engine);
|
||||
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
||||
|
|
|
@ -231,7 +231,6 @@ void sharedMessageHandler(QtMsgType type, const QMessageLogContext& context, con
|
|||
fprintf(stdout, "%s", message.toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
|
||||
unsigned char* pointToOctalCode(float x, float y, float z, float s) {
|
||||
return pointToVoxel(x, y, z, s);
|
||||
}
|
||||
|
|
|
@ -96,20 +96,9 @@ bool cmdOptionExists(int argc, const char * argv[],const char* option);
|
|||
|
||||
void sharedMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message);
|
||||
|
||||
struct VoxelDetail {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float s;
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
};
|
||||
|
||||
unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r = 0, unsigned char g = 0, unsigned char b = 0);
|
||||
unsigned char* pointToOctalCode(float x, float y, float z, float s);
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
void usleep(int waitTime);
|
||||
#endif
|
||||
|
|
37
libraries/voxels/src/VoxelDetail.cpp
Normal file
37
libraries/voxels/src/VoxelDetail.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// VoxelDetail.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 1/29/2014
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
#include "VoxelDetail.h"
|
||||
|
||||
void registerVoxelMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, voxelDetailToScriptValue, voxelDetailFromScriptValue);
|
||||
}
|
||||
|
||||
QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& voxelDetail) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", voxelDetail.x * (float)TREE_SCALE);
|
||||
obj.setProperty("y", voxelDetail.y * (float)TREE_SCALE);
|
||||
obj.setProperty("z", voxelDetail.z * (float)TREE_SCALE);
|
||||
obj.setProperty("s", voxelDetail.s * (float)TREE_SCALE);
|
||||
obj.setProperty("red", voxelDetail.red);
|
||||
obj.setProperty("green", voxelDetail.green);
|
||||
obj.setProperty("blue", voxelDetail.blue);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& voxelDetail) {
|
||||
voxelDetail.x = object.property("x").toVariant().toFloat() / (float)TREE_SCALE;
|
||||
voxelDetail.y = object.property("y").toVariant().toFloat() / (float)TREE_SCALE;
|
||||
voxelDetail.z = object.property("z").toVariant().toFloat() / (float)TREE_SCALE;
|
||||
voxelDetail.s = object.property("s").toVariant().toFloat() / (float)TREE_SCALE;
|
||||
voxelDetail.red = object.property("red").toVariant().toInt();
|
||||
voxelDetail.green = object.property("green").toVariant().toInt();
|
||||
voxelDetail.blue = object.property("blue").toVariant().toInt();
|
||||
}
|
||||
|
||||
|
||||
|
36
libraries/voxels/src/VoxelDetail.h
Normal file
36
libraries/voxels/src/VoxelDetail.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// VoxelDetail.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 1/29/2014
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__VoxelDetail__
|
||||
#define __hifi__VoxelDetail__
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include "VoxelConstants.h"
|
||||
|
||||
struct VoxelDetail {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float s;
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(VoxelDetail)
|
||||
|
||||
void registerVoxelMetaTypes(QScriptEngine* engine);
|
||||
|
||||
QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& color);
|
||||
void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& color);
|
||||
|
||||
|
||||
#endif /* defined(__hifi__VoxelDetail__) */
|
|
@ -70,14 +70,14 @@ bool createVoxelEditMessage(PacketType command, short int sequence,
|
|||
// cleanup
|
||||
delete[] voxelData;
|
||||
}
|
||||
|
||||
|
||||
if (success) {
|
||||
// finally, copy the result to the output
|
||||
bufferOut = new unsigned char[actualMessageSize];
|
||||
sizeOut = actualMessageSize;
|
||||
memcpy(bufferOut, messageBuffer, actualMessageSize);
|
||||
}
|
||||
|
||||
|
||||
delete[] messageBuffer; // clean up our temporary buffer
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define __shared__VoxelEditPacketSender__
|
||||
|
||||
#include <OctreeEditPacketSender.h>
|
||||
#include "VoxelDetail.h"
|
||||
|
||||
/// Utility for processing, packing, queueing and sending of outbound edit voxel messages.
|
||||
class VoxelEditPacketSender : public OctreeEditPacketSender {
|
||||
|
|
|
@ -91,5 +91,4 @@ protected:
|
|||
nodeColor _currentColor; /// Client only, false color of this voxel, 4 bytes
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(__hifi__VoxelTreeElement__) */
|
|
@ -57,20 +57,4 @@ private:
|
|||
void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails);
|
||||
};
|
||||
|
||||
class VoxelDetailScriptObject : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VoxelDetailScriptObject(VoxelDetail* voxelDetail) { _voxelDetail = voxelDetail; }
|
||||
|
||||
public slots:
|
||||
/// position in meter units
|
||||
glm::vec3 getPosition() const { return glm::vec3(_voxelDetail->x, _voxelDetail->y, _voxelDetail->z) * (float)TREE_SCALE; }
|
||||
xColor getColor() const { xColor color = { _voxelDetail->red, _voxelDetail->green, _voxelDetail->blue }; return color; }
|
||||
/// scale in meter units
|
||||
float getScale() const { return _voxelDetail->s * (float)TREE_SCALE; }
|
||||
|
||||
private:
|
||||
VoxelDetail* _voxelDetail;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelsScriptingInterface__) */
|
||||
|
|
Loading…
Reference in a new issue