mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 00:44:11 +02:00
Merge branch 'bispinor' into inertia
Conflicts: interface/src/entities/RenderableModelEntityItem.cpp libraries/entities/src/BoxEntityItem.cpp libraries/entities/src/EntityItem.cpp libraries/entities/src/EntityItem.h libraries/entities/src/EntityTree.cpp libraries/entities/src/EntityTree.h libraries/entities/src/EntityTreeElement.cpp
This commit is contained in:
commit
388830c2a2
115 changed files with 3586 additions and 903 deletions
assignment-client/src
domain-server/resources
examples
cleanupChessboards.jsclonedOverlaysExample.jseditModels.js
entityScripts
html
libraries
newEditEntities.jsoverlaysExample.jsplayChess.jsinterface
resources/meshes
src
Application.cppApplication.hAudio.cppAudio.hDatagramProcessor.cppFileLogger.cppMenu.cppMenu.hMetavoxelSystem.cppModelUploader.cpp
avatar
devices
entities
EntityTreeRenderer.cppEntityTreeRenderer.hRenderableModelEntityItem.cppRenderableTextEntityItem.cppRenderableTextEntityItem.h
renderer
scripting
ui
ToolWindow.cppToolWindow.h
overlays
Base3DOverlay.cppBase3DOverlay.hBillboardOverlay.cppBillboardOverlay.hCircle3DOverlay.cppCircle3DOverlay.hCube3DOverlay.cppCube3DOverlay.hGrid3DOverlay.cppGrid3DOverlay.hImageOverlay.cppImageOverlay.hLine3DOverlay.cppLine3DOverlay.hLocalModelsOverlay.cppLocalModelsOverlay.hLocalVoxelsOverlay.cppLocalVoxelsOverlay.hModelOverlay.cppModelOverlay.hOverlay.cppOverlay.hOverlay2D.cppOverlay2D.hOverlays.cppOverlays.hPlanar3DOverlay.cppPlanar3DOverlay.hRectangle3DOverlay.cppRectangle3DOverlay.hSphere3DOverlay.cppSphere3DOverlay.hText3DOverlay.cppText3DOverlay.hTextOverlay.cppTextOverlay.hVolume3DOverlay.cppVolume3DOverlay.h
libraries
audio/src
avatars/src
entities/src
|
@ -776,25 +776,8 @@ void AudioMixer::run() {
|
|||
// if the stream should be muted, send mute packet
|
||||
if (nodeData->getAvatarAudioStream()
|
||||
&& shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) {
|
||||
static const int TIME_BETWEEN_MUTES = 5; // in secs
|
||||
if (usecTimestampNow() - nodeData->getAvatarAudioStream()->getLastMuted() >
|
||||
TIME_BETWEEN_MUTES * USECS_PER_SECOND) {
|
||||
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment);
|
||||
int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float);
|
||||
|
||||
// Fake data to force mute
|
||||
glm::vec3 position = nodeData->getAvatarAudioStream()->getPosition();
|
||||
float radius = 1.0f;
|
||||
|
||||
char* packet = (char*)malloc(packetSize);
|
||||
populatePacketHeader(packet, PacketTypeMuteEnvironment);
|
||||
memcpy(packet + headerSize, &position, sizeof(glm::vec3));
|
||||
memcpy(packet + headerSize + sizeof(glm::vec3), &radius, sizeof(float));
|
||||
|
||||
nodeList->writeDatagram(packet, packetSize, node);
|
||||
nodeData->getAvatarAudioStream()->setLastMutedNow();
|
||||
free(packet);
|
||||
}
|
||||
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeNoisyMute);
|
||||
nodeList->writeDatagram(packet, node);
|
||||
}
|
||||
|
||||
if (node->getType() == NodeType::Agent && node->getActiveSocket()
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
#include "AvatarAudioStream.h"
|
||||
|
||||
AvatarAudioStream::AvatarAudioStream(bool isStereo, const InboundAudioStream::Settings& settings) :
|
||||
PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, settings),
|
||||
_lastMuted(usecTimestampNow())
|
||||
PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, settings)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -20,17 +20,12 @@ class AvatarAudioStream : public PositionalAudioStream {
|
|||
public:
|
||||
AvatarAudioStream(bool isStereo, const InboundAudioStream::Settings& settings);
|
||||
|
||||
qint64 getLastMuted() const { return _lastMuted; }
|
||||
void setLastMutedNow() { _lastMuted = usecTimestampNow(); }
|
||||
|
||||
private:
|
||||
// disallow copying of AvatarAudioStream objects
|
||||
AvatarAudioStream(const AvatarAudioStream&);
|
||||
AvatarAudioStream& operator= (const AvatarAudioStream&);
|
||||
|
||||
int parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples);
|
||||
|
||||
qint64 _lastMuted;
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarAudioStream_h
|
||||
|
|
|
@ -1017,10 +1017,13 @@ void OctreeServer::readConfiguration() {
|
|||
readOptionBool(QString("debugReceiving"), settingsSectionObject, _debugReceiving);
|
||||
qDebug("debugReceiving=%s", debug::valueOf(_debugReceiving));
|
||||
|
||||
readOptionBool(QString("debugTimestampNow"), settingsSectionObject, _debugTimestampNow);
|
||||
qDebug() << "debugTimestampNow=" << _debugTimestampNow;
|
||||
|
||||
bool noPersist;
|
||||
readOptionBool(QString("NoPersist"), settingsSectionObject, noPersist);
|
||||
_wantPersist = !noPersist;
|
||||
qDebug("wantPersist=%s", debug::valueOf(_wantPersist));
|
||||
qDebug() << "wantPersist=" << _wantPersist;
|
||||
|
||||
if (_wantPersist) {
|
||||
QString persistFilename;
|
||||
|
@ -1029,6 +1032,30 @@ void OctreeServer::readConfiguration() {
|
|||
}
|
||||
strcpy(_persistFilename, qPrintable(persistFilename));
|
||||
qDebug("persistFilename=%s", _persistFilename);
|
||||
|
||||
_persistInterval = OctreePersistThread::DEFAULT_PERSIST_INTERVAL;
|
||||
readOptionInt(QString("persistInterval"), settingsSectionObject, _persistInterval);
|
||||
qDebug() << "persistInterval=" << _persistInterval;
|
||||
|
||||
bool noBackup;
|
||||
readOptionBool(QString("NoBackup"), settingsSectionObject, noBackup);
|
||||
_wantBackup = !noBackup;
|
||||
qDebug() << "wantBackup=" << _wantBackup;
|
||||
|
||||
if (_wantBackup) {
|
||||
_backupExtensionFormat = OctreePersistThread::DEFAULT_BACKUP_EXTENSION_FORMAT;
|
||||
readOptionString(QString("backupExtensionFormat"), settingsSectionObject, _backupExtensionFormat);
|
||||
qDebug() << "backupExtensionFormat=" << _backupExtensionFormat;
|
||||
|
||||
_backupInterval = OctreePersistThread::DEFAULT_BACKUP_INTERVAL;
|
||||
readOptionInt(QString("backupInterval"), settingsSectionObject, _backupInterval);
|
||||
qDebug() << "backupInterval=" << _backupInterval;
|
||||
|
||||
_maxBackupVersions = OctreePersistThread::DEFAULT_MAX_BACKUP_VERSIONS;
|
||||
readOptionInt(QString("maxBackupVersions"), settingsSectionObject, _maxBackupVersions);
|
||||
qDebug() << "maxBackupVersions=" << _maxBackupVersions;
|
||||
}
|
||||
|
||||
} else {
|
||||
qDebug("persistFilename= DISABLED");
|
||||
}
|
||||
|
@ -1112,7 +1139,9 @@ void OctreeServer::run() {
|
|||
if (_wantPersist) {
|
||||
|
||||
// now set up PersistThread
|
||||
_persistThread = new OctreePersistThread(_tree, _persistFilename);
|
||||
_persistThread = new OctreePersistThread(_tree, _persistFilename, _persistInterval,
|
||||
_wantBackup, _backupInterval, _backupExtensionFormat,
|
||||
_maxBackupVersions, _debugTimestampNow);
|
||||
if (_persistThread) {
|
||||
_persistThread->initialize(true);
|
||||
}
|
||||
|
@ -1197,6 +1226,9 @@ void OctreeServer::aboutToFinish() {
|
|||
qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node;
|
||||
forceNodeShutdown(node);
|
||||
}
|
||||
if (_persistThread) {
|
||||
_persistThread->aboutToFinish();
|
||||
}
|
||||
qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish...";
|
||||
}
|
||||
|
||||
|
|
|
@ -162,11 +162,18 @@ protected:
|
|||
bool _wantPersist;
|
||||
bool _debugSending;
|
||||
bool _debugReceiving;
|
||||
bool _debugTimestampNow;
|
||||
bool _verboseDebug;
|
||||
JurisdictionMap* _jurisdiction;
|
||||
JurisdictionSender* _jurisdictionSender;
|
||||
OctreeInboundPacketProcessor* _octreeInboundPacketProcessor;
|
||||
OctreePersistThread* _persistThread;
|
||||
|
||||
int _persistInterval;
|
||||
bool _wantBackup;
|
||||
QString _backupExtensionFormat;
|
||||
int _backupInterval;
|
||||
int _maxBackupVersions;
|
||||
|
||||
static OctreeServer* _instance;
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@
|
|||
"name": "reverb",
|
||||
"type": "table",
|
||||
"label": "Reverb Settings",
|
||||
"help": "In this table you can set custom reverb values for each audio zones",
|
||||
"help": "In this table you can set reverb levels for audio zones. For a medium-sized (e.g., 100 square meter) meeting room, try a decay time of around 1.5 seconds and a wet level of -10 db. For an airplane hangar or cathedral, try a decay time of 4 seconds and a wet level of -5 db.",
|
||||
"numbered": true,
|
||||
"columns": [
|
||||
{
|
||||
|
@ -276,6 +276,60 @@
|
|||
"label": "Entity Server Settings",
|
||||
"assignment-types": [6],
|
||||
"settings": [
|
||||
{
|
||||
"name": "persistFilename",
|
||||
"label": "Persistant Filename",
|
||||
"help": "the filename for your entities",
|
||||
"placeholder": "resources/models.svo",
|
||||
"default": "resources/models.svo",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "persistInterval",
|
||||
"label": "Persist Interval",
|
||||
"help": "Interval between persist checks in msecs.",
|
||||
"placeholder": "30000",
|
||||
"default": "30000",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "NoPersist",
|
||||
"type": "checkbox",
|
||||
"help": "Don't persist your entities to a file.",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "backupExtensionFormat",
|
||||
"label": "Backup File Extension Format:",
|
||||
"help": "Format used to create the extension for the backup of your persisted entities. Use a format with %N to get rolling. Or use date formatting like %Y-%m-%d.%H:%M:%S.%z",
|
||||
"placeholder": ".backup.%N",
|
||||
"default": ".backup.%N",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "backupInterval",
|
||||
"label": "Backup Interval",
|
||||
"help": "Interval between backup checks in msecs.",
|
||||
"placeholder": "1800000",
|
||||
"default": "1800000",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "maxBackupVersions",
|
||||
"label": "Max Rolled Backup Versions",
|
||||
"help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?",
|
||||
"placeholder": "5",
|
||||
"default": "5",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "NoBackup",
|
||||
"type": "checkbox",
|
||||
"help": "Don't regularly backup your persisted entities to a backup file.",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "statusHost",
|
||||
"label": "Status Hostname",
|
||||
|
@ -313,6 +367,13 @@
|
|||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "debugTimestampNow",
|
||||
"type": "checkbox",
|
||||
"help": "extra debugging for usecTimestampNow() function",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "clockSkew",
|
||||
"label": "Clock Skew",
|
||||
|
@ -330,7 +391,52 @@
|
|||
"label": "Voxel Server Settings",
|
||||
"assignment-types": [3],
|
||||
"settings": [
|
||||
|
||||
{
|
||||
"name": "persistFilename",
|
||||
"label": "Persistant Filename",
|
||||
"help": "the filename for your voxels",
|
||||
"placeholder": "resources/voxels.svo",
|
||||
"default": "resources/voxels.svo",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "persistInterval",
|
||||
"label": "Persist Interval",
|
||||
"help": "Interval between persist checks in msecs.",
|
||||
"placeholder": "30000",
|
||||
"default": "30000",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "NoPersist",
|
||||
"type": "checkbox",
|
||||
"help": "Don't persist your voxels to a file.",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "backupExtensionFormat",
|
||||
"label": "Backup File Extension Format:",
|
||||
"help": "Format used to create the extension for the backup of your persisted voxels.",
|
||||
"placeholder": ".backup.%Y-%m-%d.%H:%M:%S.%z",
|
||||
"default": ".backup.%Y-%m-%d.%H:%M:%S.%z",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "backupInterval",
|
||||
"label": "Backup Interval",
|
||||
"help": "Interval between backup checks in msecs.",
|
||||
"placeholder": "1800000",
|
||||
"default": "1800000",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "NoBackup",
|
||||
"type": "checkbox",
|
||||
"help": "Don't regularly backup your persisted voxels to a backup file.",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "statusHost",
|
||||
"label": "Status Hostname",
|
||||
|
|
8
examples/cleanupChessboards.js
Normal file
8
examples/cleanupChessboards.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
var entities = Entities.findEntities(MyAvatar.position, 10000);
|
||||
var URL = "https://s3.amazonaws.com/hifi-public/models/props/chess/";
|
||||
|
||||
for(var i in entities) {
|
||||
if (Entities.getEntityProperties(entities[i]).modelURL.slice(0, URL.length) === URL) {
|
||||
Entities.deleteEntity(entities[i]);
|
||||
}
|
||||
}
|
294
examples/clonedOverlaysExample.js
Normal file
294
examples/clonedOverlaysExample.js
Normal file
|
@ -0,0 +1,294 @@
|
|||
//
|
||||
// clonedOverlaysExample.js
|
||||
// examples
|
||||
//
|
||||
// Created by Thijs Wenker on 11/13/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Demonstrates the use of the overlay cloning function.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
const NUM_OF_TREES = 40;
|
||||
const NUM_OF_SANTAS = 20;
|
||||
|
||||
// Image source: https://openclipart.org/detail/447/christmas-tree-by-theresaknott (heavily edited by Maximillian Merlin)
|
||||
const CHRISTMAS_TREE_SPRITES_URL = "http://test.thoys.nl/hifi/images/santa/christmas-tree.svg";
|
||||
|
||||
// Image source: http://opengameart.org/content/santa-claus (CC-BY 3.0)
|
||||
const SANTA_SPRITES_URL = "http://test.thoys.nl/hifi/images/santa/Santa.png";
|
||||
|
||||
Array.prototype.contains = function(obj) {
|
||||
var i = this.length;
|
||||
while (i--) {
|
||||
if (this[i] === obj) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function getRandomPosAroundMyAvatar(radius, height_offset) {
|
||||
if (height_offset == undefined) {
|
||||
height_offset = 0;
|
||||
}
|
||||
return {x: MyAvatar.position.x + Math.floor(Math.random() * radius * 2) - radius, y: MyAvatar.position.y + height_offset, z: MyAvatar.position.z + Math.floor(Math.random() * radius * 2) - radius};
|
||||
}
|
||||
|
||||
function OverlayPreloader(overlay_type, overlay_properties, loaded_callback) {
|
||||
var _this = this;
|
||||
this.loaded_callback = loaded_callback;
|
||||
this.overlay = Overlays.addOverlay(overlay_type, overlay_properties);
|
||||
this.timer = null;
|
||||
this.timer = Script.setInterval(function() {
|
||||
if (Overlays.isLoaded(_this.overlay)) {
|
||||
Script.clearInterval(_this.timer);
|
||||
_this.loaded_callback();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function SpriteBillboard(sprite_properties, overlay) {
|
||||
var _this = this;
|
||||
|
||||
// set properties
|
||||
this.overlay = overlay;
|
||||
this.overlay_properties = {};
|
||||
this.sprite_properties = sprite_properties;
|
||||
this.edited_overlay_properties = [];
|
||||
this.defaultFPS = 30;
|
||||
this.currentSequence = "";
|
||||
this.sequenceIndex = 0;
|
||||
this.sequenceFPS = 0;
|
||||
this.sequenceStepToNext = false;
|
||||
this.sequenceTimer = null;
|
||||
this.prevSequenceIndex = -1;
|
||||
this.sequenceX = 0;
|
||||
this.sequenceY = 0;
|
||||
|
||||
this.spriteSize = {x: 0, y: 0, width: 32, height: 64};
|
||||
|
||||
this.editedProperty = function(prop_name) {
|
||||
if (!_this.edited_overlay_properties.contains(prop_name)) {
|
||||
_this.edited_overlay_properties.push(prop_name);
|
||||
}
|
||||
};
|
||||
|
||||
// function definitions
|
||||
this.getPosition = function() {
|
||||
return _this.overlay_properties.position ?
|
||||
_this.overlay_properties.position : {x: 0, y: 0, z: 0};
|
||||
};
|
||||
|
||||
this.setPosition = function(newPosition) {
|
||||
this.overlay_properties.position = newPosition;
|
||||
this.editedProperty("position");
|
||||
return _this;
|
||||
};
|
||||
|
||||
this.setAlpha = function(alpha) {
|
||||
this.overlay_properties.alpha = alpha;
|
||||
this.editedProperty("alpha");
|
||||
return _this;
|
||||
}
|
||||
|
||||
this.setScale = function(scale) {
|
||||
this.overlay_properties.scale = scale;
|
||||
this.editedProperty("scale");
|
||||
return _this;
|
||||
}
|
||||
|
||||
this.setSpriteSize = function(spriteSize) {
|
||||
this.overlay_properties.subImage = spriteSize;
|
||||
this.editedProperty("subImage");
|
||||
return _this;
|
||||
};
|
||||
|
||||
this.setSpriteXIndex = function(x_index) {
|
||||
_this.sequenceX = x_index;
|
||||
_this.overlay_properties.subImage.x = x_index * _this.overlay_properties.subImage.width;
|
||||
_this.editedProperty("subImage");
|
||||
return _this;
|
||||
}
|
||||
|
||||
this.setSpriteYIndex = function(y_index) {
|
||||
_this.sequenceY = y_index;
|
||||
_this.overlay_properties.subImage.y = y_index * _this.overlay_properties.subImage.height;
|
||||
_this.editedProperty("subImage");
|
||||
return _this;
|
||||
}
|
||||
|
||||
this.editOverlay = function(properties) {
|
||||
for (var key in properties) {
|
||||
_this.overlay_properties[attrname] = properties[key];
|
||||
_this.editedProperty(key);
|
||||
}
|
||||
return _this;
|
||||
};
|
||||
|
||||
this.commitChanges = function() {
|
||||
var changed_properties = {};
|
||||
for (var i = 0; i < _this.edited_overlay_properties.length; i++) {
|
||||
var key = _this.edited_overlay_properties[i];
|
||||
changed_properties[key] = _this.overlay_properties[key];
|
||||
}
|
||||
if (Object.keys(changed_properties).length === 0) {
|
||||
return;
|
||||
}
|
||||
Overlays.editOverlay(_this.overlay, changed_properties);
|
||||
_this.edited_overlay_properties = [];
|
||||
};
|
||||
|
||||
this._renderFrame = function() {
|
||||
var currentSequence = _this.sprite_properties.sequences[_this.currentSequence];
|
||||
var currentItem = currentSequence[_this.sequenceIndex];
|
||||
var indexChanged = _this.sequenceIndex != _this.prevSequenceIndex;
|
||||
var canMoveToNext = true;
|
||||
_this.prevSequenceIndex = _this.sequenceIndex;
|
||||
if (indexChanged) {
|
||||
if (currentItem.loop != undefined) {
|
||||
_this.loopSequence = currentItem.loop;
|
||||
}
|
||||
if (currentItem.fps !== undefined && currentItem.fps != _this.sequenceFPS) {
|
||||
_this.startSequenceTimerFPS(currentItem.fps);
|
||||
}
|
||||
if (currentItem.step_to_next !== undefined) {
|
||||
_this.sequenceStepToNext = currentItem.step_to_next;
|
||||
}
|
||||
if (currentItem.x !== undefined) {
|
||||
_this.setSpriteXIndex(currentItem.x);
|
||||
}
|
||||
if (currentItem.y !== undefined) {
|
||||
_this.setSpriteYIndex(currentItem.y);
|
||||
}
|
||||
|
||||
if (_this.sequenceStepToNext) {
|
||||
canMoveToNext = false;
|
||||
}
|
||||
}
|
||||
_this.prevSequenceIndex = _this.sequenceIndex;
|
||||
var nextIndex = (_this.sequenceIndex + 1) % currentSequence.length;
|
||||
var nextItem = currentSequence[nextIndex];
|
||||
var nextX = nextItem.x != undefined ? nextItem.x : _this.sequenceX;
|
||||
var nextY = nextItem.Y != undefined ? nextItem.Y : _this.sequenceY;
|
||||
|
||||
if (_this.sequenceStepToNext && !indexChanged) {
|
||||
var XMoveNext = true;
|
||||
var YMoveNext = true;
|
||||
if (Math.abs(nextX - _this.sequenceX) > 1) {
|
||||
_this.setSpriteXIndex(_this.sequenceX + (nextX > _this.sequenceX ? 1 : -1));
|
||||
XMoveNext = Math.abs(nextX - _this.sequenceX) == 1;
|
||||
}
|
||||
if (Math.abs(nextY - _this.sequenceY) > 1) {
|
||||
_this.setSpriteYIndex(_this.sequenceY + (nextY > _this.sequenceY ? 1 : -1));
|
||||
YMoveNext = Math.abs(nextY - _this.sequenceY) == 1;
|
||||
}
|
||||
canMoveToNext = XMoveNext && YMoveNext;
|
||||
}
|
||||
if (canMoveToNext) {
|
||||
_this.sequenceIndex = nextIndex;
|
||||
}
|
||||
_this.commitChanges();
|
||||
|
||||
};
|
||||
|
||||
this.clone = function() {
|
||||
var clone = {};
|
||||
clone.prototype = this.prototype;
|
||||
for (property in this) {
|
||||
clone[property] = this[property];
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
|
||||
this.startSequenceTimerFPS = function(fps) {
|
||||
_this.sequenceFPS = fps;
|
||||
if (_this.sequenceTimer != null) {
|
||||
Script.clearInterval(_this.sequenceTimer);
|
||||
}
|
||||
_this.sequenceTimer = Script.setInterval(_this._renderFrame, 1000 / fps);
|
||||
}
|
||||
|
||||
this.start = function(sequenceName) {
|
||||
this.currentSequence = sequenceName;
|
||||
this.sequenceFPS = this.defaultFPS;
|
||||
this.startSequenceTimerFPS(this.defaultFPS);
|
||||
};
|
||||
|
||||
if (this.sprite_properties.url !== undefined) {
|
||||
this.setURL(this.sprite_properties.url);
|
||||
}
|
||||
|
||||
if (this.sprite_properties.sprite_size !== undefined) {
|
||||
this.setSpriteSize(this.sprite_properties.sprite_size);
|
||||
}
|
||||
|
||||
if (this.sprite_properties.scale !== undefined) {
|
||||
this.setScale(this.sprite_properties.scale);
|
||||
}
|
||||
|
||||
if (this.sprite_properties.alpha !== undefined) {
|
||||
this.setAlpha(this.sprite_properties.alpha);
|
||||
}
|
||||
|
||||
if (this.sprite_properties.position !== undefined) {
|
||||
this.setPosition(this.sprite_properties.position);
|
||||
}
|
||||
|
||||
_this.commitChanges();
|
||||
|
||||
if (this.sprite_properties.startup_sequence != undefined) {
|
||||
this.start(this.sprite_properties.startup_sequence);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (_this.sequenceTimer != null) {
|
||||
Script.clearInterval(_this.sequenceTimer);
|
||||
}
|
||||
Overlays.deleteOverlay(_this.overlay);
|
||||
});
|
||||
}
|
||||
|
||||
var christmastree_loader = null;
|
||||
christmastree_loader = new OverlayPreloader("billboard",
|
||||
{url: CHRISTMAS_TREE_SPRITES_URL, alpha: 0}, function() {
|
||||
for (var i = 0; i < NUM_OF_TREES; i++) {
|
||||
var clonedOverlay = Overlays.cloneOverlay(christmastree_loader.overlay);
|
||||
new SpriteBillboard({
|
||||
position: getRandomPosAroundMyAvatar(20),
|
||||
sprite_size: {x: 0, y: 0, width: 250.000, height: 357.626},
|
||||
scale: 6,
|
||||
alpha: 1,
|
||||
sequences: {"idle": [{x: 0, y: 0, step_to_next: true, fps: 3}, {x: 3, step_to_next: false}]},
|
||||
startup_sequence: "idle"
|
||||
}, clonedOverlay);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var santa_loader = null;
|
||||
santa_loader = new OverlayPreloader("billboard",
|
||||
{url: SANTA_SPRITES_URL, alpha: 0}, function() {
|
||||
for (var i = 0; i < NUM_OF_SANTAS; i++) {
|
||||
var clonedOverlay = Overlays.cloneOverlay(santa_loader.overlay);
|
||||
new SpriteBillboard({
|
||||
position: getRandomPosAroundMyAvatar(18, -1),
|
||||
sprite_size: {x: 0, y: 0, width: 64, height: 72},
|
||||
scale: 4,
|
||||
alpha: 1,
|
||||
sequences: {
|
||||
"walk_left": [{x: 2, y: 0, step_to_next: true, fps: 4}, {x: 10, step_to_next: false}],
|
||||
"walk_right": [{x: 10, y: 1, step_to_next: true, fps: 4}, {x: 2, step_to_next: false}],
|
||||
},
|
||||
startup_sequence: (i % 2 == 0) ? "walk_left" : "walk_right"
|
||||
}, clonedOverlay);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
Overlays.deleteOverlay(christmastree_loader.overlay);
|
||||
Overlays.deleteOverlay(santa_loader.overlay);
|
||||
});
|
|
@ -48,6 +48,9 @@ var RIGHT = 1;
|
|||
|
||||
var SPAWN_DISTANCE = 1;
|
||||
var DEFAULT_DIMENSION = 0.20;
|
||||
var DEFAULT_TEXT_DIMENSION_X = 1.0;
|
||||
var DEFAULT_TEXT_DIMENSION_Y = 1.0;
|
||||
var DEFAULT_TEXT_DIMENSION_Z = 0.01;
|
||||
|
||||
var modelURLs = [
|
||||
HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx",
|
||||
|
@ -1122,6 +1125,7 @@ var toolBar = (function () {
|
|||
newModelButton,
|
||||
newCubeButton,
|
||||
newSphereButton,
|
||||
newTextButton,
|
||||
browseModelsButton,
|
||||
loadURLMenuItem,
|
||||
loadFileMenuItem,
|
||||
|
@ -1208,7 +1212,16 @@ var toolBar = (function () {
|
|||
alpha: 0.9,
|
||||
visible: true
|
||||
});
|
||||
|
||||
|
||||
newTextButton = toolBar.addTool({
|
||||
//imageURL: toolIconUrl + "add-text.svg",
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/add-text.svg", // temporarily
|
||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
||||
width: toolWidth,
|
||||
height: toolHeight,
|
||||
alpha: 0.9,
|
||||
visible: true
|
||||
});
|
||||
}
|
||||
|
||||
function toggleNewModelButton(active) {
|
||||
|
@ -1372,6 +1385,25 @@ var toolBar = (function () {
|
|||
}
|
||||
|
||||
|
||||
if (newTextButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
type: "Text",
|
||||
position: position,
|
||||
dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z },
|
||||
backgroundColor: { red: 0, green: 0, blue: 0 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: "some text",
|
||||
lineHight: "0.1"
|
||||
});
|
||||
} else {
|
||||
print("Can't create box: Text would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -2447,7 +2479,7 @@ function Tooltip() {
|
|||
margin: this.margin,
|
||||
text: "",
|
||||
color: { red: 228, green: 228, blue: 228 },
|
||||
alpha: 0.5,
|
||||
alpha: 0.8,
|
||||
visible: false
|
||||
});
|
||||
this.show = function (doShow) {
|
||||
|
|
201
examples/entityScripts/chessPiece.js
Normal file
201
examples/entityScripts/chessPiece.js
Normal file
|
@ -0,0 +1,201 @@
|
|||
(function(){
|
||||
this.FIRST_TILE = null; // Global position of the first tile (1a)
|
||||
this.TILE_SIZE = null; // Size of one tile
|
||||
|
||||
this.wantDebug = false;
|
||||
this.active = false;
|
||||
|
||||
this.entityID = null;
|
||||
this.properties = null;
|
||||
this.boardID = null;
|
||||
this.boardUserData = null;
|
||||
|
||||
this.sound = null;
|
||||
this.startingTile = null;
|
||||
this.pieces = new Array();
|
||||
|
||||
// All callbacks start by updating the properties
|
||||
this.updateProperties = function(entityID) {
|
||||
// Piece ID
|
||||
if (this.entityID === null || !this.entityID.isKnownID) {
|
||||
this.entityID = Entities.identifyEntity(entityID);
|
||||
}
|
||||
// Piece Properties
|
||||
this.properties = Entities.getEntityProperties(this.entityID);
|
||||
|
||||
// Board ID
|
||||
if (this.boardID === null) {
|
||||
// Read user data string and update boardID
|
||||
var userData = JSON.parse(this.properties.userData);
|
||||
var boardID = Entities.identifyEntity(userData.boardID);
|
||||
if (boardID.isKnownID) {
|
||||
this.boardID = boardID;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Board User Data
|
||||
this.updateUserData();
|
||||
}
|
||||
// Get an entity's user data
|
||||
this.getEntityUserData = function(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
|
||||
if (properties && properties.userData){
|
||||
return JSON.parse(properties.userData);
|
||||
} else {
|
||||
print("No user data found.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Updates user data related objects
|
||||
this.updateUserData = function() {
|
||||
// Get board's user data
|
||||
if (this.boardID !== null && this.boardID.isKnownID) {
|
||||
this.boardUserData = this.getEntityUserData(this.boardID);
|
||||
|
||||
if (!(this.boardUserData &&
|
||||
this.boardUserData.firstTile &&
|
||||
this.boardUserData.tileSize)) {
|
||||
print("Incomplete boardUserData " + this.boardID.id);
|
||||
} else {
|
||||
this.FIRST_TILE = this.boardUserData.firstTile;
|
||||
this.TILE_SIZE = this.boardUserData.tileSize;
|
||||
|
||||
this.active = true;
|
||||
}
|
||||
} else {
|
||||
print("Missing boardID:" + JSON.stringify(this.boardID));
|
||||
}
|
||||
}
|
||||
// Returns whether pos is inside the grid or not
|
||||
this.isOutsideGrid = function(pos) {
|
||||
return !(pos.i >= 0 && pos.j >= 0 && pos.i < 8 && pos.j < 8);
|
||||
}
|
||||
// Returns the tile coordinate
|
||||
this.getIndexPosition = function(position) {
|
||||
var halfTile = this.TILE_SIZE / 2.0;
|
||||
var corner = Vec3.sum(this.FIRST_TILE, { x: -halfTile, y: 0.0, z: -halfTile });
|
||||
var relative = Vec3.subtract(position, corner);
|
||||
return {
|
||||
i: Math.floor(relative.x / this.TILE_SIZE),
|
||||
j: Math.floor(relative.z / this.TILE_SIZE)
|
||||
}
|
||||
}
|
||||
// Returns the world position
|
||||
this.getAbsolutePosition = function(pos, halfHeight) {
|
||||
var relative = {
|
||||
x: pos.i * this.TILE_SIZE,
|
||||
y: halfHeight,
|
||||
z: pos.j * this.TILE_SIZE
|
||||
}
|
||||
return Vec3.sum(this.FIRST_TILE, relative);
|
||||
}
|
||||
// Pr, Vr are respectively the Ray's Point of origin and Vector director
|
||||
// Pp, Np are respectively the Plane's Point of origin and Normal vector
|
||||
this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) {
|
||||
var d = -Vec3.dot(Pp, Np);
|
||||
var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np);
|
||||
return Vec3.sum(Pr, Vec3.multiply(t, Vr));
|
||||
}
|
||||
// Download sound if needed
|
||||
this.maybeDownloadSound = function() {
|
||||
if (this.sound === null) {
|
||||
this.sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW3Left-12db.wav");
|
||||
}
|
||||
}
|
||||
// Play drop sound
|
||||
this.playSound = function() {
|
||||
if (this.sound && this.sound.downloaded) {
|
||||
Audio.playSound(this.sound, { position: this.properties.position });
|
||||
}
|
||||
}
|
||||
// updates the piece position based on mouse input
|
||||
this.updatePosition = function(mouseEvent) {
|
||||
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
|
||||
var upVector = { x: 0, y: 1, z: 0 };
|
||||
var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction,
|
||||
this.properties.position, upVector);
|
||||
// if piece outside grid then send it back to the starting tile
|
||||
if (this.isOutsideGrid(this.getIndexPosition(intersection))) {
|
||||
intersection = this.getAbsolutePosition(this.startingTile, this.properties.dimensions.y / 2.0);
|
||||
}
|
||||
Entities.editEntity(this.entityID, { position: intersection });
|
||||
}
|
||||
// Snap piece to the center of the tile it is on
|
||||
this.snapToGrid = function() {
|
||||
var pos = this.getIndexPosition(this.properties.position);
|
||||
var finalPos = this.getAbsolutePosition((this.isOutsideGrid(pos)) ? this.startingTile : pos,
|
||||
this.properties.dimensions.y / 2.0);
|
||||
Entities.editEntity(this.entityID, { position: finalPos });
|
||||
}
|
||||
this.moveDeadPiece = function() {
|
||||
var myPos = this.getIndexPosition(this.properties.position);
|
||||
var others = Entities.findEntities(this.properties.position, this.properties.dimensions.y);
|
||||
|
||||
for (var i = 0; i < others.length; i++) {
|
||||
var piece = others[i];
|
||||
|
||||
if (piece.id != this.entityID.id) {
|
||||
var properties = Entities.getEntityProperties(piece);
|
||||
|
||||
var isWhite = properties.modelURL.search("White") !== -1;
|
||||
var type = (properties.modelURL.search("King") !== -1) ? 4 :
|
||||
(properties.modelURL.search("Queen") !== -1) ? 3 :
|
||||
(properties.modelURL.search("Rook") !== -1) ? 2 :
|
||||
(properties.modelURL.search("Knight") !== -1) ? 1 :
|
||||
(properties.modelURL.search("Bishop") !== -1) ? 0 :
|
||||
(properties.modelURL.search("Pawn") !== -1) ? -1 : -2;
|
||||
|
||||
var piecePos = this.getIndexPosition(properties.position);
|
||||
if (myPos.i === piecePos.i && myPos.j === piecePos.j && type !== -2) {
|
||||
var position = this.getAbsolutePosition((isWhite) ? { i: type, j: -1 } : { i: 7 - type, j: 8 },
|
||||
properties.dimensions.y / 2.0);
|
||||
Entities.editEntity(piece, {
|
||||
position: position
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.grab = function(mouseEvent) {
|
||||
if (this.active) {
|
||||
this.startingTile = this.getIndexPosition(this.properties.position);
|
||||
this.updatePosition(mouseEvent);
|
||||
}
|
||||
}
|
||||
this.move = function(mouseEvent) {
|
||||
if (this.active) {
|
||||
this.updatePosition(mouseEvent);
|
||||
}
|
||||
}
|
||||
this.release = function(mouseEvent) {
|
||||
if (this.active) {
|
||||
this.updatePosition(mouseEvent);
|
||||
this.snapToGrid();
|
||||
this.moveDeadPiece();
|
||||
this.playSound();
|
||||
}
|
||||
}
|
||||
|
||||
this.preload = function(entityID) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.maybeDownloadSound();
|
||||
}
|
||||
this.clickDownOnEntity = function(entityID, mouseEvent) {
|
||||
this.preload(entityID); // TODO : remove
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.grab(mouseEvent);
|
||||
};
|
||||
this.holdingClickOnEntity = function(entityID, mouseEvent) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.move(mouseEvent);
|
||||
};
|
||||
this.clickReleaseOnEntity = function(entityID, mouseEvent) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.release(mouseEvent);
|
||||
};
|
||||
})
|
80
examples/entityScripts/movable.js
Normal file
80
examples/entityScripts/movable.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// movable.js
|
||||
// examples/entityScripts
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 11/17/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
(function(){
|
||||
|
||||
this.entityID = null;
|
||||
this.properties = null;
|
||||
this.graboffset = null;
|
||||
|
||||
// Pr, Vr are respectively the Ray's Point of origin and Vector director
|
||||
// Pp, Np are respectively the Plane's Point of origin and Normal vector
|
||||
this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) {
|
||||
var d = -Vec3.dot(Pp, Np);
|
||||
var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np);
|
||||
return Vec3.sum(Pr, Vec3.multiply(t, Vr));
|
||||
};
|
||||
|
||||
// updates the piece position based on mouse input
|
||||
this.updatePosition = function(mouseEvent) {
|
||||
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
|
||||
var upVector = { x: 0, y: 1, z: 0 };
|
||||
var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction,
|
||||
this.properties.position, upVector);
|
||||
|
||||
var newPosition = Vec3.sum(intersection, this.graboffset);
|
||||
Entities.editEntity(this.entityID, { position: newPosition });
|
||||
};
|
||||
|
||||
this.grab = function(mouseEvent) {
|
||||
// first calculate the offset
|
||||
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
|
||||
var upVector = { x: 0, y: 1, z: 0 };
|
||||
var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction,
|
||||
this.properties.position, upVector);
|
||||
this.graboffset = Vec3.subtract(this.properties.position, intersection);
|
||||
this.updatePosition(mouseEvent);
|
||||
};
|
||||
|
||||
this.move = function(mouseEvent) {
|
||||
this.updatePosition(mouseEvent);
|
||||
};
|
||||
|
||||
this.release = function(mouseEvent) {
|
||||
this.updatePosition(mouseEvent);
|
||||
};
|
||||
|
||||
// All callbacks start by updating the properties
|
||||
this.updateProperties = function(entityID) {
|
||||
if (this.entityID === null || !this.entityID.isKnownID) {
|
||||
this.entityID = Entities.identifyEntity(entityID);
|
||||
}
|
||||
this.properties = Entities.getEntityProperties(this.entityID);
|
||||
};
|
||||
|
||||
this.preload = function(entityID) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
};
|
||||
|
||||
this.clickDownOnEntity = function(entityID, mouseEvent) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.grab(mouseEvent);
|
||||
};
|
||||
|
||||
this.holdingClickOnEntity = function(entityID, mouseEvent) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.move(mouseEvent);
|
||||
};
|
||||
this.clickReleaseOnEntity = function(entityID, mouseEvent) {
|
||||
this.updateProperties(entityID); // All callbacks start by updating the properties
|
||||
this.release(mouseEvent);
|
||||
};
|
||||
|
||||
})
|
639
examples/html/entityProperties.html
Normal file
639
examples/html/entityProperties.html
Normal file
|
@ -0,0 +1,639 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script>
|
||||
function enableChildren(el, selector) {
|
||||
els = el.querySelectorAll(selector);
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
els[i].removeAttribute('disabled');
|
||||
}
|
||||
}
|
||||
function disableChildren(el, selector) {
|
||||
els = el.querySelectorAll(selector);
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
els[i].setAttribute('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
|
||||
function createEmitCheckedPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
function createEmitNumberPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":' + this.value + '}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
function createEmitTextPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":"' + this.value + '"}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) {
|
||||
return function() {
|
||||
var data = {
|
||||
type: "update",
|
||||
properties: {
|
||||
}
|
||||
};
|
||||
data.properties[property] = {
|
||||
x: elX.value,
|
||||
y: elY.value,
|
||||
z: elZ.value,
|
||||
};
|
||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) {
|
||||
return function() {
|
||||
var data = {
|
||||
type: "update",
|
||||
properties: {
|
||||
}
|
||||
};
|
||||
data.properties[property] = {
|
||||
red: elRed.value,
|
||||
green: elGreen.value,
|
||||
blue: elBlue.value,
|
||||
};
|
||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
function loaded() {
|
||||
var elType = document.getElementById("property-type");
|
||||
var elLocked = document.getElementById("property-locked");
|
||||
var elVisible = document.getElementById("property-visible");
|
||||
var elPositionX = document.getElementById("property-pos-x");
|
||||
var elPositionY = document.getElementById("property-pos-y");
|
||||
var elPositionZ = document.getElementById("property-pos-z");
|
||||
|
||||
var elDimensionsX = document.getElementById("property-dim-x");
|
||||
var elDimensionsY = document.getElementById("property-dim-y");
|
||||
var elDimensionsZ = document.getElementById("property-dim-z");
|
||||
|
||||
var elRegistrationX = document.getElementById("property-reg-x");
|
||||
var elRegistrationY = document.getElementById("property-reg-y");
|
||||
var elRegistrationZ = document.getElementById("property-reg-z");
|
||||
|
||||
var elLinearVelocityX = document.getElementById("property-lvel-x");
|
||||
var elLinearVelocityY = document.getElementById("property-lvel-y");
|
||||
var elLinearVelocityZ = document.getElementById("property-lvel-z");
|
||||
var elLinearDamping = document.getElementById("property-ldamping");
|
||||
|
||||
var elAngularVelocityX = document.getElementById("property-avel-x");
|
||||
var elAngularVelocityY = document.getElementById("property-avel-y");
|
||||
var elAngularVelocityZ = document.getElementById("property-avel-z");
|
||||
var elAngularDamping = document.getElementById("property-adamping");
|
||||
|
||||
var elGravityX = document.getElementById("property-grav-x");
|
||||
var elGravityY = document.getElementById("property-grav-y");
|
||||
var elGravityZ = document.getElementById("property-grav-z");
|
||||
|
||||
var elMass = document.getElementById("property-mass");
|
||||
var elIgnoreForCollisions = document.getElementById("property-ignore-for-collisions");
|
||||
var elCollisionsWillMove = document.getElementById("property-collisions-will-move");
|
||||
var elLifetime = document.getElementById("property-lifetime");
|
||||
|
||||
var elBoxSection = document.getElementById("box-section");
|
||||
var elBoxColorRed = document.getElementById("property-box-red");
|
||||
var elBoxColorGreen = document.getElementById("property-box-green");
|
||||
var elBoxColorBlue = document.getElementById("property-box-blue");
|
||||
|
||||
var elLightSection = document.getElementById('light-section');
|
||||
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
||||
var elLightDiffuseRed = document.getElementById("property-light-diffuse-red");
|
||||
var elLightDiffuseGreen = document.getElementById("property-light-diffuse-green");
|
||||
var elLightDiffuseBlue = document.getElementById("property-light-diffuse-blue");
|
||||
|
||||
var elLightAmbientRed = document.getElementById("property-light-ambient-red");
|
||||
var elLightAmbientGreen = document.getElementById("property-light-ambient-green");
|
||||
var elLightAmbientBlue = document.getElementById("property-light-ambient-blue");
|
||||
|
||||
var elLightSpecularRed = document.getElementById("property-light-specular-red");
|
||||
var elLightSpecularGreen = document.getElementById("property-light-specular-green");
|
||||
var elLightSpecularBlue = document.getElementById("property-light-specular-blue");
|
||||
|
||||
var elLightConstantAttenuation = document.getElementById("property-light-constant-attenuation");
|
||||
var elLightLinearAttenuation = document.getElementById("property-light-linear-attenuation");
|
||||
var elLightQuadraticAttenuation = document.getElementById("property-light-quadratic-attenuation");
|
||||
var elLightExponent = document.getElementById("property-light-exponent");
|
||||
var elLightCutoff = document.getElementById("property-light-cutoff");
|
||||
|
||||
var elModelSection = document.getElementById("model-section");
|
||||
var elModelURL = document.getElementById("property-model-url");
|
||||
var elModelAnimationURL = document.getElementById("property-model-animation-url");
|
||||
var elModelAnimationPlaying = document.getElementById("property-model-animation-playing");
|
||||
var elModelAnimationFPS = document.getElementById("property-model-animation-fps");
|
||||
var elModelAnimationFrame = document.getElementById("property-model-animation-frame");
|
||||
|
||||
var elTextSection = document.getElementById("text-section");
|
||||
var elTextText = document.getElementById("property-text-text");
|
||||
var elTextLineHeight = document.getElementById("property-text-line-height");
|
||||
var elTextTextColorRed = document.getElementById("property-text-text-color-red");
|
||||
var elTextTextColorGreen = document.getElementById("property-text-text-color-green");
|
||||
var elTextTextColorBlue = document.getElementById("property-text-text-color-blue");
|
||||
var elTextBackgroundColorRed = document.getElementById("property-text-background-color-red");
|
||||
var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green");
|
||||
var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.type == "update") {
|
||||
if (data.properties === undefined) {
|
||||
disableChildren(document.getElementById("properties"), 'input');
|
||||
} else {
|
||||
var properties = data.properties;
|
||||
|
||||
elType.innerHTML = properties.type;
|
||||
|
||||
elLocked.checked = properties.locked;
|
||||
|
||||
if (properties.locked) {
|
||||
disableChildren(document.getElementById("properties"), 'input');
|
||||
elLocked.removeAttribute('disabled');
|
||||
} else {
|
||||
enableChildren(document.getElementById("properties"), 'input');
|
||||
|
||||
elVisible.checked = properties.visible;
|
||||
|
||||
elPositionX.value = properties.position.x.toFixed(2);
|
||||
elPositionY.value = properties.position.y.toFixed(2);
|
||||
elPositionZ.value = properties.position.z.toFixed(2);
|
||||
|
||||
elDimensionsX.value = properties.dimensions.x.toFixed(2);
|
||||
elDimensionsY.value = properties.dimensions.y.toFixed(2);
|
||||
elDimensionsZ.value = properties.dimensions.z.toFixed(2);
|
||||
|
||||
elRegistrationX.value = properties.registrationPoint.x.toFixed(2);
|
||||
elRegistrationY.value = properties.registrationPoint.y.toFixed(2);
|
||||
elRegistrationZ.value = properties.registrationPoint.z.toFixed(2);
|
||||
|
||||
elLinearVelocityX.value = properties.velocity.x.toFixed(2);
|
||||
elLinearVelocityY.value = properties.velocity.y.toFixed(2);
|
||||
elLinearVelocityZ.value = properties.velocity.z.toFixed(2);
|
||||
elLinearDamping.value = properties.damping.toFixed(2);
|
||||
|
||||
elAngularVelocityX.value = properties.angularVelocity.x.toFixed(2);
|
||||
elAngularVelocityY.value = properties.angularVelocity.y.toFixed(2);
|
||||
elAngularVelocityZ.value = properties.angularVelocity.z.toFixed(2);
|
||||
elAngularDamping.value = properties.angularDamping.toFixed(2);
|
||||
|
||||
elGravityX.value = properties.gravity.x.toFixed(2);
|
||||
elGravityY.value = properties.gravity.y.toFixed(2);
|
||||
elGravityZ.value = properties.gravity.z.toFixed(2);
|
||||
|
||||
elMass.value = properties.mass.toFixed(2);
|
||||
elIgnoreForCollisions.checked = properties.ignoreForCollisions;
|
||||
elCollisionsWillMove.checked = properties.collisionsWillMove;
|
||||
elLifetime.value = properties.lifetime;
|
||||
|
||||
if (properties.type != "Box") {
|
||||
elBoxSection.style.display = 'none';
|
||||
} else {
|
||||
elBoxSection.style.display = 'block';
|
||||
|
||||
elBoxColorRed.value = properties.color.red;
|
||||
elBoxColorGreen.value = properties.color.green;
|
||||
elBoxColorBlue.value = properties.color.blue;
|
||||
}
|
||||
|
||||
if (properties.type != "Model") {
|
||||
elModelSection.style.display = 'none';
|
||||
} else {
|
||||
elModelSection.style.display = 'block';
|
||||
elModelURL.value = properties.modelURL;
|
||||
elModelAnimationURL.value = properties.animationURL;
|
||||
elModelAnimationPlaying.checked = properties.animationPlaying;
|
||||
elModelAnimationFPS.value = properties.animationFPS;
|
||||
}
|
||||
|
||||
if (properties.type != "Text") {
|
||||
elTextSection.style.display = 'none';
|
||||
} else {
|
||||
elTextSection.style.display = 'block';
|
||||
|
||||
elTextText.value = properties.text;
|
||||
elTextLineHeight.value = properties.lineHeight;
|
||||
elTextTextColorRed.value = properties.textColor.red;
|
||||
elTextTextColorGreen.value = properties.textColor.green;
|
||||
elTextTextColorBlue.value = properties.textColor.blue;
|
||||
elTextBackgroundColorRed.value = properties.backgroundColor.red;
|
||||
elTextBackgroundColorGreen.value = properties.backgroundColor.green;
|
||||
elTextBackgroundColorBlue.value = properties.backgroundColor.blue;
|
||||
}
|
||||
|
||||
if (properties.type != "Light") {
|
||||
elLightSection.style.display = 'none';
|
||||
} else {
|
||||
elLightSection.style.display = 'block';
|
||||
|
||||
elLightDiffuseRed.value = properties.diffuseColor.red;
|
||||
elLightDiffuseGreen.value = properties.diffuseColor.green;
|
||||
elLightDiffuseBlue.value = properties.diffuseColor.blue;
|
||||
|
||||
elLightAmbientRed.value = properties.ambientColor.red;
|
||||
elLightAmbientGreen.value = properties.ambientColor.green;
|
||||
elLightAmbientBlue.value = properties.ambientColor.blue;
|
||||
|
||||
elLightSpecularRed.value = properties.specularColor.red;
|
||||
elLightSpecularGreen.value = properties.specularColor.green;
|
||||
elLightSpecularBlue.value = properties.specularColor.blue;
|
||||
|
||||
elLightConstantAttenuation.value = properties.constantAttenuation;
|
||||
elLightLinearAttenuation.value = properties.linearAttenuation;
|
||||
elLightQuadraticAttenuation.value = properties.quadraticAttenuation;
|
||||
elLightExponent.value = properties.exponent;
|
||||
elLightCutoff.value = properties.cutoff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked'));
|
||||
elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible'));
|
||||
|
||||
var positionChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'position', elPositionX, elPositionY, elPositionZ);
|
||||
elPositionX.addEventListener('change', positionChangeFunction);
|
||||
elPositionY.addEventListener('change', positionChangeFunction);
|
||||
elPositionZ.addEventListener('change', positionChangeFunction);
|
||||
|
||||
var dimensionsChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'dimensions', elDimensionsX, elDimensionsY, elDimensionsZ);
|
||||
elDimensionsX.addEventListener('change', dimensionsChangeFunction);
|
||||
elDimensionsY.addEventListener('change', dimensionsChangeFunction);
|
||||
elDimensionsZ.addEventListener('change', dimensionsChangeFunction);
|
||||
|
||||
var registrationChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ);
|
||||
elRegistrationX.addEventListener('change', registrationChangeFunction);
|
||||
elRegistrationY.addEventListener('change', registrationChangeFunction);
|
||||
elRegistrationZ.addEventListener('change', registrationChangeFunction);
|
||||
|
||||
var velocityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'velocity', elLinearVelocityX, elLinearVelocityY, elLinearVelocityZ);
|
||||
elLinearVelocityX.addEventListener('change', velocityChangeFunction);
|
||||
elLinearVelocityY.addEventListener('change', velocityChangeFunction);
|
||||
elLinearVelocityZ.addEventListener('change', velocityChangeFunction);
|
||||
elLinearDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('damping'));
|
||||
|
||||
var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ);
|
||||
elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction);
|
||||
elAngularDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('angularDamping'))
|
||||
|
||||
var gravityChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'gravity', elGravityX, elGravityY, elGravityZ);
|
||||
elGravityX.addEventListener('change', gravityChangeFunction);
|
||||
elGravityY.addEventListener('change', gravityChangeFunction);
|
||||
elGravityZ.addEventListener('change', gravityChangeFunction);
|
||||
|
||||
elMass.addEventListener('change', createEmitNumberPropertyUpdateFunction('mass'));
|
||||
elIgnoreForCollisions.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ignoreForCollisions'));
|
||||
elCollisionsWillMove.addEventListener('change', createEmitCheckedPropertyUpdateFunction('collisionsWillMove'));
|
||||
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
|
||||
|
||||
var boxColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'color', elBoxColorRed, elBoxColorGreen, elBoxColorBlue);
|
||||
elBoxColorRed.addEventListener('change', boxColorChangeFunction);
|
||||
elBoxColorGreen.addEventListener('change', boxColorChangeFunction);
|
||||
elBoxColorBlue.addEventListener('change', boxColorChangeFunction);
|
||||
|
||||
elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight'));
|
||||
|
||||
var lightDiffuseChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'diffuseColor', elLightDiffuseRed, elLightDiffuseGreen, elLightDiffuseBlue);
|
||||
elLightDiffuseRed.addEventListener('change', lightDiffuseChangeFunction);
|
||||
elLightDiffuseGreen.addEventListener('change', lightDiffuseChangeFunction);
|
||||
elLightDiffuseBlue.addEventListener('change', lightDiffuseChangeFunction);
|
||||
|
||||
var lightAmbientChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'ambientColor', elLightAmbientRed, elLightAmbientGreen, elLightAmbientBlue);
|
||||
elLightAmbientRed.addEventListener('change', lightAmbientChangeFunction);
|
||||
elLightAmbientGreen.addEventListener('change', lightAmbientChangeFunction);
|
||||
elLightAmbientBlue.addEventListener('change', lightAmbientChangeFunction);
|
||||
|
||||
var lightSpecularChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'specularColor', elLightSpecularRed, elLightSpecularGreen, elLightSpecularBlue);
|
||||
elLightSpecularRed.addEventListener('change', lightSpecularChangeFunction);
|
||||
elLightSpecularGreen.addEventListener('change', lightSpecularChangeFunction);
|
||||
elLightSpecularBlue.addEventListener('change', lightSpecularChangeFunction);
|
||||
|
||||
elLightConstantAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('constantAttenuation'));
|
||||
elLightLinearAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('linearAttenuation'));
|
||||
elLightQuadraticAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('quadraticAttenuation'));
|
||||
elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent'));
|
||||
elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff'));
|
||||
|
||||
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
|
||||
elModelAnimationURL.addEventListener('change', createEmitTextPropertyUpdateFunction('animationURL'));
|
||||
elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying'));
|
||||
elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS'));
|
||||
elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex'));
|
||||
|
||||
elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text'));
|
||||
elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight'));
|
||||
|
||||
var textTextColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'textColor', elTextTextColorRed, elTextTextColorGreen, elTextTextColorBlue);
|
||||
elTextTextColorRed.addEventListener('change', textTextColorChangeFunction);
|
||||
elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction);
|
||||
elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction);
|
||||
|
||||
var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue);
|
||||
elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction);
|
||||
elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction);
|
||||
elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction);
|
||||
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div class="section-header">
|
||||
<label>Entity Properties</label>
|
||||
</div>
|
||||
<div id="properties" class="grid-section">
|
||||
<div class="property-section">
|
||||
<label>Type</label>
|
||||
<span>
|
||||
<label id="property-type"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Locked</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-locked">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Visible</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-visible">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Position</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-pos-x"></input>
|
||||
Y <input class="coord" type='number' id="property-pos-y"></input>
|
||||
Z <input class="coord" type='number' id="property-pos-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Registration</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-reg-x"></input>
|
||||
Y <input class="coord" type='number' id="property-reg-y"></input>
|
||||
Z <input class="coord" type='number' id="property-reg-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Width</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-dim-x"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Height</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-dim-y"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Depth</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-dim-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Linear</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-lvel-x"></input>
|
||||
Y <input class="coord" type='number' id="property-lvel-y"></input>
|
||||
Z <input class="coord" type='number' id="property-lvel-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Linear Damping</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-ldamping"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Angular</label>
|
||||
<span>
|
||||
Pitch <input class="coord" type='number' id="property-avel-x"></input>
|
||||
Roll <input class="coord" type='number' id="property-avel-z"></input>
|
||||
Yaw <input class="coord" type='number' id="property-avel-y"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Angular Damping</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-adamping"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Gravity</label>
|
||||
<span>
|
||||
X <input class="coord" type='number' id="property-grav-x"></input>
|
||||
Y <input class="coord" type='number' id="property-grav-y"></input>
|
||||
Z <input class="coord" type='number' id="property-grav-z"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Mass</label>
|
||||
<span>
|
||||
<input type='number' id="property-mass"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Ignore For Collisions</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-ignore-for-collisions"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Collisions Will Move</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-collisions-will-move"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Lifetime</label>
|
||||
<span>
|
||||
<input type='number' id="property-lifetime"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="box-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Color</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-box-red"></input>
|
||||
Green <input class="coord" type='number' id="property-box-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-box-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="model-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Model URL</label>
|
||||
<span>
|
||||
<input type="text" id="property-model-url"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation URL</label>
|
||||
<span>
|
||||
<input type="text" id="property-model-animation-url"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation Playing</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-model-animation-playing">
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation FPS</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-model-animation-fps"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Animation Frame</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-model-animation-frame"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="text-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Text</label>
|
||||
<span>
|
||||
<input type="text" id="property-text-text"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Line Height</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-text-line-height"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Text Color</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-text-text-color-red"></input>
|
||||
Green <input class="coord" type='number' id="property-text-text-color-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-text-text-color-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Background Color</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-text-background-color-red"></input>
|
||||
Green <input class="coord" type='number' id="property-text-background-color-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-text-background-color-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="light-section" class="multi-property-section">
|
||||
<div class="property-section">
|
||||
<label>Spot Light</label>
|
||||
<span>
|
||||
<input type='checkbox' id="property-light-spot-light">
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Diffuse</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-light-diffuse-red"></input>
|
||||
Green <input class="coord" type='number' id="property-light-diffuse-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-light-diffuse-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Ambient</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-light-ambient-red"></input>
|
||||
Green <input class="coord" type='number' id="property-light-ambient-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-light-ambient-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Specular</label>
|
||||
<span>
|
||||
Red <input class="coord" type='number' id="property-light-specular-red"></input>
|
||||
Green <input class="coord" type='number' id="property-light-specular-green"></input>
|
||||
Blue <input class="coord" type='number' id="property-light-specular-blue"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Constant Attenuation</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-constant-attenuation"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Linear Attenuation</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-linear-attenuation"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Quadratic Attenuation</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-quadratic-attenuation"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Exponent</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-exponent"></input>
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Cutoff (degrees)</label>
|
||||
<span>
|
||||
<input class="coord" type='number' id="property-light-cutoff"></input>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script>
|
||||
function loaded() {
|
||||
var gridColor = { red: 0, green: 0, blue: 0 };
|
||||
|
@ -17,13 +18,14 @@
|
|||
gridOn = document.getElementById("grid-on");
|
||||
snapToGrid = document.getElementById("snap-to-grid");
|
||||
hGridVisible = document.getElementById("horiz-grid-visible");
|
||||
|
||||
bMoveToSelection = document.getElementById("move-to-selection");
|
||||
bMoveToAvatar = document.getElementById("move-to-avatar");
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.origin) {
|
||||
|
||||
if (data.origin) {
|
||||
var origin = data.origin;
|
||||
posY.value = origin.y;
|
||||
}
|
||||
|
@ -69,6 +71,19 @@
|
|||
hGridVisible.addEventListener("change", emitUpdate);
|
||||
snapToGrid.addEventListener("change", emitUpdate);
|
||||
|
||||
bMoveToAvatar.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToAvatar",
|
||||
}));
|
||||
});
|
||||
bMoveToSelection.addEventListener("click", function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "action",
|
||||
action: "moveToSelection",
|
||||
}));
|
||||
});
|
||||
|
||||
var gridColorBox = document.getElementById('grid-color');
|
||||
|
||||
for (var i = 0; i < gridColors.length; i++) {
|
||||
|
@ -88,105 +103,63 @@
|
|||
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
* {
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
background: #DDD;
|
||||
font-family: Sans-Serif;
|
||||
font-size: 12px;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
input {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.input-left {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid black;
|
||||
background: blue;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.color-box.highlight {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: #AAA;
|
||||
border-bottom: 1px solid #CCC;
|
||||
}
|
||||
|
||||
.section-header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.grid-section {
|
||||
border-top: 1px solid #DDD;
|
||||
padding: 4px 0px 4px 20px;
|
||||
background: #DDD;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div class="section-header">
|
||||
<input type='checkbox' id="horiz-grid-visible">
|
||||
<label>Horizontal Grid</label>
|
||||
</div>
|
||||
|
||||
<div class="grid-section">
|
||||
|
||||
<label>Snap to grid</label>
|
||||
<div>
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='checkbox' id="snap-to-grid">
|
||||
<div class="property-section">
|
||||
<label>Visible</label>
|
||||
<span>
|
||||
<input type='checkbox' id="horiz-grid-visible">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Position (Y Axis)</label>
|
||||
<div id="horizontal-position">
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='number' id="horiz-y" class="number" value="0.0" step="0.1"></input>
|
||||
<div class="property-section">
|
||||
<label>Snap to grid</label>
|
||||
<span>
|
||||
<input type='checkbox' id="snap-to-grid">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Minor Grid Size</label>
|
||||
<div>
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='number' id="minor-spacing" min="0" step="0.01", ></input>
|
||||
<div id="horizontal-position" class="property-section">
|
||||
<label>Position (Y Axis)</label>
|
||||
<span>
|
||||
<input type='number' id="horiz-y" class="number" value="0.0" step="0.1"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Major Grid Every</label>
|
||||
<div>
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<input type='number' id="major-spacing" min="2" step="1", ></input>
|
||||
<div class="property-section">
|
||||
<label>Minor Grid Size</label>
|
||||
<span>
|
||||
<input type='number' id="minor-spacing" min="0" step="0.01", ></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label>Grid Color</label>
|
||||
<div id="grid-colors">
|
||||
<div class="input-left">
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<label>Major Grid Every</label>
|
||||
<span>
|
||||
<input type='number' id="major-spacing" min="2" step="1", ></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Grid Color</label>
|
||||
<span id="grid-colors"></span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<span>
|
||||
<input type="button" id="move-to-selection" value="Move to Selection">
|
||||
</span>
|
||||
</div>
|
||||
<div class="property-section">
|
||||
<span>
|
||||
<input type="button" id="move-to-avatar" value="Move to Avatar">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
95
examples/html/style.css
Normal file
95
examples/html/style.css
Normal file
|
@ -0,0 +1,95 @@
|
|||
* {
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
background-color: #efefef;
|
||||
font-family: Sans-Serif;
|
||||
font-size: 12px;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
input {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.input-left {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid black;
|
||||
margin: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.color-box.highlight {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: #AAA;
|
||||
border-bottom: 1px solid #CCC;
|
||||
background-color: #333333;
|
||||
color: #999;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.section-header label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.multi-property-section {
|
||||
}
|
||||
.property-section {
|
||||
display: block;
|
||||
margin: 10 10;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.property-section label {
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.property-section span {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.grid-section {
|
||||
border-top: 1px solid #DDD;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
cursor: pointer;
|
||||
background-color: #608e96;
|
||||
border-color: #608e96;
|
||||
border-radius: 5px;
|
||||
padding: 5px 10px;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin: 0 2px;
|
||||
margin-top: 5px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
input.coord {
|
||||
width: 6em;
|
||||
height: 2em;
|
||||
}
|
|
@ -41,15 +41,15 @@ EntityPropertyDialogBox = (function () {
|
|||
|
||||
array.push({ label: "Entity Type:" + properties.type, type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Locked:", value: properties.locked });
|
||||
array.push({ label: "Locked:", type: "checkbox", value: properties.locked });
|
||||
index++;
|
||||
|
||||
|
||||
if (properties.type == "Model") {
|
||||
array.push({ label: "Model URL:", value: properties.modelURL });
|
||||
index++;
|
||||
array.push({ label: "Animation URL:", value: properties.animationURL });
|
||||
index++;
|
||||
array.push({ label: "Animation is playing:", value: properties.animationIsPlaying });
|
||||
array.push({ label: "Animation is playing:", type: "checkbox", value: properties.animationIsPlaying });
|
||||
previousAnimationIsPlaying = properties.animationIsPlaying;
|
||||
index++;
|
||||
array.push({ label: "Animation FPS:", value: properties.animationFPS });
|
||||
|
@ -65,6 +65,30 @@ EntityPropertyDialogBox = (function () {
|
|||
array.push({ label: "Original Textures:\n" + properties.originalTextures, type: "header" });
|
||||
index++;
|
||||
}
|
||||
|
||||
if (properties.type == "Text") {
|
||||
array.push({ label: "Text:", value: properties.text });
|
||||
index++;
|
||||
array.push({ label: "Line Height:", value: properties.lineHeight });
|
||||
index++;
|
||||
array.push({ label: "Text Color:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Red:", value: properties.textColor.red });
|
||||
index++;
|
||||
array.push({ label: "Green:", value: properties.textColor.green });
|
||||
index++;
|
||||
array.push({ label: "Blue:", value: properties.textColor.blue });
|
||||
index++;
|
||||
array.push({ label: "Background Color:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "Red:", value: properties.backgroundColor.red });
|
||||
index++;
|
||||
array.push({ label: "Green:", value: properties.backgroundColor.green });
|
||||
index++;
|
||||
array.push({ label: "Blue:", value: properties.backgroundColor.blue });
|
||||
index++;
|
||||
}
|
||||
|
||||
array.push({ label: "Position:", type: "header" });
|
||||
index++;
|
||||
array.push({ label: "X:", value: properties.position.x.toFixed(decimals) });
|
||||
|
@ -140,20 +164,20 @@ EntityPropertyDialogBox = (function () {
|
|||
index++;
|
||||
array.push({ label: "Mass:", value: properties.mass.toFixed(decimals) });
|
||||
index++;
|
||||
array.push({ label: "Ignore for Collisions:", value: properties.ignoreForCollisions });
|
||||
array.push({ label: "Ignore for Collisions:", type: "checkbox", value: properties.ignoreForCollisions });
|
||||
index++;
|
||||
array.push({ label: "Collisions Will Move:", value: properties.collisionsWillMove });
|
||||
array.push({ label: "Collisions Will Move:", type: "checkbox", value: properties.collisionsWillMove });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Visible:", value: properties.visible });
|
||||
array.push({ label: "Visible:", type: "checkbox", value: properties.visible });
|
||||
index++;
|
||||
|
||||
array.push({ label: "Script:", value: properties.script });
|
||||
index++;
|
||||
|
||||
|
||||
if (properties.type == "Box" || properties.type == "Sphere") {
|
||||
array.push({ label: "Color:", type: "header" });
|
||||
index++;
|
||||
|
@ -225,7 +249,7 @@ EntityPropertyDialogBox = (function () {
|
|||
var rescaledX = peekX * peekRescale / 100.0;
|
||||
var rescaledY = peekY * peekRescale / 100.0;
|
||||
var rescaledZ = peekZ * peekRescale / 100.0;
|
||||
|
||||
|
||||
Window.reloadNonBlockingForm([
|
||||
{ value: rescaledX.toFixed(decimals), oldIndex: dimensionX },
|
||||
{ value: rescaledY.toFixed(decimals), oldIndex: dimensionY },
|
||||
|
@ -271,6 +295,22 @@ EntityPropertyDialogBox = (function () {
|
|||
properties.textures = array[index++].value;
|
||||
index++; // skip textureNames label
|
||||
}
|
||||
|
||||
if (properties.type == "Text") {
|
||||
properties.text = array[index++].value;
|
||||
properties.lineHeight = array[index++].value;
|
||||
|
||||
index++; // skip header
|
||||
properties.textColor.red = array[index++].value;
|
||||
properties.textColor.green = array[index++].value;
|
||||
properties.textColor.blue = array[index++].value;
|
||||
|
||||
index++; // skip header
|
||||
properties.backgroundColor.red = array[index++].value;
|
||||
properties.backgroundColor.green = array[index++].value;
|
||||
properties.backgroundColor.blue = array[index++].value;
|
||||
}
|
||||
|
||||
index++; // skip header
|
||||
properties.position.x = array[index++].value;
|
||||
properties.position.y = array[index++].value;
|
||||
|
@ -354,4 +394,3 @@ EntityPropertyDialogBox = (function () {
|
|||
return that;
|
||||
|
||||
}());
|
||||
|
||||
|
|
|
@ -23,12 +23,13 @@ SelectionManager = (function() {
|
|||
|
||||
that.savedProperties = {};
|
||||
|
||||
that.eventListener = null;
|
||||
that.selections = [];
|
||||
// These are selections that don't have a known ID yet
|
||||
that.pendingSelections = [];
|
||||
var pendingSelectionTimer = null;
|
||||
|
||||
var listeners = [];
|
||||
|
||||
that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||
that.localPosition = { x: 0, y: 0, z: 0 };
|
||||
that.localDimensions = { x: 0, y: 0, z: 0 };
|
||||
|
@ -46,8 +47,8 @@ SelectionManager = (function() {
|
|||
}
|
||||
};
|
||||
|
||||
that.setEventListener = function(func) {
|
||||
that.eventListener = func;
|
||||
that.addEventListener = function(func) {
|
||||
listeners.push(func);
|
||||
};
|
||||
|
||||
that.hasSelection = function() {
|
||||
|
@ -187,8 +188,12 @@ SelectionManager = (function() {
|
|||
SelectionDisplay.setSpaceMode(SPACE_WORLD);
|
||||
}
|
||||
|
||||
if (that.eventListener) {
|
||||
that.eventListener();
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
try {
|
||||
listeners[i]();
|
||||
} catch (e) {
|
||||
print("got exception");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ Grid = function(opts) {
|
|||
that.getMajorIncrement = function() { return minorGridSpacing * majorGridEvery; };
|
||||
|
||||
that.visible = false;
|
||||
that.enabled = false;
|
||||
|
||||
that.getOrigin = function() {
|
||||
return origin;
|
||||
|
@ -38,6 +39,11 @@ Grid = function(opts) {
|
|||
|
||||
that.getSnapToGrid = function() { return snapToGrid; };
|
||||
|
||||
that.setEnabled = function(enabled) {
|
||||
that.enabled = enabled;
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
that.setVisible = function(visible, noUpdate) {
|
||||
that.visible = visible;
|
||||
updateGrid();
|
||||
|
@ -127,7 +133,7 @@ Grid = function(opts) {
|
|||
function updateGrid() {
|
||||
Overlays.editOverlay(gridOverlay, {
|
||||
position: { x: origin.y, y: origin.y, z: -origin.y },
|
||||
visible: that.visible,
|
||||
visible: that.visible && that.enabled,
|
||||
minorGridWidth: minorGridSpacing,
|
||||
majorGridEvery: majorGridEvery,
|
||||
color: gridColor,
|
||||
|
@ -159,7 +165,7 @@ GridTool = function(opts) {
|
|||
var listeners = [];
|
||||
|
||||
var url = Script.resolvePath('html/gridControls.html');
|
||||
var webView = new WebWindow(url, 200, 280);
|
||||
var webView = new WebWindow('Grid', url, 200, 280);
|
||||
|
||||
horizontalGrid.addListener(function(data) {
|
||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||
|
@ -174,6 +180,15 @@ GridTool = function(opts) {
|
|||
for (var i = 0; i < listeners.length; i++) {
|
||||
listeners[i](data);
|
||||
}
|
||||
} else if (data.type == "action") {
|
||||
var action = data.action;
|
||||
if (action == "moveToAvatar") {
|
||||
grid.setPosition(MyAvatar.position);
|
||||
} else if (action == "moveToSelection") {
|
||||
var newPosition = selectionManager.worldPosition;
|
||||
newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 });
|
||||
grid.setPosition(newPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ Script.include("libraries/gridTool.js");
|
|||
var grid = Grid();
|
||||
gridTool = GridTool({ horizontalGrid: grid });
|
||||
|
||||
selectionManager.setEventListener(selectionDisplay.updateHandles);
|
||||
selectionManager.addEventListener(selectionDisplay.updateHandles);
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||
|
@ -54,14 +54,15 @@ var wantEntityGlow = false;
|
|||
|
||||
var SPAWN_DISTANCE = 1;
|
||||
var DEFAULT_DIMENSION = 0.20;
|
||||
var DEFAULT_TEXT_DIMENSION_X = 1.0;
|
||||
var DEFAULT_TEXT_DIMENSION_Y = 1.0;
|
||||
var DEFAULT_TEXT_DIMENSION_Z = 0.01;
|
||||
|
||||
var MENU_GRID_TOOL_ENABLED = 'Grid Tool';
|
||||
var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool";
|
||||
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
|
||||
|
||||
var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled";
|
||||
var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
|
||||
var SETTING_GRID_TOOL_ENABLED = 'GridToolEnabled';
|
||||
|
||||
var modelURLs = [
|
||||
HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx",
|
||||
|
@ -86,6 +87,7 @@ var toolBar = (function () {
|
|||
newCubeButton,
|
||||
newSphereButton,
|
||||
newLightButton,
|
||||
newTextButton,
|
||||
browseModelsButton,
|
||||
loadURLMenuItem,
|
||||
loadFileMenuItem,
|
||||
|
@ -182,6 +184,16 @@ var toolBar = (function () {
|
|||
visible: true
|
||||
});
|
||||
|
||||
newTextButton = toolBar.addTool({
|
||||
//imageURL: toolIconUrl + "add-text.svg",
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/add-text.svg", // temporarily
|
||||
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
|
||||
width: toolWidth,
|
||||
height: toolHeight,
|
||||
alpha: 0.9,
|
||||
visible: true
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function toggleNewModelButton(active) {
|
||||
|
@ -272,11 +284,15 @@ var toolBar = (function () {
|
|||
isActive = !isActive;
|
||||
if (!isActive) {
|
||||
gridTool.setVisible(false);
|
||||
grid.setEnabled(false);
|
||||
propertiesTool.setVisible(false);
|
||||
selectionManager.clearSelections();
|
||||
cameraManager.disable();
|
||||
} else {
|
||||
cameraManager.enable();
|
||||
gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED));
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -355,7 +371,7 @@ var toolBar = (function () {
|
|||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
Entities.addEntity({
|
||||
type: "Light",
|
||||
position: position,
|
||||
dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION },
|
||||
|
@ -376,6 +392,24 @@ var toolBar = (function () {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (newTextButton === toolBar.clicked(clickedOverlay)) {
|
||||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
type: "Text",
|
||||
position: position,
|
||||
dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z },
|
||||
backgroundColor: { red: 0, green: 0, blue: 0 },
|
||||
textColor: { red: 255, green: 255, blue: 255 },
|
||||
text: "some text",
|
||||
lineHight: "0.1"
|
||||
});
|
||||
} else {
|
||||
print("Can't create box: Text would be out of bounds.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
@ -608,10 +642,6 @@ function setupModelMenus() {
|
|||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" });
|
||||
Menu.addMenuItem({ menuName: "Developer", menuItemName: "Debug Ryans Rotation Problems", isCheckable: true });
|
||||
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_GRID_TOOL_ENABLED, afterItem: "Edit Entities Help...", isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_GRID_TOOL_ENABLED) == 'true'});
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_INSPECT_TOOL_ENABLED, afterItem: MENU_GRID_TOOL_ENABLED,
|
||||
isCheckable: true, isChecked: Settings.getValue(SETTING_INSPECT_TOOL_ENABLED) == "true" });
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED,
|
||||
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
|
||||
}
|
||||
|
@ -636,8 +666,6 @@ function cleanupModelMenus() {
|
|||
Menu.removeMenuItem("File", "Import Models");
|
||||
Menu.removeMenuItem("Developer", "Debug Ryans Rotation Problems");
|
||||
|
||||
Settings.setValue(SETTING_GRID_TOOL_ENABLED, Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED));
|
||||
Menu.removeMenuItem("View", MENU_GRID_TOOL_ENABLED);
|
||||
Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED);
|
||||
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
|
||||
}
|
||||
|
@ -714,7 +742,7 @@ function handeMenuEvent(menuItem) {
|
|||
var selectedModel = form[0].value;
|
||||
if (form[1].value == "Properties") {
|
||||
editModelID = selectedModel;
|
||||
showPropertiesForm(editModelID);
|
||||
entityPropertyDialogBox.openDialog(editModelID);
|
||||
} else if (form[1].value == "Delete") {
|
||||
Entities.deleteEntity(selectedModel);
|
||||
} else if (form[1].value == "Teleport") {
|
||||
|
@ -749,10 +777,6 @@ function handeMenuEvent(menuItem) {
|
|||
}
|
||||
} else if (menuItem == "Import Models") {
|
||||
modelImporter.doImport();
|
||||
} else if (menuItem == MENU_GRID_TOOL_ENABLED) {
|
||||
if (isActive) {
|
||||
gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED));
|
||||
}
|
||||
}
|
||||
tooltip.show(false);
|
||||
}
|
||||
|
@ -911,3 +935,43 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
|
|||
}
|
||||
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
|
||||
}
|
||||
|
||||
PropertiesTool = function(opts) {
|
||||
var that = {};
|
||||
|
||||
var url = Script.resolvePath('html/entityProperties.html');
|
||||
var webView = new WebWindow('Entity Properties', url, 200, 280);
|
||||
|
||||
var visible = false;
|
||||
|
||||
webView.setVisible(visible);
|
||||
|
||||
that.setVisible = function(newVisible) {
|
||||
visible = newVisible;
|
||||
webView.setVisible(visible);
|
||||
};
|
||||
|
||||
selectionManager.addEventListener(function() {
|
||||
data = {
|
||||
type: 'update',
|
||||
};
|
||||
if (selectionManager.hasSelection()) {
|
||||
data.properties = Entities.getEntityProperties(selectionManager.selections[0]);
|
||||
}
|
||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||
});
|
||||
|
||||
webView.eventBridge.webEventReceived.connect(function(data) {
|
||||
print(data);
|
||||
data = JSON.parse(data);
|
||||
if (data.type == "update") {
|
||||
Entities.editEntity(selectionManager.selections[0], data.properties);
|
||||
selectionManager._update();
|
||||
}
|
||||
});
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
propertiesTool = PropertiesTool();
|
||||
|
||||
|
|
|
@ -194,20 +194,23 @@ print("Cube overlay color =\n"
|
|||
+ "green: " + cubeColor.green + "\n"
|
||||
+ "blue: " + cubeColor.blue
|
||||
);
|
||||
var modelOverlayProperties = {
|
||||
textures: {
|
||||
filename1: "http://url1",
|
||||
filename2: "http://url2"
|
||||
}
|
||||
}
|
||||
var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties);
|
||||
var textures = Overlays.getProperty(modelOverlay, "textures");
|
||||
var textureValues = "";
|
||||
for (key in textures) {
|
||||
textureValues += "\n" + key + ": " + textures[key];
|
||||
}
|
||||
print("Model overlay textures =" + textureValues);
|
||||
Overlays.deleteOverlay(modelOverlay);
|
||||
|
||||
// This model overlay example causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL()
|
||||
//var modelOverlayProperties = {
|
||||
// textures: {
|
||||
// filename1: HIFI_PUBLIC_BUCKET + "images/testing-swatches.svg",
|
||||
// filename2: HIFI_PUBLIC_BUCKET + "images/hifi-interface-tools.svg"
|
||||
// }
|
||||
//}
|
||||
//var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties);
|
||||
//var textures = Overlays.getProperty(modelOverlay, "textures");
|
||||
//var textureValues = "";
|
||||
//for (key in textures) {
|
||||
// textureValues += "\n" + key + ": " + textures[key];
|
||||
//}
|
||||
//print("Model overlay textures =" + textureValues);
|
||||
//Overlays.deleteOverlay(modelOverlay);
|
||||
|
||||
print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined
|
||||
|
||||
// When our script shuts down, we should clean up all of our overlays
|
||||
|
|
262
examples/playChess.js
Normal file
262
examples/playChess.js
Normal file
|
@ -0,0 +1,262 @@
|
|||
//
|
||||
// playChess.js
|
||||
// examples
|
||||
//
|
||||
// Created by Clement Brisset on 11/08/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
|
||||
|
||||
var gamePosition = { x: 1.0, y: 1.0, z: 1.0 };
|
||||
var gameSize = 1.0;
|
||||
|
||||
// Script namespace
|
||||
var extraDebug = extraDebug || true;
|
||||
var ChessGame = ChessGame || {
|
||||
BOARD: {
|
||||
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/chess/Board.fbx",
|
||||
dimensions: { x: 773.191, y: 20.010, z: 773.191 },
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
|
||||
numTiles: 10.0
|
||||
},
|
||||
KING: 0, QUEEN: 1, BISHOP: 2, KNIGHT: 3, ROOK: 4, PAWN: 5,
|
||||
|
||||
board: null,
|
||||
pieces: new Array()
|
||||
};
|
||||
|
||||
ChessGame.getPieceInfo = function(type, isWhite) {
|
||||
var info = {
|
||||
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/chess/",
|
||||
dimensions: { x: 1.0, y: 1.0, z: 1.0 },
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0)
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case ChessGame.KING:
|
||||
info.modelURL += "King";
|
||||
info.dimensions = { x: 110.496, y: 306.713, z: 110.496 };
|
||||
info.rotation = Quat.fromPitchYawRollDegrees(0, 90, 0);
|
||||
break;
|
||||
case ChessGame.QUEEN:
|
||||
info.modelURL += "Queen";
|
||||
info.dimensions = { x: 110.496, y: 257.459, z: 110.496 };
|
||||
break;
|
||||
case ChessGame.BISHOP:
|
||||
info.modelURL += "Bishop";
|
||||
info.dimensions = { x: 102.002, y: 213.941, z: 102.002 };
|
||||
info.rotation = Quat.fromPitchYawRollDegrees(0, 90, 0);
|
||||
break;
|
||||
case ChessGame.KNIGHT:
|
||||
info.modelURL += "Knight";
|
||||
info.dimensions = { x: 95.602, y: 186.939, z: 95.602 };
|
||||
info.rotation = Quat.fromPitchYawRollDegrees(0, 180, 0);
|
||||
break;
|
||||
case ChessGame.ROOK:
|
||||
info.modelURL += "Rook";
|
||||
info.dimensions = { x: 101.024, y: 167.523, z: 101.024 };
|
||||
break;
|
||||
case ChessGame.PAWN:
|
||||
info.modelURL += "Pawn";
|
||||
info.dimensions = { x: 93.317, y: 138.747, z: 93.317 };
|
||||
break;
|
||||
}
|
||||
info.modelURL += ((isWhite) ? "_White" : "_Black") + ".fbx"
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
// Board class
|
||||
ChessGame.Board = (function(position, scale) {
|
||||
this.dimensions = Vec3.multiply(1.0 / ChessGame.BOARD.dimensions.x, ChessGame.BOARD.dimensions); // 1 by 1
|
||||
this.dimensions = Vec3.multiply(scale, this.dimensions); // scale by scale
|
||||
this.position = position
|
||||
this.tileSize = scale / ChessGame.BOARD.numTiles;
|
||||
|
||||
this.userDataObject = {
|
||||
firstTile: this.tilePosition(1, 1),
|
||||
tileSize: this.tileSize,
|
||||
whitesDeadPieces: this.tilePosition(0,0),
|
||||
blacksDeadPieces: this.tilePosition(9,9)
|
||||
}
|
||||
this.entityProperties = {
|
||||
type: "Model",
|
||||
modelURL: ChessGame.BOARD.modelURL,
|
||||
position: this.position,
|
||||
dimensions: this.dimensions,
|
||||
userData: this.buildUserDataString()
|
||||
}
|
||||
this.entity = null;
|
||||
});
|
||||
// Returns the top center point of tile i,j
|
||||
ChessGame.Board.prototype.tilePosition = function(i, j) {
|
||||
if (!(this.position || this.dimensions || this.tileSize || ChessGame.BOARD.numTiles)) {
|
||||
print("ChessGame.Board.prototype.tilePosition(): Called before proper initialisation, bailing.");
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
x: this.position.x + (i - ChessGame.BOARD.numTiles / 2.0 + 0.5) * this.tileSize,
|
||||
y: this.position.y + this.dimensions.y / 2.0,
|
||||
z: this.position.z + (j - ChessGame.BOARD.numTiles / 2.0 + 0.5) * this.tileSize
|
||||
};
|
||||
}
|
||||
// Checks the color of the tile
|
||||
ChessGame.Board.prototype.isWhite = function(i, j) {
|
||||
return (i + j) % 2 != 0;
|
||||
}
|
||||
// Build the user data string
|
||||
ChessGame.Board.prototype.buildUserDataString = function() {
|
||||
return JSON.stringify(this.userDataObject);
|
||||
}
|
||||
// Updates the user data stored by the board
|
||||
ChessGame.Board.prototype.updateUserData = function() {
|
||||
var userDataString = this.buildUserDataString();
|
||||
this.entityProperties.userData = userDataString;
|
||||
Entities.editEntity(this.entity, { userData: userDataString });
|
||||
}
|
||||
// Spawns the board using entities
|
||||
ChessGame.Board.prototype.spawn = function() {
|
||||
if (extraDebug) {
|
||||
print("Spawning board...");
|
||||
}
|
||||
this.entity = Entities.addEntity(this.entityProperties);
|
||||
print("Board spawned");
|
||||
}
|
||||
// Cleans up the entities of the board
|
||||
ChessGame.Board.prototype.cleanup = function() {
|
||||
if (extraDebug) {
|
||||
print("Cleaning up board...");
|
||||
}
|
||||
Entities.deleteEntity(this.entity);
|
||||
print("Board cleaned up");
|
||||
}
|
||||
|
||||
// Piece class
|
||||
ChessGame.Piece = (function(position, dimensions, url, rotation) {
|
||||
this.dimensions = dimensions;
|
||||
this.position = position;
|
||||
this.position.y += this.dimensions.y / 2.0;
|
||||
|
||||
this.entityProperties = {
|
||||
type: "Model",
|
||||
position: this.position,
|
||||
rotation: rotation,
|
||||
dimensions: this.dimensions,
|
||||
modelURL: url,
|
||||
/**/
|
||||
script: "https://s3.amazonaws.com/hifi-public/scripts/entityScripts/chessPiece.js",
|
||||
/*/
|
||||
script: "file:/Users/clement/hifi/examples/entityScripts/chessPiece.js",
|
||||
/**/
|
||||
userData: this.buildUserDataString()
|
||||
}
|
||||
this.entity = null;
|
||||
});
|
||||
// Build the user data string
|
||||
ChessGame.Piece.prototype.buildUserDataString = function() {
|
||||
if (!(ChessGame.board !== null || ChessGame.board.entity.isKnownID)) {
|
||||
print("ChessGame.Piece.prototype.buildUserDataString(): Called before proper initialization, bailing.");
|
||||
return null;
|
||||
}
|
||||
var userDataObject = {
|
||||
boardID: ChessGame.board.entity,
|
||||
};
|
||||
return JSON.stringify(userDataObject);
|
||||
}
|
||||
// Spawns the piece
|
||||
ChessGame.Piece.prototype.spawn = function() {
|
||||
this.entity = Entities.addEntity(this.entityProperties);
|
||||
}
|
||||
// Cleans up the piece
|
||||
ChessGame.Piece.prototype.cleanup = function() {
|
||||
Entities.deleteEntity(this.entity);
|
||||
}
|
||||
ChessGame.makePiece = function(piece, i, j, isWhite) {
|
||||
var info = ChessGame.getPieceInfo(piece, isWhite);
|
||||
var url = info.modelURL;
|
||||
var size = Vec3.multiply(0.5 * (1.0 / ChessGame.BOARD.dimensions.x), info.dimensions);
|
||||
var rotation = (isWhite) ? info.rotation
|
||||
: Quat.multiply(Quat.fromPitchYawRollDegrees(0, 180, 0),
|
||||
info.rotation);
|
||||
var position = ChessGame.board.tilePosition(i, j);
|
||||
|
||||
var piece = new ChessGame.Piece(position, size, url, rotation);
|
||||
piece.spawn();
|
||||
ChessGame.pieces.push(piece);
|
||||
return piece;
|
||||
}
|
||||
|
||||
ChessGame.scriptStarting = function() {
|
||||
print("playChess.js started");
|
||||
gamePosition = Vec3.sum(MyAvatar.position,
|
||||
Vec3.multiplyQbyV(MyAvatar.orientation,
|
||||
{ x: 0, y: 0, z: -1 }));
|
||||
// Setup board
|
||||
ChessGame.board = new ChessGame.Board(gamePosition, gameSize);
|
||||
ChessGame.board.spawn();
|
||||
}
|
||||
|
||||
ChessGame.update = function() {
|
||||
ChessGame.board.entity = Entities.identifyEntity(ChessGame.board.entity);
|
||||
|
||||
if (ChessGame.board.entity.isKnownID && ChessGame.pieces.length == 0) {
|
||||
// Setup white pieces
|
||||
var isWhite = true;
|
||||
var row = 1;
|
||||
// King
|
||||
ChessGame.makePiece(ChessGame.KING, row, 5, isWhite);
|
||||
// Queen
|
||||
ChessGame.makePiece(ChessGame.QUEEN, row, 4, isWhite);
|
||||
// Bishop
|
||||
ChessGame.makePiece(ChessGame.BISHOP, row, 3, isWhite);
|
||||
ChessGame.makePiece(ChessGame.BISHOP, row, 6, isWhite);
|
||||
// Knight
|
||||
ChessGame.makePiece(ChessGame.KNIGHT, row, 2, isWhite);
|
||||
ChessGame.makePiece(ChessGame.KNIGHT, row, 7, isWhite);
|
||||
// Rook
|
||||
ChessGame.makePiece(ChessGame.ROOK, row, 1, isWhite);
|
||||
ChessGame.makePiece(ChessGame.ROOK, row, 8, isWhite);
|
||||
for(var j = 1; j <= 8; j++) {
|
||||
ChessGame.makePiece(ChessGame.PAWN, row + 1, j, isWhite);
|
||||
}
|
||||
|
||||
// Setup black pieces
|
||||
isWhite = false;
|
||||
row = 8;
|
||||
// King
|
||||
ChessGame.makePiece(ChessGame.KING, row, 5, isWhite);
|
||||
// Queen
|
||||
ChessGame.makePiece(ChessGame.QUEEN, row, 4, isWhite);
|
||||
// Bishop
|
||||
ChessGame.makePiece(ChessGame.BISHOP, row, 3, isWhite);
|
||||
ChessGame.makePiece(ChessGame.BISHOP, row, 6, isWhite);
|
||||
// Knight
|
||||
ChessGame.makePiece(ChessGame.KNIGHT, row, 2, isWhite);
|
||||
ChessGame.makePiece(ChessGame.KNIGHT, row, 7, isWhite);
|
||||
// Rook
|
||||
ChessGame.makePiece(ChessGame.ROOK, row, 1, isWhite);
|
||||
ChessGame.makePiece(ChessGame.ROOK, row, 8, isWhite);
|
||||
for(var j = 1; j <= 8; j++) {
|
||||
ChessGame.makePiece(ChessGame.PAWN, row - 1, j, isWhite);
|
||||
}
|
||||
Script.update.disconnect(ChessGame.update);
|
||||
}
|
||||
}
|
||||
|
||||
ChessGame.scriptEnding = function() {
|
||||
// Cleaning up board
|
||||
ChessGame.board.cleanup();
|
||||
|
||||
// Cleaning up pieces
|
||||
for(var i in ChessGame.pieces) {
|
||||
ChessGame.pieces[i].cleanup();
|
||||
}
|
||||
|
||||
print("playChess.js finished");
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(ChessGame.scriptEnding);
|
||||
Script.update.connect(ChessGame.update);
|
||||
ChessGame.scriptStarting();
|
|
@ -1,6 +1,6 @@
|
|||
filename=defaultAvatar/body.fbx
|
||||
texdir=defaultAvatar
|
||||
scale=130
|
||||
scale=8.666
|
||||
joint = jointRoot = jointRoot
|
||||
joint = jointLean = jointSpine
|
||||
joint = jointNeck = jointNeck
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
name= defaultAvatar_head
|
||||
filename=defaultAvatar/head.fbx
|
||||
texdir=defaultAvatar
|
||||
scale=80
|
||||
scale=5.333
|
||||
rx=0
|
||||
ry=0
|
||||
rz=0
|
||||
|
|
|
@ -125,7 +125,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message);
|
||||
|
||||
if (!logMessage.isEmpty()) {
|
||||
Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage));
|
||||
Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage + "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,6 +377,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
// enable mouse tracking; otherwise, we only get drag events
|
||||
_glWidget->setMouseTracking(true);
|
||||
|
||||
_toolWindow = new ToolWindow();
|
||||
_toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint);
|
||||
_toolWindow->setWindowTitle("Tools");
|
||||
|
||||
// initialization continues in initializeGL when OpenGL context is ready
|
||||
|
||||
// Tell our voxel edit sender about our known jurisdictions
|
||||
|
@ -1555,6 +1559,8 @@ void Application::checkBandwidthMeterClick() {
|
|||
// ... to be called upon button release
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::UserInterface) &&
|
||||
glm::compMax(glm::abs(glm::ivec2(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY)))
|
||||
<= BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH
|
||||
&& _bandwidthMeter.isWithinArea(_mouseX, _mouseY, _glWidget->width(), _glWidget->height())) {
|
||||
|
@ -2890,7 +2896,7 @@ QImage Application::renderAvatarBillboard() {
|
|||
return image;
|
||||
}
|
||||
|
||||
void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||
void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderArgs::RenderSide renderSide) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
PerformanceTimer perfTimer("display");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
|
||||
|
@ -3037,7 +3043,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
PerformanceTimer perfTimer("entities");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... entities...");
|
||||
_entities.render();
|
||||
_entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide);
|
||||
}
|
||||
|
||||
// render JS/scriptable overlays
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
#include "ui/overlays/Overlays.h"
|
||||
#include "ui/ApplicationOverlay.h"
|
||||
#include "ui/RunningScriptsWidget.h"
|
||||
#include "ui/ToolWindow.h"
|
||||
#include "ui/VoxelImportDialog.h"
|
||||
#include "voxels/VoxelFade.h"
|
||||
#include "voxels/VoxelHideShowThread.h"
|
||||
|
@ -115,15 +116,15 @@ static const float NODE_KILLED_BLUE = 0.0f;
|
|||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
||||
|
||||
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
|
||||
static const float BILLBOARD_DISTANCE = 5.0f; // meters
|
||||
static const float BILLBOARD_DISTANCE = 5.56f; // meters
|
||||
|
||||
static const int MIRROR_VIEW_TOP_PADDING = 5;
|
||||
static const int MIRROR_VIEW_LEFT_PADDING = 10;
|
||||
static const int MIRROR_VIEW_WIDTH = 265;
|
||||
static const int MIRROR_VIEW_HEIGHT = 215;
|
||||
static const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
|
||||
static const float MIRROR_REARVIEW_DISTANCE = 0.65f;
|
||||
static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
|
||||
static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f;
|
||||
static const float MIRROR_REARVIEW_DISTANCE = 0.722f;
|
||||
static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f;
|
||||
static const float MIRROR_FIELD_OF_VIEW = 30.0f;
|
||||
|
||||
static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS_PER_SECOND;
|
||||
|
@ -247,6 +248,8 @@ public:
|
|||
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
||||
void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
|
||||
|
||||
ToolWindow* getToolWindow() { return _toolWindow ; }
|
||||
|
||||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||
AnimationCache* getAnimationCache() { return &_animationCache; }
|
||||
TextureCache* getTextureCache() { return &_textureCache; }
|
||||
|
@ -263,7 +266,7 @@ public:
|
|||
|
||||
QImage renderAvatarBillboard();
|
||||
|
||||
void displaySide(Camera& whichCamera, bool selfAvatarOnly = false);
|
||||
void displaySide(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO);
|
||||
|
||||
/// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as
|
||||
/// the view matrix translation.
|
||||
|
@ -461,6 +464,8 @@ private:
|
|||
MainWindow* _window;
|
||||
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
||||
|
||||
ToolWindow* _toolWindow;
|
||||
|
||||
BandwidthMeter _bandwidthMeter;
|
||||
|
||||
QThread* _nodeThread;
|
||||
|
|
|
@ -99,6 +99,7 @@ Audio::Audio(QObject* parent) :
|
|||
_muted(false),
|
||||
_reverb(false),
|
||||
_reverbOptions(&_scriptReverbOptions),
|
||||
_gverbLocal(NULL),
|
||||
_gverb(NULL),
|
||||
_iconColor(1.0f),
|
||||
_iconPulseTimeReference(usecTimestampNow()),
|
||||
|
@ -504,12 +505,23 @@ bool Audio::switchOutputToAudioDevice(const QString& outputDeviceName) {
|
|||
|
||||
void Audio::initGverb() {
|
||||
// Initialize a new gverb instance
|
||||
_gverbLocal = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
||||
_reverbOptions->getTailLevel());
|
||||
_gverb = gverb_new(_outputFormat.sampleRate(), _reverbOptions->getMaxRoomSize(), _reverbOptions->getRoomSize(),
|
||||
_reverbOptions->getReverbTime(), _reverbOptions->getDamping(), _reverbOptions->getSpread(),
|
||||
_reverbOptions->getInputBandwidth(), _reverbOptions->getEarlyLevel(),
|
||||
_reverbOptions->getTailLevel());
|
||||
|
||||
|
||||
// Configure the instance (these functions are not super well named - they actually set several internal variables)
|
||||
gverb_set_roomsize(_gverbLocal, _reverbOptions->getRoomSize());
|
||||
gverb_set_revtime(_gverbLocal, _reverbOptions->getReverbTime());
|
||||
gverb_set_damping(_gverbLocal, _reverbOptions->getDamping());
|
||||
gverb_set_inputbandwidth(_gverbLocal, _reverbOptions->getInputBandwidth());
|
||||
gverb_set_earlylevel(_gverbLocal, DB_CO(_reverbOptions->getEarlyLevel()));
|
||||
gverb_set_taillevel(_gverbLocal, DB_CO(_reverbOptions->getTailLevel()));
|
||||
|
||||
gverb_set_roomsize(_gverb, _reverbOptions->getRoomSize());
|
||||
gverb_set_revtime(_gverb, _reverbOptions->getReverbTime());
|
||||
gverb_set_damping(_gverb, _reverbOptions->getDamping());
|
||||
|
@ -565,25 +577,27 @@ void Audio::setReverbOptions(const AudioEffectOptions* options) {
|
|||
}
|
||||
}
|
||||
|
||||
void Audio::addReverb(int16_t* samplesData, int numSamples, QAudioFormat& audioFormat) {
|
||||
float dryFraction = DB_CO(_reverbOptions->getDryLevel());
|
||||
void Audio::addReverb(ty_gverb* gverb, int16_t* samplesData, int numSamples, QAudioFormat& audioFormat, bool noEcho) {
|
||||
float wetFraction = DB_CO(_reverbOptions->getWetLevel());
|
||||
float dryFraction = (noEcho) ? 0.0f : (1.0f - wetFraction);
|
||||
|
||||
float lValue,rValue;
|
||||
for (int sample = 0; sample < numSamples; sample += audioFormat.channelCount()) {
|
||||
// Run GVerb
|
||||
float value = (float)samplesData[sample];
|
||||
gverb_do(_gverb, value, &lValue, &rValue);
|
||||
gverb_do(gverb, value, &lValue, &rValue);
|
||||
|
||||
// Mix, accounting for clipping, the left and right channels. Ignore the rest.
|
||||
for (int j = sample; j < sample + audioFormat.channelCount(); j++) {
|
||||
if (j == sample) {
|
||||
// left channel
|
||||
int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
int lResult = glm::clamp((int)(samplesData[j] * dryFraction + lValue * wetFraction),
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
samplesData[j] = (int16_t)lResult;
|
||||
} else if (j == (sample + 1)) {
|
||||
// right channel
|
||||
int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction), MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
int rResult = glm::clamp((int)(samplesData[j] * dryFraction + rValue * wetFraction),
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
samplesData[j] = (int16_t)rResult;
|
||||
} else {
|
||||
// ignore channels above 2
|
||||
|
@ -622,23 +636,10 @@ void Audio::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
|
|||
}
|
||||
|
||||
if (hasLocalReverb) {
|
||||
QByteArray loopbackCopy;
|
||||
if (!hasEcho) {
|
||||
loopbackCopy = loopBackByteArray;
|
||||
}
|
||||
|
||||
int16_t* loopbackSamples = reinterpret_cast<int16_t*>(loopBackByteArray.data());
|
||||
int numLoopbackSamples = loopBackByteArray.size() / sizeof(int16_t);
|
||||
updateGverbOptions();
|
||||
addReverb(loopbackSamples, numLoopbackSamples, _outputFormat);
|
||||
|
||||
if (!hasEcho) {
|
||||
int16_t* loopbackCopySamples = reinterpret_cast<int16_t*>(loopbackCopy.data());
|
||||
for (int i = 0; i < numLoopbackSamples; ++i) {
|
||||
loopbackSamples[i] = glm::clamp((int)loopbackSamples[i] - loopbackCopySamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
}
|
||||
}
|
||||
addReverb(_gverbLocal, loopbackSamples, numLoopbackSamples, _outputFormat, !hasEcho);
|
||||
}
|
||||
|
||||
if (_loopbackOutputDevice) {
|
||||
|
@ -1029,7 +1030,7 @@ void Audio::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& ou
|
|||
|
||||
if(_reverb || _receivedAudioStream.hasReverb()) {
|
||||
updateGverbOptions();
|
||||
addReverb((int16_t*)outputBuffer.data(), numDeviceOutputSamples, _outputFormat);
|
||||
addReverb(_gverb, (int16_t*)outputBuffer.data(), numDeviceOutputSamples, _outputFormat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -248,6 +248,7 @@ private:
|
|||
AudioEffectOptions _scriptReverbOptions;
|
||||
AudioEffectOptions _zoneReverbOptions;
|
||||
AudioEffectOptions* _reverbOptions;
|
||||
ty_gverb* _gverbLocal;
|
||||
ty_gverb* _gverb;
|
||||
GLuint _micTextureId;
|
||||
GLuint _muteTextureId;
|
||||
|
@ -269,7 +270,7 @@ private:
|
|||
// Adds Reverb
|
||||
void initGverb();
|
||||
void updateGverbOptions();
|
||||
void addReverb(int16_t* samples, int numSamples, QAudioFormat& format);
|
||||
void addReverb(ty_gverb* gverb, int16_t* samples, int numSamples, QAudioFormat& format, bool noEcho = false);
|
||||
|
||||
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
||||
|
||||
|
|
|
@ -141,17 +141,29 @@ void DatagramProcessor::processDatagrams() {
|
|||
AccountManager::getInstance().checkAndSignalForAccessToken();
|
||||
break;
|
||||
}
|
||||
case PacketTypeNoisyMute:
|
||||
case PacketTypeMuteEnvironment: {
|
||||
glm::vec3 position;
|
||||
float radius;
|
||||
bool mute = !Application::getInstance()->getAudio()->getMuted();
|
||||
|
||||
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment);
|
||||
memcpy(&position, incomingPacket.constData() + headerSize, sizeof(glm::vec3));
|
||||
memcpy(&radius, incomingPacket.constData() + headerSize + sizeof(glm::vec3), sizeof(float));
|
||||
if (incomingType == PacketTypeMuteEnvironment) {
|
||||
glm::vec3 position;
|
||||
float radius, distance;
|
||||
|
||||
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(Application::getInstance()->getAvatar()->getPosition(), position);
|
||||
|
||||
mute = mute && (distance < radius);
|
||||
}
|
||||
|
||||
if (glm::distance(Application::getInstance()->getAvatar()->getPosition(), position) < radius
|
||||
&& !Application::getInstance()->getAudio()->getMuted()) {
|
||||
if (mute) {
|
||||
Application::getInstance()->getAudio()->toggleMute();
|
||||
if (incomingType == PacketTypeMuteEnvironment) {
|
||||
AudioScriptingInterface::getInstance().environmentMuted();
|
||||
} else {
|
||||
AudioScriptingInterface::getInstance().mutedByMixer();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ void FileLogger::addMessage(QString message) {
|
|||
QFile file(_fileName);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
|
||||
QTextStream out(&file);
|
||||
out << message << "\n";
|
||||
out << message;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,6 +247,12 @@ Menu::Menu() :
|
|||
_chatWindow = new ChatWindow(Application::getInstance()->getWindow());
|
||||
#endif
|
||||
|
||||
addActionToQMenuAndActionHash(toolsMenu,
|
||||
MenuOption::ToolWindow,
|
||||
Qt::CTRL | Qt::ALT | Qt::Key_T,
|
||||
this,
|
||||
SLOT(toggleToolWindow()));
|
||||
|
||||
addActionToQMenuAndActionHash(toolsMenu,
|
||||
MenuOption::Console,
|
||||
Qt::CTRL | Qt::ALT | Qt::Key_J,
|
||||
|
@ -1464,6 +1470,11 @@ void Menu::toggleConsole() {
|
|||
_jsConsole->setVisible(!_jsConsole->isVisible());
|
||||
}
|
||||
|
||||
void Menu::toggleToolWindow() {
|
||||
QMainWindow* toolWindow = Application::getInstance()->getToolWindow();
|
||||
toolWindow->setVisible(!toolWindow->isVisible());
|
||||
}
|
||||
|
||||
void Menu::audioMuteToggled() {
|
||||
QAction *muteAction = _actionHash.value(MenuOption::MuteAudio);
|
||||
if (muteAction) {
|
||||
|
|
|
@ -224,6 +224,7 @@ private slots:
|
|||
void showScriptEditor();
|
||||
void showChat();
|
||||
void toggleConsole();
|
||||
void toggleToolWindow();
|
||||
void toggleChat();
|
||||
void audioMuteToggled();
|
||||
void displayNameLocationResponse(const QString& errorString);
|
||||
|
@ -490,6 +491,7 @@ namespace MenuOption {
|
|||
const QString StringHair = "String Hair";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
const QString TestPing = "Test Ping";
|
||||
const QString ToolWindow = "Tool Window";
|
||||
const QString TransmitterDrive = "Transmitter Drive";
|
||||
const QString TurnWithHead = "Turn using Head";
|
||||
const QString UploadAttachment = "Upload Attachment Model";
|
||||
|
|
|
@ -3164,8 +3164,7 @@ void StaticModelRenderer::applyRotation(const glm::quat& rotation) {
|
|||
}
|
||||
|
||||
void StaticModelRenderer::applyScale(float scale) {
|
||||
const float SCALE_MULTIPLIER = 0.0006f;
|
||||
_model->setScale(glm::vec3(scale, scale, scale) * SCALE_MULTIPLIER);
|
||||
_model->setScale(glm::vec3(scale, scale, scale));
|
||||
}
|
||||
|
||||
void StaticModelRenderer::applyURL(const QUrl& url) {
|
||||
|
|
|
@ -157,7 +157,7 @@ bool ModelUploader::zip() {
|
|||
|
||||
// mixamo/autodesk defaults
|
||||
if (!mapping.contains(SCALE_FIELD)) {
|
||||
mapping.insert(SCALE_FIELD, 15.0);
|
||||
mapping.insert(SCALE_FIELD, 1.0);
|
||||
}
|
||||
QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
|
||||
if (!joints.contains("jointEyeLeft")) {
|
||||
|
|
|
@ -34,8 +34,7 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
neckParentRotation = owningAvatar->getOrientation();
|
||||
}
|
||||
setRotation(neckParentRotation);
|
||||
const float MODEL_SCALE = 0.0006f;
|
||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale() * MODEL_SCALE);
|
||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale());
|
||||
|
||||
setPupilDilation(_owningHead->getPupilDilation());
|
||||
setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients());
|
||||
|
|
|
@ -36,8 +36,6 @@ SkeletonModel::~SkeletonModel() {
|
|||
_ragdoll = NULL;
|
||||
}
|
||||
|
||||
const float MODEL_SCALE = 0.0006f;
|
||||
|
||||
void SkeletonModel::setJointStates(QVector<JointState> states) {
|
||||
Model::setJointStates(states);
|
||||
|
||||
|
@ -57,7 +55,7 @@ void SkeletonModel::setJointStates(QVector<JointState> states) {
|
|||
_defaultEyeModelPosition.z = -_defaultEyeModelPosition.z;
|
||||
|
||||
// Skeleton may have already been scaled so unscale it
|
||||
_defaultEyeModelPosition = MODEL_SCALE * _defaultEyeModelPosition / _scale;
|
||||
_defaultEyeModelPosition = _defaultEyeModelPosition / _scale;
|
||||
}
|
||||
|
||||
// the SkeletonModel override of updateJointState() will clear the translation part
|
||||
|
@ -80,7 +78,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
setTranslation(_owningAvatar->getSkeletonPosition());
|
||||
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
setRotation(_owningAvatar->getOrientation() * refOrientation);
|
||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale() * MODEL_SCALE);
|
||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale());
|
||||
setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients());
|
||||
|
||||
Model::simulate(deltaTime, fullUpdate);
|
||||
|
|
|
@ -126,7 +126,7 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
Application::getInstance()->displaySide(whichCamera);
|
||||
Application::getInstance()->displaySide(whichCamera, false, RenderArgs::STEREO_LEFT);
|
||||
|
||||
if (displayOverlays) {
|
||||
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
|
||||
|
@ -156,7 +156,7 @@ void TV3DManager::display(Camera& whichCamera) {
|
|||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
Application::getInstance()->displaySide(whichCamera);
|
||||
Application::getInstance()->displaySide(whichCamera, false, RenderArgs::STEREO_RIGHT);
|
||||
|
||||
if (displayOverlays) {
|
||||
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "RenderableLightEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
#include "RenderableSphereEntityItem.h"
|
||||
#include "RenderableTextEntityItem.h"
|
||||
|
||||
|
||||
QThread* EntityTreeRenderer::getMainThread() {
|
||||
|
@ -50,6 +51,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts) :
|
|||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory)
|
||||
|
||||
_currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
_currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
|
@ -163,10 +165,12 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) {
|
|||
|
||||
QString scriptContents = loadScriptContents(entity->getScript());
|
||||
|
||||
if (QScriptEngine::checkSyntax(scriptContents).state() != QScriptSyntaxCheckResult::Valid) {
|
||||
QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(scriptContents);
|
||||
if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
|
||||
qDebug() << "EntityTreeRenderer::loadEntityScript() entity:" << entityID;
|
||||
qDebug() << " INVALID SYNTAX";
|
||||
qDebug() << " SCRIPT:" << scriptContents;
|
||||
qDebug() << " " << syntaxCheck.errorMessage() << ":"
|
||||
<< syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
|
||||
qDebug() << " SCRIPT:" << entity->getScript();
|
||||
return QScriptValue(); // invalid script
|
||||
}
|
||||
|
||||
|
@ -175,7 +179,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) {
|
|||
if (!entityScriptConstructor.isFunction()) {
|
||||
qDebug() << "EntityTreeRenderer::loadEntityScript() entity:" << entityID;
|
||||
qDebug() << " NOT CONSTRUCTOR";
|
||||
qDebug() << " SCRIPT:" << scriptContents;
|
||||
qDebug() << " SCRIPT:" << entity->getScript();
|
||||
return QScriptValue(); // invalid script
|
||||
}
|
||||
|
||||
|
@ -252,15 +256,15 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode) {
|
||||
void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) {
|
||||
bool dontRenderAsScene = !Menu::getInstance()->isOptionChecked(MenuOption::RenderEntitiesAsScene);
|
||||
|
||||
if (dontRenderAsScene) {
|
||||
OctreeRenderer::render(renderMode);
|
||||
OctreeRenderer::render(renderMode, renderSide);
|
||||
} else {
|
||||
if (_tree) {
|
||||
Model::startScene();
|
||||
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode,
|
||||
Model::startScene(renderSide);
|
||||
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
_tree->lockForRead();
|
||||
_tree->recurseTreeWithOperation(renderOperation, &args);
|
||||
|
|
|
@ -56,7 +56,8 @@ public:
|
|||
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
|
||||
|
||||
virtual void init();
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE);
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO);
|
||||
|
||||
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem);
|
||||
virtual const Model* getModelForEntityItem(const EntityItem* entityItem);
|
||||
|
|
|
@ -246,8 +246,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
|||
}
|
||||
|
||||
bool RenderableModelEntityItem::needsSimulation() const {
|
||||
SimulationState simulationState = computeSimulationState();
|
||||
return _needsInitialSimulation || simulationState == Moving || simulationState == Changing;
|
||||
return _needsInitialSimulation || getSimulationState() == EntityItem::Moving;
|
||||
}
|
||||
|
||||
EntityItemProperties RenderableModelEntityItem::getProperties() const {
|
||||
|
|
110
interface/src/entities/RenderableTextEntityItem.cpp
Normal file
110
interface/src/entities/RenderableTextEntityItem.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// RenderableTextEntityItem.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <TextEntityItem.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "Menu.h"
|
||||
#include "EntityTreeRenderer.h"
|
||||
#include "RenderableTextEntityItem.h"
|
||||
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const float LINE_SCALE_RATIO = 1.2f;
|
||||
|
||||
EntityItem* RenderableTextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return new RenderableTextEntityItem(entityID, properties);
|
||||
}
|
||||
|
||||
void RenderableTextEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
||||
assert(getType() == EntityTypes::Text);
|
||||
glm::vec3 position = getPositionInMeters();
|
||||
glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE;
|
||||
glm::vec3 halfDimensions = dimensions / 2.0f;
|
||||
glm::quat rotation = getRotation();
|
||||
float leftMargin = 0.1f;
|
||||
float rightMargin = 0.1f;
|
||||
float topMargin = 0.1f;
|
||||
float bottomMargin = 0.1f;
|
||||
|
||||
//qDebug() << "RenderableTextEntityItem::render() id:" << getEntityItemID() << "text:" << getText();
|
||||
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor backgroundColor = getBackgroundColorX();
|
||||
float alpha = 1.0f; //getBackgroundAlpha();
|
||||
glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, alpha);
|
||||
|
||||
const float SLIGHTLY_BEHIND = -0.005f;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glVertex3f(halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glVertex3f(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glEnd();
|
||||
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation
|
||||
|
||||
// Same font properties as textWidth()
|
||||
TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
glTranslatef(-(halfDimensions.x - leftMargin), halfDimensions.y - topMargin, 0.0f);
|
||||
|
||||
glm::vec2 clipMinimum(0.0f, 0.0f);
|
||||
glm::vec2 clipDimensions((dimensions.x - (leftMargin + rightMargin)) / scaleFactor,
|
||||
(dimensions.y - (topMargin + bottomMargin)) / scaleFactor);
|
||||
|
||||
glScalef(scaleFactor, -scaleFactor, 1.0);
|
||||
enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x);
|
||||
enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x);
|
||||
enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y);
|
||||
enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);
|
||||
|
||||
xColor textColor = getTextColorX();
|
||||
glColor3f(textColor.red / MAX_COLOR, textColor.green / MAX_COLOR, textColor.blue / MAX_COLOR);
|
||||
QStringList lines = _text.split("\n");
|
||||
int lineOffset = maxHeight;
|
||||
float textAlpha = 1.0f; // getTextAlpha()
|
||||
foreach(QString thisLine, lines) {
|
||||
textRenderer->draw(0, lineOffset, qPrintable(thisLine), textAlpha);
|
||||
lineOffset += maxHeight;
|
||||
}
|
||||
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void RenderableTextEntityItem::enableClipPlane(GLenum plane, float x, float y, float z, float w) {
|
||||
GLdouble coefficients[] = { x, y, z, w };
|
||||
glClipPlane(plane, coefficients);
|
||||
glEnable(plane);
|
||||
}
|
||||
|
||||
|
||||
|
44
interface/src/entities/RenderableTextEntityItem.h
Normal file
44
interface/src/entities/RenderableTextEntityItem.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// RenderableTextEntityItem.h
|
||||
// interface/src/entities
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderableTextEntityItem_h
|
||||
#define hifi_RenderableTextEntityItem_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <EntityTree.h>
|
||||
#include <Octree.h>
|
||||
#include <OctreePacketData.h>
|
||||
#include <OctreeRenderer.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include <TextEntityItem.h>
|
||||
|
||||
class RenderableTextEntityItem : public TextEntityItem {
|
||||
public:
|
||||
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableTextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
TextEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
private:
|
||||
void enableClipPlane(GLenum plane, float x, float y, float z, float w);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_RenderableTextEntityItem_h
|
|
@ -1484,8 +1484,10 @@ void Model::deleteGeometry() {
|
|||
// Scene rendering support
|
||||
QVector<Model*> Model::_modelsInScene;
|
||||
gpu::Batch Model::_sceneRenderBatch;
|
||||
void Model::startScene() {
|
||||
_modelsInScene.clear();
|
||||
void Model::startScene(RenderArgs::RenderSide renderSide) {
|
||||
if (renderSide != RenderArgs::STEREO_RIGHT) {
|
||||
_modelsInScene.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::setupBatchTransform(gpu::Batch& batch) {
|
||||
|
@ -1503,146 +1505,155 @@ void Model::setupBatchTransform(gpu::Batch& batch) {
|
|||
void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
|
||||
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
||||
_sceneRenderBatch.clear();
|
||||
gpu::Batch& batch = _sceneRenderBatch;
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO;
|
||||
if (args) {
|
||||
renderSide = args->_renderSide;
|
||||
}
|
||||
|
||||
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
||||
// Do the rendering batch creation for mono or left eye, not for right eye
|
||||
if (renderSide != RenderArgs::STEREO_RIGHT) {
|
||||
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
||||
_sceneRenderBatch.clear();
|
||||
gpu::Batch& batch = _sceneRenderBatch;
|
||||
|
||||
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
||||
|
||||
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||
} else {
|
||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
GLBATCH(glCullFace)(GL_FRONT);
|
||||
}
|
||||
}
|
||||
|
||||
// render opaque meshes with alpha testing
|
||||
|
||||
GLBATCH(glDisable)(GL_BLEND);
|
||||
GLBATCH(glEnable)(GL_ALPHA_TEST);
|
||||
|
||||
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||
} else {
|
||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
GLBATCH(glCullFace)(GL_FRONT);
|
||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// render opaque meshes with alpha testing
|
||||
|
||||
GLBATCH(glDisable)(GL_BLEND);
|
||||
GLBATCH(glEnable)(GL_ALPHA_TEST);
|
||||
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
/*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
|
||||
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE);
|
||||
*/
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
/*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
|
||||
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE);
|
||||
*/
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
}
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
}
|
||||
if (mode == DEFAULT_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
}
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
||||
|
||||
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
||||
|
||||
int opaqueMeshPartsRendered = 0;
|
||||
|
||||
// now, for each model in the scene, render the mesh portions
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
{
|
||||
GLenum buffers[2];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
}
|
||||
if (mode == DEFAULT_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
|
||||
int translucentParts = 0;
|
||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args);
|
||||
|
||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||
GLBATCH(glEnable)(GL_BLEND);
|
||||
GLBATCH(glDepthMask)(false);
|
||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
||||
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
|
||||
{
|
||||
GLenum buffers[1];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args);
|
||||
}
|
||||
|
||||
GLBATCH(glDepthMask)(true);
|
||||
GLBATCH(glDepthFunc)(GL_LESS);
|
||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
GLBATCH(glCullFace)(GL_BACK);
|
||||
}
|
||||
|
||||
// deactivate vertex arrays after drawing
|
||||
GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
|
||||
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT);
|
||||
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX);
|
||||
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT);
|
||||
|
||||
// bind with 0 to switch back to normal operation
|
||||
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
|
||||
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||
if (args) {
|
||||
args->_translucentMeshPartsRendered = translucentParts;
|
||||
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
|
||||
}
|
||||
|
||||
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
||||
|
||||
int opaqueMeshPartsRendered = 0;
|
||||
|
||||
// now, for each model in the scene, render the mesh portions
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
{
|
||||
GLenum buffers[2];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
|
||||
int translucentParts = 0;
|
||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args);
|
||||
|
||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||
GLBATCH(glEnable)(GL_BLEND);
|
||||
GLBATCH(glDepthMask)(false);
|
||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
||||
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
|
||||
{
|
||||
GLenum buffers[1];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args);
|
||||
}
|
||||
|
||||
GLBATCH(glDepthMask)(true);
|
||||
GLBATCH(glDepthFunc)(GL_LESS);
|
||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
GLBATCH(glCullFace)(GL_BACK);
|
||||
}
|
||||
|
||||
// deactivate vertex arrays after drawing
|
||||
GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
|
||||
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT);
|
||||
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX);
|
||||
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT);
|
||||
|
||||
// bind with 0 to switch back to normal operation
|
||||
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
|
||||
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Render!
|
||||
{
|
||||
PROFILE_RANGE("render Batch");
|
||||
::gpu::GLBackend::renderBatch(batch);
|
||||
::gpu::GLBackend::renderBatch(_sceneRenderBatch);
|
||||
}
|
||||
|
||||
// restore all the default material settings
|
||||
Application::getInstance()->setupWorldLight();
|
||||
|
||||
if (args) {
|
||||
args->_translucentMeshPartsRendered = translucentParts;
|
||||
args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered;
|
||||
}
|
||||
}
|
||||
|
||||
bool Model::renderInScene(float alpha, RenderArgs* args) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
class QScriptEngine;
|
||||
|
||||
class Shape;
|
||||
class RenderArgs;
|
||||
#include "RenderArgs.h"
|
||||
class ViewFrustum;
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ public:
|
|||
bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||
|
||||
// Scene rendering support
|
||||
static void startScene();
|
||||
static void startScene(RenderArgs::RenderSide renderSide);
|
||||
bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL);
|
||||
static void endScene(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
|
||||
#include <QVBoxLayout>
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QDockWidget>
|
||||
#include <QWebFrame>
|
||||
#include <QWebView>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "WindowScriptingInterface.h"
|
||||
#include "WebWindowClass.h"
|
||||
|
||||
|
@ -28,29 +32,34 @@ void ScriptEventBridge::emitScriptEvent(const QString& data) {
|
|||
emit scriptEventReceived(data);
|
||||
}
|
||||
|
||||
WebWindowClass::WebWindowClass(const QString& url, int width, int height)
|
||||
|
||||
WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height)
|
||||
: QObject(NULL),
|
||||
_window(new QWidget(NULL, Qt::Tool)),
|
||||
_eventBridge(new ScriptEventBridge(this)) {
|
||||
|
||||
QWebView* webView = new QWebView(_window);
|
||||
ToolWindow* toolWindow = Application::getInstance()->getToolWindow();
|
||||
|
||||
_dockWidget = new QDockWidget(title, toolWindow);
|
||||
_dockWidget->setFeatures(QDockWidget::DockWidgetMovable);
|
||||
QWebView* webView = new QWebView(_dockWidget);
|
||||
webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge);
|
||||
webView->setUrl(url);
|
||||
QVBoxLayout* layout = new QVBoxLayout(_window);
|
||||
_window->setLayout(layout);
|
||||
layout->addWidget(webView);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
_window->setGeometry(0, 0, width, height);
|
||||
_dockWidget->setWidget(webView);
|
||||
|
||||
connect(this, &WebWindowClass::destroyed, _window, &QWidget::deleteLater);
|
||||
toolWindow->addDockWidget(Qt::RightDockWidgetArea, _dockWidget);
|
||||
|
||||
connect(this, &WebWindowClass::destroyed, _dockWidget, &QWidget::deleteLater);
|
||||
}
|
||||
|
||||
WebWindowClass::~WebWindowClass() {
|
||||
}
|
||||
|
||||
void WebWindowClass::setVisible(bool visible) {
|
||||
QMetaObject::invokeMethod(_window, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
|
||||
if (visible) {
|
||||
QMetaObject::invokeMethod(
|
||||
Application::getInstance()->getToolWindow(), "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
|
||||
}
|
||||
QMetaObject::invokeMethod(_dockWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
|
||||
}
|
||||
|
||||
QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) {
|
||||
|
@ -59,8 +68,9 @@ QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine*
|
|||
QMetaObject::invokeMethod(WindowScriptingInterface::getInstance(), "doCreateWebWindow", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(WebWindowClass*, retVal),
|
||||
Q_ARG(const QString&, file),
|
||||
Q_ARG(int, context->argument(1).toInteger()),
|
||||
Q_ARG(int, context->argument(2).toInteger()));
|
||||
Q_ARG(QString, context->argument(1).toString()),
|
||||
Q_ARG(int, context->argument(2).toInteger()),
|
||||
Q_ARG(int, context->argument(3).toInteger()));
|
||||
|
||||
connect(engine, &QScriptEngine::destroyed, retVal, &WebWindowClass::deleteLater);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class WebWindowClass : public QObject {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(QObject* eventBridge READ getEventBridge)
|
||||
public:
|
||||
WebWindowClass(const QString& url, int width, int height);
|
||||
WebWindowClass(const QString& title, const QString& url, int width, int height);
|
||||
~WebWindowClass();
|
||||
|
||||
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
|
||||
|
@ -44,7 +44,7 @@ public slots:
|
|||
ScriptEventBridge* getEventBridge() const { return _eventBridge; }
|
||||
|
||||
private:
|
||||
QWidget* _window;
|
||||
QDockWidget* _dockWidget;
|
||||
ScriptEventBridge* _eventBridge;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@ WindowScriptingInterface::WindowScriptingInterface() :
|
|||
{
|
||||
}
|
||||
|
||||
WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& url, int width, int height) {
|
||||
return new WebWindowClass(url, width, height);
|
||||
WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) {
|
||||
return new WebWindowClass(title, url, width, height);
|
||||
}
|
||||
|
||||
QScriptValue WindowScriptingInterface::hasFocus() {
|
||||
|
@ -252,6 +252,7 @@ QScriptValue WindowScriptingInterface::doPeekNonBlockingFormResult(QScriptValue
|
|||
int e = -1;
|
||||
int d = -1;
|
||||
int c = -1;
|
||||
int h = -1;
|
||||
for (int i = 0; i < _form.property("length").toInt32(); ++i) {
|
||||
QScriptValue item = _form.property(i);
|
||||
QScriptValue value = item.property("value");
|
||||
|
@ -275,6 +276,11 @@ QScriptValue WindowScriptingInterface::doPeekNonBlockingFormResult(QScriptValue
|
|||
array.engine()->undefinedValue()
|
||||
);
|
||||
_form.setProperty(i, item);
|
||||
} else if (item.property("type").toString() == "checkbox") {
|
||||
h++;
|
||||
value = _checks.at(h)->checkState() == Qt::Checked;
|
||||
item.setProperty("value", value);
|
||||
_form.setProperty(i, item);
|
||||
} else {
|
||||
e += 1;
|
||||
bool ok = true;
|
||||
|
@ -309,6 +315,7 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a
|
|||
int e = -1;
|
||||
int d = -1;
|
||||
int c = -1;
|
||||
int h = -1;
|
||||
for (int i = 0; i < _form.property("length").toInt32(); ++i) {
|
||||
QScriptValue item = _form.property(i);
|
||||
QScriptValue value = item.property("value");
|
||||
|
@ -332,6 +339,11 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a
|
|||
array.engine()->undefinedValue()
|
||||
);
|
||||
_form.setProperty(i, item);
|
||||
} else if (item.property("type").toString() == "checkbox") {
|
||||
h++;
|
||||
value = _checks.at(h)->checkState() == Qt::Checked;
|
||||
item.setProperty("value", value);
|
||||
_form.setProperty(i, item);
|
||||
} else {
|
||||
e += 1;
|
||||
bool ok = true;
|
||||
|
@ -362,6 +374,7 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a
|
|||
_edits.clear();
|
||||
_directories.clear();
|
||||
_combos.clear();
|
||||
_checks.clear();
|
||||
|
||||
array = _form;
|
||||
return (_formResult == QDialog::Accepted);
|
||||
|
@ -387,6 +400,7 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal
|
|||
int e = -1;
|
||||
int d = -1;
|
||||
int c = -1;
|
||||
int h = -1;
|
||||
for (int i = 0; i < form.property("length").toInt32(); ++i) {
|
||||
QScriptValue item = form.property(i);
|
||||
QScriptValue value = item.property("value");
|
||||
|
@ -410,6 +424,11 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal
|
|||
form.engine()->undefinedValue()
|
||||
);
|
||||
form.setProperty(i, item);
|
||||
} else if (item.property("type").toString() == "checkbox") {
|
||||
h++;
|
||||
value = _checks.at(h)->checkState() == Qt::Checked;
|
||||
item.setProperty("value", value);
|
||||
form.setProperty(i, item);
|
||||
} else {
|
||||
e += 1;
|
||||
bool ok = true;
|
||||
|
@ -436,6 +455,7 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal
|
|||
|
||||
delete editDialog;
|
||||
_combos.clear();
|
||||
_checks.clear();
|
||||
_edits.clear();
|
||||
_directories.clear();
|
||||
return (result == QDialog::Accepted);
|
||||
|
@ -522,6 +542,12 @@ QDialog* WindowScriptingInterface::createForm(const QString& title, QScriptValue
|
|||
}
|
||||
_combos.push_back(combo);
|
||||
formLayout->addRow(new QLabel(item.property("label").toString()), combo);
|
||||
} else if (item.property("type").toString() == "checkbox") {
|
||||
QCheckBox* check = new QCheckBox();
|
||||
check->setTristate(false);
|
||||
check->setCheckState(item.property("value").toString() == "true" ? Qt::Checked : Qt::Unchecked);
|
||||
_checks.push_back(check);
|
||||
formLayout->addRow(new QLabel(item.property("label").toString()), check);
|
||||
} else {
|
||||
QLineEdit* edit = new QLineEdit(item.property("value").toString());
|
||||
edit->setMinimumWidth(200);
|
||||
|
|
|
@ -78,7 +78,7 @@ private slots:
|
|||
void nonBlockingFormAccepted() { _nonBlockingFormActive = false; _formResult = QDialog::Accepted; emit nonBlockingFormClosed(); }
|
||||
void nonBlockingFormRejected() { _nonBlockingFormActive = false; _formResult = QDialog::Rejected; emit nonBlockingFormClosed(); }
|
||||
|
||||
WebWindowClass* doCreateWebWindow(const QString& url, int width, int height);
|
||||
WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height);
|
||||
|
||||
private:
|
||||
WindowScriptingInterface();
|
||||
|
@ -90,6 +90,7 @@ private:
|
|||
bool _nonBlockingFormActive;
|
||||
int _formResult;
|
||||
QVector<QComboBox*> _combos;
|
||||
QVector<QCheckBox*> _checks;
|
||||
QVector<QLineEdit*> _edits;
|
||||
QVector<QPushButton*> _directories;
|
||||
};
|
||||
|
|
82
interface/src/ui/ToolWindow.cpp
Normal file
82
interface/src/ui/ToolWindow.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// ToolWindow.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Ryan Huffman on 11/13/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "ToolWindow.h"
|
||||
#include "UIUtil.h"
|
||||
|
||||
const int DEFAULT_WIDTH = 300;
|
||||
|
||||
ToolWindow::ToolWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
_hasShown(false),
|
||||
_lastGeometry() {
|
||||
}
|
||||
|
||||
bool ToolWindow::event(QEvent* event) {
|
||||
QEvent::Type type = event->type();
|
||||
if (type == QEvent::Show) {
|
||||
if (!_hasShown) {
|
||||
_hasShown = true;
|
||||
|
||||
QMainWindow* mainWindow = Application::getInstance()->getWindow();
|
||||
QRect mainGeometry = mainWindow->geometry();
|
||||
|
||||
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
|
||||
int menuBarHeight = Menu::getInstance()->geometry().height();
|
||||
int topMargin = titleBarHeight + menuBarHeight;
|
||||
|
||||
_lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin,
|
||||
DEFAULT_WIDTH, mainGeometry.height() - topMargin);
|
||||
}
|
||||
setGeometry(_lastGeometry);
|
||||
return true;
|
||||
} else if (type == QEvent::Hide) {
|
||||
_lastGeometry = geometry();
|
||||
return true;
|
||||
}
|
||||
|
||||
return QMainWindow::event(event);
|
||||
}
|
||||
|
||||
void ToolWindow::onChildVisibilityUpdated(bool visible) {
|
||||
if (visible) {
|
||||
setVisible(true);
|
||||
} else {
|
||||
bool hasVisible = false;
|
||||
QList<QDockWidget*> dockWidgets = findChildren<QDockWidget*>();
|
||||
for (int i = 0; i < dockWidgets.count(); i++) {
|
||||
if (dockWidgets[i]->isVisible()) {
|
||||
hasVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setVisible(hasVisible);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget) {
|
||||
QMainWindow::addDockWidget(area, dockWidget);
|
||||
|
||||
connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated);
|
||||
}
|
||||
|
||||
void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation) {
|
||||
QMainWindow::addDockWidget(area, dockWidget, orientation);
|
||||
|
||||
connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated);
|
||||
}
|
||||
|
||||
void ToolWindow::removeDockWidget(QDockWidget* dockWidget) {
|
||||
QMainWindow::removeDockWidget(dockWidget);
|
||||
|
||||
disconnect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated);
|
||||
}
|
40
interface/src/ui/ToolWindow.h
Normal file
40
interface/src/ui/ToolWindow.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ToolWindow.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Ryan Huffman on 11/13/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_ToolWindow_h
|
||||
#define hifi_ToolWindow_h
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QEvent>
|
||||
#include <QMainWindow>
|
||||
#include <QRect>
|
||||
#include <QWidget>
|
||||
|
||||
class ToolWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ToolWindow(QWidget* parent = NULL);
|
||||
|
||||
virtual bool event(QEvent* event);
|
||||
virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget);
|
||||
virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation);
|
||||
virtual void removeDockWidget(QDockWidget* dockWidget);
|
||||
|
||||
public slots:
|
||||
void onChildVisibilityUpdated(bool visible);
|
||||
|
||||
|
||||
private:
|
||||
bool _hasShown;
|
||||
QRect _lastGeometry;
|
||||
};
|
||||
|
||||
#endif // hifi_ToolWindow_h
|
|
@ -31,6 +31,17 @@ Base3DOverlay::Base3DOverlay() :
|
|||
{
|
||||
}
|
||||
|
||||
Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
||||
Overlay(base3DOverlay),
|
||||
_position(base3DOverlay->_position),
|
||||
_lineWidth(base3DOverlay->_lineWidth),
|
||||
_rotation(base3DOverlay->_rotation),
|
||||
_isSolid(base3DOverlay->_isSolid),
|
||||
_isDashedLine(base3DOverlay->_isDashedLine),
|
||||
_ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection)
|
||||
{
|
||||
}
|
||||
|
||||
Base3DOverlay::~Base3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -178,8 +189,4 @@ void Base3DOverlay::drawDashedLine(const glm::vec3& start, const glm::vec3& end)
|
|||
glVertex3f(end.x, end.y, end.z);
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ class Base3DOverlay : public Overlay {
|
|||
|
||||
public:
|
||||
Base3DOverlay();
|
||||
Base3DOverlay(const Base3DOverlay* base3DOverlay);
|
||||
~Base3DOverlay();
|
||||
|
||||
// getters
|
||||
|
@ -64,6 +65,5 @@ protected:
|
|||
bool _isDashedLine;
|
||||
bool _ignoreRayIntersection;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Base3DOverlay_h
|
||||
|
|
|
@ -24,6 +24,19 @@ BillboardOverlay::BillboardOverlay() :
|
|||
_isLoaded = false;
|
||||
}
|
||||
|
||||
BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) :
|
||||
Base3DOverlay(billboardOverlay),
|
||||
_url(billboardOverlay->_url),
|
||||
_billboard(billboardOverlay->_billboard),
|
||||
_size(),
|
||||
_billboardTexture(),
|
||||
_newTextureNeeded(true),
|
||||
_fromImage(billboardOverlay->_fromImage),
|
||||
_scale(billboardOverlay->_scale),
|
||||
_isFacingAvatar(billboardOverlay->_isFacingAvatar)
|
||||
{
|
||||
}
|
||||
|
||||
void BillboardOverlay::render(RenderArgs* args) {
|
||||
if (!_visible || !_isLoaded) {
|
||||
return;
|
||||
|
@ -215,3 +228,6 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v
|
|||
return false;
|
||||
}
|
||||
|
||||
BillboardOverlay* BillboardOverlay::createClone() const {
|
||||
return new BillboardOverlay(this);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ class BillboardOverlay : public Base3DOverlay {
|
|||
Q_OBJECT
|
||||
public:
|
||||
BillboardOverlay();
|
||||
|
||||
BillboardOverlay(const BillboardOverlay* billboardOverlay);
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// setters
|
||||
|
@ -36,6 +37,8 @@ public:
|
|||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
virtual BillboardOverlay* createClone() const;
|
||||
|
||||
private slots:
|
||||
void replyFinished();
|
||||
|
||||
|
|
|
@ -33,6 +33,22 @@ Circle3DOverlay::Circle3DOverlay() :
|
|||
_minorTickMarksColor.red = _minorTickMarksColor.green = _minorTickMarksColor.blue = (unsigned char)0;
|
||||
}
|
||||
|
||||
Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
|
||||
Planar3DOverlay(circle3DOverlay),
|
||||
_startAt(circle3DOverlay->_startAt),
|
||||
_endAt(circle3DOverlay->_endAt),
|
||||
_outerRadius(circle3DOverlay->_outerRadius),
|
||||
_innerRadius(circle3DOverlay->_innerRadius),
|
||||
_hasTickMarks(circle3DOverlay->_hasTickMarks),
|
||||
_majorTickMarksAngle(circle3DOverlay->_majorTickMarksAngle),
|
||||
_minorTickMarksAngle(circle3DOverlay->_minorTickMarksAngle),
|
||||
_majorTickMarksLength(circle3DOverlay->_majorTickMarksLength),
|
||||
_minorTickMarksLength(circle3DOverlay->_minorTickMarksLength),
|
||||
_majorTickMarksColor(circle3DOverlay->_majorTickMarksColor),
|
||||
_minorTickMarksColor(circle3DOverlay->_minorTickMarksColor)
|
||||
{
|
||||
}
|
||||
|
||||
Circle3DOverlay::~Circle3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -358,9 +374,6 @@ bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin,
|
|||
return intersects;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Circle3DOverlay* Circle3DOverlay::createClone() const {
|
||||
return new Circle3DOverlay(this);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class Circle3DOverlay : public Planar3DOverlay {
|
|||
|
||||
public:
|
||||
Circle3DOverlay();
|
||||
Circle3DOverlay(const Circle3DOverlay* circle3DOverlay);
|
||||
~Circle3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
@ -48,6 +49,8 @@ public:
|
|||
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
virtual Circle3DOverlay* createClone() const;
|
||||
|
||||
protected:
|
||||
float _startAt;
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
Cube3DOverlay::Cube3DOverlay() {
|
||||
}
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) :
|
||||
Volume3DOverlay(cube3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Cube3DOverlay::~Cube3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -102,3 +107,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
|||
delete glower;
|
||||
}
|
||||
}
|
||||
|
||||
Cube3DOverlay* Cube3DOverlay::createClone() const {
|
||||
return new Cube3DOverlay(this);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@ class Cube3DOverlay : public Volume3DOverlay {
|
|||
|
||||
public:
|
||||
Cube3DOverlay();
|
||||
Cube3DOverlay(const Cube3DOverlay* cube3DOverlay);
|
||||
~Cube3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual Cube3DOverlay* createClone() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,13 @@ Grid3DOverlay::Grid3DOverlay() : Base3DOverlay(),
|
|||
_majorGridEvery(5) {
|
||||
}
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) :
|
||||
Base3DOverlay(grid3DOverlay),
|
||||
_minorGridWidth(grid3DOverlay->_minorGridWidth),
|
||||
_majorGridEvery(grid3DOverlay->_majorGridEvery)
|
||||
{
|
||||
}
|
||||
|
||||
Grid3DOverlay::~Grid3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -127,3 +134,7 @@ QScriptValue Grid3DOverlay::getProperty(const QString& property) {
|
|||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Grid3DOverlay* Grid3DOverlay::createClone() const {
|
||||
return new Grid3DOverlay(this);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,15 @@ class Grid3DOverlay : public Base3DOverlay {
|
|||
|
||||
public:
|
||||
Grid3DOverlay();
|
||||
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
||||
~Grid3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual Grid3DOverlay* createClone() const;
|
||||
|
||||
private:
|
||||
float _minorGridWidth;
|
||||
int _majorGridEvery;
|
||||
|
|
|
@ -27,6 +27,18 @@ ImageOverlay::ImageOverlay() :
|
|||
_isLoaded = false;
|
||||
}
|
||||
|
||||
ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) :
|
||||
Overlay2D(imageOverlay),
|
||||
_imageURL(imageOverlay->_imageURL),
|
||||
_textureImage(imageOverlay->_textureImage),
|
||||
_textureID(0),
|
||||
_fromImage(),
|
||||
_renderImage(imageOverlay->_renderImage),
|
||||
_textureBound(false),
|
||||
_wantClipFromImage(false)
|
||||
{
|
||||
}
|
||||
|
||||
ImageOverlay::~ImageOverlay() {
|
||||
if (_parent && _textureID) {
|
||||
// do we need to call this?
|
||||
|
@ -161,3 +173,6 @@ QScriptValue ImageOverlay::getProperty(const QString& property) {
|
|||
|
||||
return Overlay2D::getProperty(property);
|
||||
}
|
||||
ImageOverlay* ImageOverlay::createClone() const {
|
||||
return new ImageOverlay(this);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ class ImageOverlay : public Overlay2D {
|
|||
|
||||
public:
|
||||
ImageOverlay();
|
||||
ImageOverlay(const ImageOverlay* imageOverlay);
|
||||
~ImageOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
|
@ -46,6 +47,8 @@ public:
|
|||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual ImageOverlay* createClone() const;
|
||||
|
||||
private slots:
|
||||
void replyFinished(); // we actually want to hide this...
|
||||
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
Line3DOverlay::Line3DOverlay() {
|
||||
}
|
||||
|
||||
Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) :
|
||||
Base3DOverlay(line3DOverlay),
|
||||
_end(line3DOverlay->_end)
|
||||
{
|
||||
}
|
||||
|
||||
Line3DOverlay::~Line3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -87,3 +93,7 @@ QScriptValue Line3DOverlay::getProperty(const QString& property) {
|
|||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Line3DOverlay* Line3DOverlay::createClone() const {
|
||||
return new Line3DOverlay(this);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class Line3DOverlay : public Base3DOverlay {
|
|||
|
||||
public:
|
||||
Line3DOverlay();
|
||||
Line3DOverlay(const Line3DOverlay* line3DOverlay);
|
||||
~Line3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
|
@ -30,6 +31,8 @@ public:
|
|||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual Line3DOverlay* createClone() const;
|
||||
|
||||
protected:
|
||||
glm::vec3 _end;
|
||||
};
|
||||
|
|
|
@ -18,6 +18,13 @@ LocalModelsOverlay::LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer) :
|
|||
_entityTreeRenderer(entityTreeRenderer) {
|
||||
}
|
||||
|
||||
LocalModelsOverlay::LocalModelsOverlay(const LocalModelsOverlay* localModelsOverlay) :
|
||||
Volume3DOverlay(localModelsOverlay),
|
||||
_entityTreeRenderer(localModelsOverlay->_entityTreeRenderer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LocalModelsOverlay::~LocalModelsOverlay() {
|
||||
}
|
||||
|
||||
|
@ -48,3 +55,7 @@ void LocalModelsOverlay::render(RenderArgs* args) {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
LocalModelsOverlay* LocalModelsOverlay::createClone() const {
|
||||
return new LocalModelsOverlay(this);
|
||||
}
|
||||
|
|
|
@ -20,11 +20,14 @@ class LocalModelsOverlay : public Volume3DOverlay {
|
|||
Q_OBJECT
|
||||
public:
|
||||
LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer);
|
||||
LocalModelsOverlay(const LocalModelsOverlay* localModelsOverlay);
|
||||
~LocalModelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual LocalModelsOverlay* createClone() const;
|
||||
|
||||
private:
|
||||
EntityTreeRenderer* _entityTreeRenderer;
|
||||
};
|
||||
|
|
|
@ -28,6 +28,12 @@ LocalVoxelsOverlay::LocalVoxelsOverlay() :
|
|||
{
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay::LocalVoxelsOverlay(const LocalVoxelsOverlay* localVoxelsOverlay) :
|
||||
Volume3DOverlay(localVoxelsOverlay),
|
||||
_voxelCount(localVoxelsOverlay->_voxelCount)
|
||||
{
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay::~LocalVoxelsOverlay() {
|
||||
_voxelSystem->changeTree(new VoxelTree());
|
||||
_voxelSystem.clear();
|
||||
|
@ -103,6 +109,10 @@ void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay* LocalVoxelsOverlay::createClone() const {
|
||||
return new LocalVoxelsOverlay(this);
|
||||
}
|
||||
|
||||
QScriptValue LocalVoxelsOverlay::getProperty(const QString& property) {
|
||||
if (property == "scale") {
|
||||
return vec3toScriptValue(_scriptEngine, getDimensions());
|
||||
|
|
|
@ -32,6 +32,7 @@ class LocalVoxelsOverlay : public Volume3DOverlay {
|
|||
Q_OBJECT
|
||||
public:
|
||||
LocalVoxelsOverlay();
|
||||
LocalVoxelsOverlay(const LocalVoxelsOverlay* localVoxelsOverlay);
|
||||
~LocalVoxelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
|
@ -40,6 +41,7 @@ public:
|
|||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual LocalVoxelsOverlay* createClone() const;
|
||||
private:
|
||||
static QMap<QString, WeakVoxelSystemPointer> _voxelSystemMap; // treeName/voxelSystem
|
||||
|
||||
|
|
|
@ -22,6 +22,22 @@ ModelOverlay::ModelOverlay()
|
|||
_isLoaded = false;
|
||||
}
|
||||
|
||||
ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
||||
Base3DOverlay(modelOverlay),
|
||||
_model(),
|
||||
_modelTextures(QVariantMap()),
|
||||
_url(modelOverlay->_url),
|
||||
_rotation(modelOverlay->_rotation),
|
||||
_scale(modelOverlay->_scale),
|
||||
_updateModel(false)
|
||||
{
|
||||
_model.init();
|
||||
if (_url.isValid()) {
|
||||
_updateModel = true;
|
||||
_isLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::update(float deltatime) {
|
||||
if (_updateModel) {
|
||||
_updateModel = false;
|
||||
|
@ -166,4 +182,6 @@ bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const g
|
|||
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo);
|
||||
}
|
||||
|
||||
|
||||
ModelOverlay* ModelOverlay::createClone() const {
|
||||
return new ModelOverlay(this);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ class ModelOverlay : public Base3DOverlay {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ModelOverlay();
|
||||
|
||||
ModelOverlay(const ModelOverlay* modelOverlay);
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
@ -29,8 +30,10 @@ public:
|
|||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const;
|
||||
|
||||
virtual ModelOverlay* createClone() const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Model _model;
|
||||
QVariantMap _modelTextures;
|
||||
|
||||
|
|
|
@ -39,12 +39,32 @@ Overlay::Overlay() :
|
|||
{
|
||||
}
|
||||
|
||||
Overlay::Overlay(const Overlay* overlay) :
|
||||
_parent(NULL),
|
||||
_isLoaded(overlay->_isLoaded),
|
||||
_alpha(overlay->_alpha),
|
||||
_glowLevel(overlay->_glowLevel),
|
||||
_pulse(overlay->_pulse),
|
||||
_pulseMax(overlay->_pulseMax),
|
||||
_pulseMin(overlay->_pulseMin),
|
||||
_pulsePeriod(overlay->_pulsePeriod),
|
||||
_pulseDirection(overlay->_pulseDirection),
|
||||
_lastPulseUpdate(usecTimestampNow()),
|
||||
_glowLevelPulse(overlay->_glowLevelPulse),
|
||||
_alphaPulse(overlay->_alphaPulse),
|
||||
_colorPulse(overlay->_colorPulse),
|
||||
_color(overlay->_color),
|
||||
_visible(overlay->_visible),
|
||||
_anchor(overlay->_anchor),
|
||||
_scriptEngine(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void Overlay::init(QGLWidget* parent, QScriptEngine* scriptEngine) {
|
||||
_parent = parent;
|
||||
_scriptEngine = scriptEngine;
|
||||
}
|
||||
|
||||
|
||||
Overlay::~Overlay() {
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
};
|
||||
|
||||
Overlay();
|
||||
Overlay(const Overlay* overlay);
|
||||
~Overlay();
|
||||
void init(QGLWidget* parent, QScriptEngine* scriptEngine);
|
||||
virtual void update(float deltatime) {}
|
||||
|
@ -78,6 +79,7 @@ public:
|
|||
void setAlphaPulse(float value) { _alphaPulse = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual Overlay* createClone() const = 0;
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
Overlay2D::Overlay2D() {
|
||||
}
|
||||
|
||||
Overlay2D::Overlay2D(const Overlay2D* overlay2D) :
|
||||
Overlay(overlay2D),
|
||||
_bounds(overlay2D->_bounds)
|
||||
{
|
||||
}
|
||||
|
||||
Overlay2D::~Overlay2D() {
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ class Overlay2D : public Overlay {
|
|||
|
||||
public:
|
||||
Overlay2D();
|
||||
Overlay2D(const Overlay2D* overlay2D);
|
||||
~Overlay2D();
|
||||
|
||||
virtual bool is3D() const { return false; }
|
||||
|
@ -43,7 +44,7 @@ public:
|
|||
void setX(int x) { _bounds.setX(x); }
|
||||
void setY(int y) { _bounds.setY(y); }
|
||||
void setWidth(int width) { _bounds.setWidth(width); }
|
||||
void setHeight(int height) { _bounds.setHeight(height); }
|
||||
void setHeight(int height) { _bounds.setHeight(height); }
|
||||
void setBounds(const QRect& bounds) { _bounds = bounds; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
|
|
@ -86,14 +86,14 @@ void Overlays::render2D() {
|
|||
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlays2D) {
|
||||
thisOverlay->render(&args);
|
||||
}
|
||||
}
|
||||
|
||||
void Overlays::render3D(RenderArgs::RenderMode renderMode) {
|
||||
void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) {
|
||||
QReadLocker lock(&_lock);
|
||||
if (_overlays3D.size() == 0) {
|
||||
return;
|
||||
|
@ -108,7 +108,7 @@ void Overlays::render3D(RenderArgs::RenderMode renderMode) {
|
|||
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
renderMode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlays3D) {
|
||||
|
@ -196,6 +196,16 @@ unsigned int Overlays::addOverlay(Overlay* overlay) {
|
|||
return thisID;
|
||||
}
|
||||
|
||||
unsigned int Overlays::cloneOverlay(unsigned int id) {
|
||||
Overlay* thisOverlay = NULL;
|
||||
if (_overlays2D.contains(id)) {
|
||||
thisOverlay = _overlays2D[id];
|
||||
} else if (_overlays3D.contains(id)) {
|
||||
thisOverlay = _overlays3D[id];
|
||||
}
|
||||
return addOverlay(thisOverlay->createClone());
|
||||
}
|
||||
|
||||
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
||||
Overlay* thisOverlay = NULL;
|
||||
QWriteLocker lock(&_lock);
|
||||
|
@ -397,15 +407,15 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
|||
|
||||
bool Overlays::isLoaded(unsigned int id) {
|
||||
QReadLocker lock(&_lock);
|
||||
Overlay* overlay = _overlays2D.value(id);
|
||||
if (!overlay) {
|
||||
_overlays3D.value(id);
|
||||
}
|
||||
if (!overlay) {
|
||||
Overlay* thisOverlay = NULL;
|
||||
if (_overlays2D.contains(id)) {
|
||||
thisOverlay = _overlays2D[id];
|
||||
} else if (_overlays3D.contains(id)) {
|
||||
thisOverlay = _overlays3D[id];
|
||||
} else {
|
||||
return false; // not found
|
||||
}
|
||||
|
||||
return overlay->isLoaded();
|
||||
return thisOverlay->isLoaded();
|
||||
}
|
||||
|
||||
float Overlays::textWidth(unsigned int id, const QString& text) const {
|
||||
|
|
|
@ -51,7 +51,8 @@ public:
|
|||
~Overlays();
|
||||
void init(QGLWidget* parent);
|
||||
void update(float deltatime);
|
||||
void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE);
|
||||
void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE,
|
||||
RenderArgs::RenderSide renderSide = RenderArgs::MONO);
|
||||
void render2D();
|
||||
|
||||
public slots:
|
||||
|
@ -61,6 +62,9 @@ public slots:
|
|||
/// adds an overlay that's already been created
|
||||
unsigned int addOverlay(Overlay* overlay);
|
||||
|
||||
/// clones an existing overlay
|
||||
unsigned int cloneOverlay(unsigned int id);
|
||||
|
||||
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
|
||||
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
||||
bool editOverlay(unsigned int id, const QScriptValue& properties);
|
||||
|
|
|
@ -26,6 +26,12 @@ Planar3DOverlay::Planar3DOverlay() :
|
|||
{
|
||||
}
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay(const Planar3DOverlay* planar3DOverlay) :
|
||||
Base3DOverlay(planar3DOverlay),
|
||||
_dimensions(planar3DOverlay->_dimensions)
|
||||
{
|
||||
}
|
||||
|
||||
Planar3DOverlay::~Planar3DOverlay() {
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ class Planar3DOverlay : public Base3DOverlay {
|
|||
|
||||
public:
|
||||
Planar3DOverlay();
|
||||
Planar3DOverlay(const Planar3DOverlay* planar3DOverlay);
|
||||
~Planar3DOverlay();
|
||||
|
||||
// getters
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
Rectangle3DOverlay::Rectangle3DOverlay() {
|
||||
}
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) :
|
||||
Planar3DOverlay(rectangle3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle3DOverlay::~Rectangle3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -106,9 +111,6 @@ void Rectangle3DOverlay::setProperties(const QScriptValue &properties) {
|
|||
Planar3DOverlay::setProperties(properties);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Rectangle3DOverlay* Rectangle3DOverlay::createClone() const {
|
||||
return new Rectangle3DOverlay(this);
|
||||
}
|
||||
|
|
|
@ -18,9 +18,12 @@ class Rectangle3DOverlay : public Planar3DOverlay {
|
|||
|
||||
public:
|
||||
Rectangle3DOverlay();
|
||||
Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay);
|
||||
~Rectangle3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
||||
virtual Rectangle3DOverlay* createClone() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
Sphere3DOverlay::Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
||||
Volume3DOverlay(Sphere3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Sphere3DOverlay::~Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -70,3 +75,7 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
Sphere3DOverlay* Sphere3DOverlay::createClone() const {
|
||||
return new Sphere3DOverlay(this);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@ class Sphere3DOverlay : public Volume3DOverlay {
|
|||
|
||||
public:
|
||||
Sphere3DOverlay();
|
||||
Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay);
|
||||
~Sphere3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual Sphere3DOverlay* createClone() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,19 @@ Text3DOverlay::Text3DOverlay() :
|
|||
{
|
||||
}
|
||||
|
||||
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||
Planar3DOverlay(text3DOverlay),
|
||||
_text(text3DOverlay->_text),
|
||||
_backgroundColor(text3DOverlay->_backgroundColor),
|
||||
_lineHeight(text3DOverlay->_lineHeight),
|
||||
_leftMargin(text3DOverlay->_leftMargin),
|
||||
_topMargin(text3DOverlay->_topMargin),
|
||||
_rightMargin(text3DOverlay->_rightMargin),
|
||||
_bottomMargin(text3DOverlay->_bottomMargin),
|
||||
_isFacingAvatar(text3DOverlay->_isFacingAvatar)
|
||||
{
|
||||
}
|
||||
|
||||
Text3DOverlay::~Text3DOverlay() {
|
||||
}
|
||||
|
||||
|
@ -172,7 +185,6 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
setBottomMargin(properties.property("bottomMargin").toVariant().toFloat());
|
||||
}
|
||||
|
||||
|
||||
QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar");
|
||||
if (isFacingAvatarValue.isValid()) {
|
||||
_isFacingAvatar = isFacingAvatarValue.toVariant().toBool();
|
||||
|
@ -208,6 +220,10 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) {
|
|||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Text3DOverlay* Text3DOverlay::createClone() const {
|
||||
return new Text3DOverlay(this);;
|
||||
}
|
||||
|
||||
float Text3DOverlay::textWidth(const QString& text) const {
|
||||
QFont font(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); // Same font properties as render()
|
||||
QFontMetrics fontMetrics(font);
|
||||
|
@ -215,3 +231,4 @@ float Text3DOverlay::textWidth(const QString& text) const {
|
|||
return scaleFactor * (float)fontMetrics.width(qPrintable(text));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ class Text3DOverlay : public Planar3DOverlay {
|
|||
|
||||
public:
|
||||
Text3DOverlay();
|
||||
Text3DOverlay(const Text3DOverlay* text3DOverlay);
|
||||
~Text3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
|
@ -51,6 +52,8 @@ public:
|
|||
|
||||
float textWidth(const QString& text) const; // Meters
|
||||
|
||||
virtual Text3DOverlay* createClone() const;
|
||||
|
||||
private:
|
||||
void enableClipPlane(GLenum plane, float x, float y, float z, float w);
|
||||
|
||||
|
|
|
@ -25,6 +25,16 @@ TextOverlay::TextOverlay() :
|
|||
{
|
||||
}
|
||||
|
||||
TextOverlay::TextOverlay(const TextOverlay* textOverlay) :
|
||||
Overlay2D(textOverlay),
|
||||
_text(textOverlay->_text),
|
||||
_backgroundColor(textOverlay->_backgroundColor),
|
||||
_leftMargin(textOverlay->_leftMargin),
|
||||
_topMargin(textOverlay->_topMargin),
|
||||
_fontSize(textOverlay->_fontSize)
|
||||
{
|
||||
}
|
||||
|
||||
TextOverlay::~TextOverlay() {
|
||||
}
|
||||
|
||||
|
@ -124,6 +134,10 @@ void TextOverlay::setProperties(const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
|
||||
TextOverlay* TextOverlay::createClone() const {
|
||||
return new TextOverlay(this);
|
||||
}
|
||||
|
||||
QScriptValue TextOverlay::getProperty(const QString& property) {
|
||||
if (property == "font") {
|
||||
QScriptValue font = _scriptEngine->newObject();
|
||||
|
@ -146,7 +160,6 @@ QScriptValue TextOverlay::getProperty(const QString& property) {
|
|||
return Overlay2D::getProperty(property);
|
||||
}
|
||||
|
||||
|
||||
float TextOverlay::textWidth(const QString& text) const {
|
||||
QFont font(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); // Same font properties as render()
|
||||
QFontMetrics fontMetrics(font);
|
||||
|
|
|
@ -37,6 +37,7 @@ class TextOverlay : public Overlay2D {
|
|||
|
||||
public:
|
||||
TextOverlay();
|
||||
TextOverlay(const TextOverlay* textOverlay);
|
||||
~TextOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
|
@ -53,12 +54,12 @@ public:
|
|||
void setFontSize(int fontSize) { _fontSize = fontSize; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual TextOverlay* createClone() const;
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
float textWidth(const QString& text) const; // Pixels
|
||||
|
||||
private:
|
||||
|
||||
QString _text;
|
||||
xColor _backgroundColor;
|
||||
int _leftMargin;
|
||||
|
|
|
@ -28,6 +28,12 @@ Volume3DOverlay::Volume3DOverlay() :
|
|||
{
|
||||
}
|
||||
|
||||
Volume3DOverlay::Volume3DOverlay(const Volume3DOverlay* volume3DOverlay) :
|
||||
Base3DOverlay(volume3DOverlay),
|
||||
_dimensions(volume3DOverlay->_dimensions)
|
||||
{
|
||||
}
|
||||
|
||||
Volume3DOverlay::~Volume3DOverlay() {
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ class Volume3DOverlay : public Base3DOverlay {
|
|||
|
||||
public:
|
||||
Volume3DOverlay();
|
||||
Volume3DOverlay(const Volume3DOverlay* volume3DOverlay);
|
||||
~Volume3DOverlay();
|
||||
|
||||
// getters
|
||||
|
|
|
@ -37,6 +37,10 @@ public slots:
|
|||
|
||||
void injectorStopped();
|
||||
|
||||
signals:
|
||||
void mutedByMixer();
|
||||
void environmentMuted();
|
||||
|
||||
private:
|
||||
AudioScriptingInterface();
|
||||
QList< QPointer<AudioInjector> > _activeInjectors;
|
||||
|
|
|
@ -91,8 +91,8 @@ const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
|
|||
const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
|
||||
const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000;
|
||||
|
||||
const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_head.fst");
|
||||
const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_body.fst");
|
||||
const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/models/heads/defaultAvatar_head.fst");
|
||||
const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/models/skeletons/defaultAvatar_body.fst");
|
||||
|
||||
enum KeyState {
|
||||
NO_KEY_DOWN = 0,
|
||||
|
|
|
@ -96,6 +96,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
|||
#endif // USE_BULLET_PHYSICS
|
||||
_changedOnServer = 0;
|
||||
initFromEntityItemID(entityItemID);
|
||||
_simulationState = EntityItem::Static;
|
||||
}
|
||||
|
||||
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) {
|
||||
|
@ -111,6 +112,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
|
|||
_changedOnServer = 0;
|
||||
initFromEntityItemID(entityItemID);
|
||||
setProperties(properties, true); // force copy
|
||||
_simulationState = EntityItem::Static;
|
||||
}
|
||||
|
||||
EntityItem::~EntityItem() {
|
||||
|
@ -735,12 +737,9 @@ void EntityItem::update(const quint64& updateTime) {
|
|||
}
|
||||
|
||||
EntityItem::SimulationState EntityItem::computeSimulationState() const {
|
||||
if (hasVelocity() || (hasGravity() && !isRestingOnSurface())) {
|
||||
if (hasVelocity() || (hasGravity() && !isRestingOnSurface()) || hasAngularVelocity()) {
|
||||
return EntityItem::Moving;
|
||||
}
|
||||
if (hasAngularVelocity()) {
|
||||
return EntityItem::Changing;
|
||||
}
|
||||
if (isMortal()) {
|
||||
return EntityItem::Mortal;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "EntityItemProperties.h"
|
||||
#include "EntityTypes.h"
|
||||
|
||||
class EntityTree;
|
||||
class EntityTreeElement;
|
||||
class EntityTreeElementExtraEncodeData;
|
||||
|
||||
|
@ -119,11 +120,13 @@ public:
|
|||
typedef enum SimulationState_t {
|
||||
Static,
|
||||
Mortal,
|
||||
Changing,
|
||||
Moving
|
||||
} SimulationState;
|
||||
|
||||
virtual SimulationState computeSimulationState() const;
|
||||
// computes the SimulationState that the entity SHOULD be in.
|
||||
// Use getSimulationState() to find the state under which it is currently categorized.
|
||||
virtual SimulationState computeSimulationState() const;
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
// similar to assignment/copy, but it handles keeping lifetime accurate
|
||||
|
@ -272,8 +275,12 @@ public:
|
|||
virtual EntityMotionState* createMotionState() { return NULL; }
|
||||
void destroyMotionState();
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
SimulationState getSimulationState() const { return _simulationState; }
|
||||
|
||||
protected:
|
||||
friend class EntityTree;
|
||||
void setSimulationState(SimulationState state) { _simulationState = state; }
|
||||
|
||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
||||
virtual void recalculateCollisionShape();
|
||||
|
||||
|
@ -318,6 +325,7 @@ protected:
|
|||
#ifdef USE_BULLET_PHYSICS
|
||||
EntityMotionState* _motionState;
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
SimulationState _simulationState; // only set by EntityTree
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,93 +20,60 @@
|
|||
#include "EntityItem.h"
|
||||
#include "EntityItemProperties.h"
|
||||
#include "ModelEntityItem.h"
|
||||
#include "TextEntityItem.h"
|
||||
|
||||
EntityItemProperties::EntityItemProperties() :
|
||||
|
||||
CONSTRUCT_PROPERTY(visible, EntityItem::DEFAULT_VISIBLE),
|
||||
CONSTRUCT_PROPERTY(position, 0),
|
||||
CONSTRUCT_PROPERTY(dimensions, EntityItem::DEFAULT_DIMENSIONS),
|
||||
CONSTRUCT_PROPERTY(rotation, EntityItem::DEFAULT_ROTATION),
|
||||
CONSTRUCT_PROPERTY(mass, EntityItem::DEFAULT_MASS),
|
||||
CONSTRUCT_PROPERTY(velocity, EntityItem::DEFAULT_VELOCITY),
|
||||
CONSTRUCT_PROPERTY(gravity, EntityItem::DEFAULT_GRAVITY),
|
||||
CONSTRUCT_PROPERTY(damping, EntityItem::DEFAULT_DAMPING),
|
||||
CONSTRUCT_PROPERTY(lifetime, EntityItem::DEFAULT_LIFETIME),
|
||||
CONSTRUCT_PROPERTY(script, EntityItem::DEFAULT_SCRIPT),
|
||||
CONSTRUCT_PROPERTY(color, ),
|
||||
CONSTRUCT_PROPERTY(modelURL, ""),
|
||||
CONSTRUCT_PROPERTY(animationURL, ""),
|
||||
CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS),
|
||||
CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX),
|
||||
CONSTRUCT_PROPERTY(animationIsPlaying, ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING),
|
||||
CONSTRUCT_PROPERTY(registrationPoint, EntityItem::DEFAULT_REGISTRATION_POINT),
|
||||
CONSTRUCT_PROPERTY(angularVelocity, EntityItem::DEFAULT_ANGULAR_VELOCITY),
|
||||
CONSTRUCT_PROPERTY(angularDamping, EntityItem::DEFAULT_ANGULAR_DAMPING),
|
||||
CONSTRUCT_PROPERTY(ignoreForCollisions, EntityItem::DEFAULT_IGNORE_FOR_COLLISIONS),
|
||||
CONSTRUCT_PROPERTY(collisionsWillMove, EntityItem::DEFAULT_COLLISIONS_WILL_MOVE),
|
||||
CONSTRUCT_PROPERTY(isSpotlight, false),
|
||||
CONSTRUCT_PROPERTY(diffuseColor, ),
|
||||
CONSTRUCT_PROPERTY(ambientColor, ),
|
||||
CONSTRUCT_PROPERTY(specularColor, ),
|
||||
CONSTRUCT_PROPERTY(constantAttenuation, 1.0f),
|
||||
CONSTRUCT_PROPERTY(linearAttenuation, 0.0f),
|
||||
CONSTRUCT_PROPERTY(quadraticAttenuation, 0.0f),
|
||||
CONSTRUCT_PROPERTY(exponent, 0.0f),
|
||||
CONSTRUCT_PROPERTY(cutoff, PI),
|
||||
CONSTRUCT_PROPERTY(locked, false),
|
||||
CONSTRUCT_PROPERTY(textures, ""),
|
||||
CONSTRUCT_PROPERTY(animationSettings, ""),
|
||||
CONSTRUCT_PROPERTY(userData, EntityItem::DEFAULT_USER_DATA),
|
||||
CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT),
|
||||
CONSTRUCT_PROPERTY(lineHeight, TextEntityItem::DEFAULT_LINE_HEIGHT),
|
||||
CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR),
|
||||
CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR),
|
||||
|
||||
_id(UNKNOWN_ENTITY_ID),
|
||||
_idSet(false),
|
||||
_lastEdited(0), // ????
|
||||
_lastEdited(0),
|
||||
_created(UNKNOWN_CREATED_TIME),
|
||||
_type(EntityTypes::Unknown),
|
||||
|
||||
_position(0),
|
||||
_dimensions(EntityItem::DEFAULT_DIMENSIONS),
|
||||
_rotation(EntityItem::DEFAULT_ROTATION),
|
||||
_mass(EntityItem::DEFAULT_MASS),
|
||||
_velocity(EntityItem::DEFAULT_VELOCITY),
|
||||
_gravity(EntityItem::DEFAULT_GRAVITY),
|
||||
_damping(EntityItem::DEFAULT_DAMPING),
|
||||
_lifetime(EntityItem::DEFAULT_LIFETIME),
|
||||
_userData(EntityItem::DEFAULT_USER_DATA),
|
||||
_script(EntityItem::DEFAULT_SCRIPT),
|
||||
_registrationPoint(EntityItem::DEFAULT_REGISTRATION_POINT),
|
||||
_angularVelocity(EntityItem::DEFAULT_ANGULAR_VELOCITY),
|
||||
_angularDamping(EntityItem::DEFAULT_ANGULAR_DAMPING),
|
||||
_visible(EntityItem::DEFAULT_VISIBLE),
|
||||
_ignoreForCollisions(EntityItem::DEFAULT_IGNORE_FOR_COLLISIONS),
|
||||
_collisionsWillMove(EntityItem::DEFAULT_COLLISIONS_WILL_MOVE),
|
||||
|
||||
_positionChanged(false),
|
||||
_dimensionsChanged(false),
|
||||
_rotationChanged(false),
|
||||
_massChanged(false),
|
||||
_velocityChanged(false),
|
||||
_gravityChanged(false),
|
||||
_dampingChanged(false),
|
||||
_lifetimeChanged(false),
|
||||
_userDataChanged(false),
|
||||
_scriptChanged(false),
|
||||
_registrationPointChanged(false),
|
||||
_angularVelocityChanged(false),
|
||||
_angularDampingChanged(false),
|
||||
_visibleChanged(false),
|
||||
_ignoreForCollisionsChanged(false),
|
||||
_collisionsWillMoveChanged(false),
|
||||
|
||||
_color(),
|
||||
_modelURL(""),
|
||||
_animationURL(""),
|
||||
_animationIsPlaying(ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING),
|
||||
_animationFrameIndex(ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX),
|
||||
_animationFPS(ModelEntityItem::DEFAULT_ANIMATION_FPS),
|
||||
_animationSettings(""),
|
||||
_glowLevel(0.0f),
|
||||
_localRenderAlpha(1.0f),
|
||||
_isSpotlight(false),
|
||||
|
||||
_colorChanged(false),
|
||||
_modelURLChanged(false),
|
||||
_animationURLChanged(false),
|
||||
_animationIsPlayingChanged(false),
|
||||
_animationFrameIndexChanged(false),
|
||||
_animationFPSChanged(false),
|
||||
_animationSettingsChanged(false),
|
||||
|
||||
_glowLevelChanged(false),
|
||||
_localRenderAlphaChanged(false),
|
||||
_isSpotlightChanged(false),
|
||||
|
||||
_diffuseColor(),
|
||||
_ambientColor(),
|
||||
_specularColor(),
|
||||
_constantAttenuation(1.0f),
|
||||
_linearAttenuation(0.0f),
|
||||
_quadraticAttenuation(0.0f),
|
||||
_exponent(0.0f),
|
||||
_cutoff(PI),
|
||||
_locked(false),
|
||||
_textures(""),
|
||||
|
||||
_diffuseColorChanged(false),
|
||||
_ambientColorChanged(false),
|
||||
_specularColorChanged(false),
|
||||
_constantAttenuationChanged(false),
|
||||
_linearAttenuationChanged(false),
|
||||
_quadraticAttenuationChanged(false),
|
||||
_exponentChanged(false),
|
||||
_cutoffChanged(false),
|
||||
_lockedChanged(false),
|
||||
_texturesChanged(false),
|
||||
|
||||
_defaultSettings(true),
|
||||
_naturalDimensions(1.0f, 1.0f, 1.0f)
|
||||
|
@ -226,6 +193,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_LOCKED, locked);
|
||||
CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures);
|
||||
CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData);
|
||||
CHECK_PROPERTY_CHANGE(PROP_TEXT, text);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LINE_HEIGHT, lineHeight);
|
||||
CHECK_PROPERTY_CHANGE(PROP_TEXT_COLOR, textColor);
|
||||
CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
@ -280,6 +251,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(locked);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(textures);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(userData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(text);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor());
|
||||
|
||||
// Sitting properties support
|
||||
QScriptValue sittingPoints = engine->newObject();
|
||||
|
@ -355,6 +330,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(textures, setTextures);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(userData, setUserData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(text, setText);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor);
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
@ -494,30 +473,43 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, properties.getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, properties.getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, properties.getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, properties.getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, properties.getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, properties.getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, properties.getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, properties.getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, properties.getAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, appendValue, properties.getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, appendValue, properties.getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, properties.getIgnoreForCollisions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, properties.getCollisionsWillMove());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, properties.getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, appendColor, properties.getDiffuseColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_COLOR, appendColor, properties.getAmbientColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SPECULAR_COLOR, appendColor, properties.getSpecularColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CONSTANT_ATTENUATION, appendValue, properties.getConstantAttenuation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, appendValue, properties.getLinearAttenuation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, appendValue, properties.getQuadraticAttenuation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, properties.getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, properties.getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, properties.getUserData());
|
||||
|
||||
if (properties.getType() == EntityTypes::Text) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, appendValue, properties.getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, properties.getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, properties.getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, properties.getBackgroundColor());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, properties.getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, properties.getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, properties.getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, properties.getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, properties.getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, properties.getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, appendColor, properties.getDiffuseColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_COLOR, appendColor, properties.getAmbientColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SPECULAR_COLOR, appendColor, properties.getSpecularColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CONSTANT_ATTENUATION, appendValue, properties.getConstantAttenuation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, appendValue, properties.getLinearAttenuation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, appendValue, properties.getQuadraticAttenuation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, properties.getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff());
|
||||
}
|
||||
}
|
||||
if (propertyCount > 0) {
|
||||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
@ -705,30 +697,43 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFETIME, float, setLifetime);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_SCRIPT,setScript);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_COLOR, setColor);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MODEL_URL, setModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_URL, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_FOR_COLLISIONS, bool, setIgnoreForCollisions);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONS_WILL_MOVE, bool, setCollisionsWillMove);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_DIFFUSE_COLOR, setDiffuseColor);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_AMBIENT_COLOR, setAmbientColor);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_SPECULAR_COLOR, setSpecularColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CONSTANT_ATTENUATION, float, setConstantAttenuation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINEAR_ATTENUATION, float, setLinearAttenuation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUADRATIC_ATTENUATION, float, setQuadraticAttenuation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_USER_DATA, setUserData);
|
||||
|
||||
if (properties.getType() == EntityTypes::Text) {
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXT, setText);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_TEXT_COLOR, setTextColor);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_BACKGROUND_COLOR, setBackgroundColor);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MODEL_URL, setModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_URL, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_DIFFUSE_COLOR, setDiffuseColor);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_AMBIENT_COLOR, setAmbientColor);
|
||||
READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_SPECULAR_COLOR, setSpecularColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CONSTANT_ATTENUATION, float, setConstantAttenuation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINEAR_ATTENUATION, float, setLinearAttenuation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUADRATIC_ATTENUATION, float, setQuadraticAttenuation);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
@ -800,6 +805,11 @@ void EntityItemProperties::markAllChanged() {
|
|||
_cutoffChanged = true;
|
||||
_lockedChanged = true;
|
||||
_texturesChanged = true;
|
||||
|
||||
_textChanged = true;
|
||||
_lineHeightChanged = true;
|
||||
_textColorChanged = true;
|
||||
_backgroundColorChanged = true;
|
||||
}
|
||||
|
||||
AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const {
|
||||
|
|
|
@ -83,7 +83,14 @@ enum EntityPropertyList {
|
|||
PROP_ANIMATION_SETTINGS,
|
||||
PROP_USER_DATA,
|
||||
|
||||
PROP_LAST_ITEM = PROP_USER_DATA
|
||||
PROP_LAST_ITEM = PROP_USER_DATA,
|
||||
|
||||
// These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter
|
||||
// since the derived class knows how to interpret it's own properties and knows the types it expects
|
||||
PROP_TEXT_COLOR = PROP_COLOR,
|
||||
PROP_TEXT = PROP_MODEL_URL,
|
||||
PROP_LINE_HEIGHT = PROP_ANIMATION_URL,
|
||||
PROP_BACKGROUND_COLOR = PROP_ANIMATION_FPS,
|
||||
};
|
||||
|
||||
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
|
||||
|
@ -102,10 +109,14 @@ class EntityItemProperties {
|
|||
friend class BoxEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class SphereEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class LightEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class TextEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
public:
|
||||
EntityItemProperties();
|
||||
virtual ~EntityItemProperties();
|
||||
|
||||
EntityTypes::EntityType getType() const { return _type; }
|
||||
void setType(EntityTypes::EntityType type) { _type = type; }
|
||||
|
||||
virtual QScriptValue copyToScriptValue(QScriptEngine* engine) const;
|
||||
virtual void copyFromScriptValue(const QScriptValue& object);
|
||||
|
||||
|
@ -123,86 +134,63 @@ public:
|
|||
AABox getAABoxInMeters() const;
|
||||
|
||||
void debugDump() const;
|
||||
void setLastEdited(quint64 usecTime) { _lastEdited = usecTime; }
|
||||
|
||||
DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool);
|
||||
DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat);
|
||||
DEFINE_PROPERTY(PROP_MASS, Mass, mass, float);
|
||||
DEFINE_PROPERTY_REF(PROP_VELOCITY, Velocity, velocity, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_GRAVITY, Gravity, gravity, glm::vec3);
|
||||
DEFINE_PROPERTY(PROP_DAMPING, Damping, damping, float);
|
||||
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float);
|
||||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, AnimationURL, animationURL, QString);
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float);
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_FRAME_INDEX, AnimationFrameIndex, animationFrameIndex, float);
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_PLAYING, AnimationIsPlaying, animationIsPlaying, bool);
|
||||
DEFINE_PROPERTY_REF(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3);
|
||||
DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3);
|
||||
DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float);
|
||||
DEFINE_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, IgnoreForCollisions, ignoreForCollisions, bool);
|
||||
DEFINE_PROPERTY(PROP_COLLISIONS_WILL_MOVE, CollisionsWillMove, collisionsWillMove, bool);
|
||||
DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool);
|
||||
DEFINE_PROPERTY_REF(PROP_DIFFUSE_COLOR, DiffuseColor, diffuseColor, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_AMBIENT_COLOR, AmbientColor, ambientColor, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_SPECULAR_COLOR, SpecularColor, specularColor, xColor);
|
||||
DEFINE_PROPERTY(PROP_CONSTANT_ATTENUATION, ConstantAttenuation, constantAttenuation, float);
|
||||
DEFINE_PROPERTY(PROP_LINEAR_ATTENUATION, LinearAttenuation, linearAttenuation, float);
|
||||
DEFINE_PROPERTY(PROP_QUADRATIC_ATTENUATION, QuadraticAttenuation, quadraticAttenuation, float);
|
||||
DEFINE_PROPERTY(PROP_EXPONENT, Exponent, exponent, float);
|
||||
DEFINE_PROPERTY(PROP_CUTOFF, Cutoff, cutoff, float);
|
||||
DEFINE_PROPERTY(PROP_LOCKED, Locked, locked, bool);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString);
|
||||
DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(PROP_ANIMATION_SETTINGS, AnimationSettings, animationSettings, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_USER_DATA, UserData, userData, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT, Text, text, QString);
|
||||
DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor);
|
||||
|
||||
// properties of all entities
|
||||
EntityTypes::EntityType getType() const { return _type; }
|
||||
|
||||
void setType(EntityTypes::EntityType type) { _type = type; }
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
/// set position in meter units, will be clamped to domain bounds
|
||||
void setPosition(const glm::vec3& value) { _position = glm::clamp(value, 0.0f, (float)TREE_SCALE); _positionChanged = true; }
|
||||
|
||||
|
||||
const glm::vec3& getDimensions() const { return _dimensions; }
|
||||
void setDimensions(const glm::vec3& value) { _dimensions = value; _dimensionsChanged = true; }
|
||||
public:
|
||||
float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); }
|
||||
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
void setRotation(const glm::quat& rotation) { _rotation = rotation; _rotationChanged = true; }
|
||||
|
||||
float getMass() const { return _mass; }
|
||||
void setMass(float value) { _mass = value; _massChanged = true; }
|
||||
|
||||
/// velocity in meters (0.0-1.0) per second
|
||||
const glm::vec3& getVelocity() const { return _velocity; }
|
||||
/// velocity in meters (0.0-1.0) per second
|
||||
void setVelocity(const glm::vec3& value) { _velocity = value; _velocityChanged = true; }
|
||||
|
||||
/// gravity in meters (0.0-TREE_SCALE) per second squared
|
||||
const glm::vec3& getGravity() const { return _gravity; }
|
||||
/// gravity in meters (0.0-TREE_SCALE) per second squared
|
||||
void setGravity(const glm::vec3& value) { _gravity = value; _gravityChanged = true; }
|
||||
|
||||
float getDamping() const { return _damping; }
|
||||
void setDamping(float value) { _damping = value; _dampingChanged = true; }
|
||||
|
||||
float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity
|
||||
void setLifetime(float value) { _lifetime = value; _lifetimeChanged = true; } /// set the lifetime in seconds for the entity
|
||||
|
||||
const QString& getUserData() const { return _userData; }
|
||||
void setUserData(const QString& value) { _userData = value; _userDataChanged = true; }
|
||||
|
||||
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
|
||||
quint64 getCreated() const { return _created; }
|
||||
void setCreated(quint64 usecTime) { _created = usecTime; }
|
||||
bool hasCreatedTime() const { return (_created != UNKNOWN_CREATED_TIME); }
|
||||
|
||||
|
||||
// NOTE: how do we handle _defaultSettings???
|
||||
bool containsBoundsProperties() const { return (_positionChanged || _dimensionsChanged); }
|
||||
bool containsPositionChange() const { return _positionChanged; }
|
||||
bool containsDimensionsChange() const { return _dimensionsChanged; }
|
||||
|
||||
// TODO: this need to be more generic. for now, we're going to have the properties class support these as
|
||||
// named getter/setters, but we want to move them to generic types...
|
||||
// properties we want to move to just models and particles
|
||||
xColor getColor() const { return _color; }
|
||||
const QString& getModelURL() const { return _modelURL; }
|
||||
const QString& getAnimationURL() const { return _animationURL; }
|
||||
float getAnimationFrameIndex() const { return _animationFrameIndex; }
|
||||
bool getAnimationIsPlaying() const { return _animationIsPlaying; }
|
||||
float getAnimationFPS() const { return _animationFPS; }
|
||||
QString getAnimationSettings() const;
|
||||
|
||||
float getGlowLevel() const { return _glowLevel; }
|
||||
float getLocalRenderAlpha() const { return _localRenderAlpha; }
|
||||
const QString& getScript() const { return _script; }
|
||||
|
||||
// model related properties
|
||||
void setColor(const xColor& value) { _color = value; _colorChanged = true; }
|
||||
void setModelURL(const QString& url) { _modelURL = url; _modelURLChanged = true; }
|
||||
void setAnimationURL(const QString& url) { _animationURL = url; _animationURLChanged = true; }
|
||||
void setAnimationFrameIndex(float value) { _animationFrameIndex = value; _animationFrameIndexChanged = true; }
|
||||
void setAnimationIsPlaying(bool value) { _animationIsPlaying = value; _animationIsPlayingChanged = true; }
|
||||
void setAnimationFPS(float value) { _animationFPS = value; _animationFPSChanged = true; }
|
||||
void setAnimationSettings(const QString& value);
|
||||
|
||||
void setGlowLevel(float value) { _glowLevel = value; _glowLevelChanged = true; }
|
||||
void setLocalRenderAlpha(float value) { _localRenderAlpha = value; _localRenderAlphaChanged = true; }
|
||||
void setScript(const QString& value) { _script = value; _scriptChanged = true; }
|
||||
|
||||
|
||||
static bool encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut);
|
||||
|
@ -214,23 +202,6 @@ public:
|
|||
static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
|
||||
EntityItemID& entityID, EntityItemProperties& properties);
|
||||
|
||||
bool positionChanged() const { return _positionChanged; }
|
||||
bool rotationChanged() const { return _rotationChanged; }
|
||||
bool massChanged() const { return _massChanged; }
|
||||
bool velocityChanged() const { return _velocityChanged; }
|
||||
bool gravityChanged() const { return _gravityChanged; }
|
||||
bool dampingChanged() const { return _dampingChanged; }
|
||||
bool lifetimeChanged() const { return _lifetimeChanged; }
|
||||
bool userDataChanged() const { return _userDataChanged; }
|
||||
bool scriptChanged() const { return _scriptChanged; }
|
||||
bool dimensionsChanged() const { return _dimensionsChanged; }
|
||||
bool registrationPointChanged() const { return _registrationPointChanged; }
|
||||
bool colorChanged() const { return _colorChanged; }
|
||||
bool modelURLChanged() const { return _modelURLChanged; }
|
||||
bool animationURLChanged() const { return _animationURLChanged; }
|
||||
bool animationIsPlayingChanged() const { return _animationIsPlayingChanged; }
|
||||
bool animationFrameIndexChanged() const { return _animationFrameIndexChanged; }
|
||||
bool animationFPSChanged() const { return _animationFPSChanged; }
|
||||
bool glowLevelChanged() const { return _glowLevelChanged; }
|
||||
bool localRenderAlphaChanged() const { return _localRenderAlphaChanged; }
|
||||
|
||||
|
@ -238,161 +209,26 @@ public:
|
|||
void markAllChanged();
|
||||
|
||||
void setSittingPoints(const QVector<SittingPoint>& sittingPoints);
|
||||
|
||||
|
||||
const glm::vec3& getNaturalDimensions() const { return _naturalDimensions; }
|
||||
void setNaturalDimensions(const glm::vec3& value) { _naturalDimensions = value; }
|
||||
|
||||
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; }
|
||||
void setRegistrationPoint(const glm::vec3& value) { _registrationPoint = value; _registrationPointChanged = true; }
|
||||
|
||||
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
|
||||
void setAngularVelocity(const glm::vec3& value) { _angularVelocity = value; _angularVelocityChanged = true; }
|
||||
|
||||
float getAngularDamping() const { return _angularDamping; }
|
||||
void setAngularDamping(float value) { _angularDamping = value; _angularDampingChanged = true; }
|
||||
|
||||
bool getVisible() const { return _visible; }
|
||||
void setVisible(bool value) { _visible = value; _visibleChanged = true; }
|
||||
|
||||
bool getIgnoreForCollisions() const { return _ignoreForCollisions; }
|
||||
void setIgnoreForCollisions(bool value) { _ignoreForCollisions = value; _ignoreForCollisionsChanged = true; }
|
||||
|
||||
bool getCollisionsWillMove() const { return _collisionsWillMove; }
|
||||
void setCollisionsWillMove(bool value) { _collisionsWillMove = value; _collisionsWillMoveChanged = true; }
|
||||
|
||||
bool getIsSpotlight() const { return _isSpotlight; }
|
||||
void setIsSpotlight(bool value) { _isSpotlight = value; _isSpotlightChanged = true; }
|
||||
|
||||
xColor getDiffuseColor() const { return _diffuseColor; }
|
||||
xColor getAmbientColor() const { return _ambientColor; }
|
||||
xColor getSpecularColor() const { return _specularColor; }
|
||||
|
||||
void setDiffuseColor(const xColor& value) { _diffuseColor = value; _diffuseColorChanged = true; }
|
||||
void setAmbientColor(const xColor& value) { _ambientColor = value; _ambientColorChanged = true; }
|
||||
void setSpecularColor(const xColor& value) { _specularColor = value; _specularColorChanged = true; }
|
||||
|
||||
bool diffuseColorChanged() const { return _colorChanged; }
|
||||
bool ambientColorChanged() const { return _ambientColorChanged; }
|
||||
bool specularColorChanged() const { return _specularColorChanged; }
|
||||
|
||||
float getConstantAttenuation() const { return _constantAttenuation; }
|
||||
void setConstantAttenuation(float value) { _constantAttenuation = value; _constantAttenuationChanged = true; }
|
||||
|
||||
float getLinearAttenuation() const { return _linearAttenuation; }
|
||||
void setLinearAttenuation(float value) { _linearAttenuation = value; _linearAttenuationChanged = true; }
|
||||
|
||||
float getQuadraticAttenuation() const { return _quadraticAttenuation; }
|
||||
void setQuadraticAttenuation(float value) { _quadraticAttenuation = value; _quadraticAttenuationChanged = true; }
|
||||
|
||||
float getExponent() const { return _exponent; }
|
||||
void setExponent(float value) { _exponent = value; _exponentChanged = true; }
|
||||
|
||||
float getCutoff() const { return _cutoff; }
|
||||
void setCutoff(float value) { _cutoff = value; _cutoffChanged = true; }
|
||||
|
||||
bool getLocked() const { return _locked; }
|
||||
void setLocked(bool value) { _locked = value; _lockedChanged = true; }
|
||||
bool lockedChanged() const { return _lockedChanged; }
|
||||
|
||||
const QString& getTextures() const { return _textures; }
|
||||
void setTextures(const QString& value) { _textures = value; _texturesChanged = true; }
|
||||
|
||||
const QStringList& getTextureNames() const { return _textureNames; }
|
||||
void setTextureNames(const QStringList& value) { _textureNames = value; }
|
||||
|
||||
void setLastEdited(quint64 usecTime) { _lastEdited = usecTime; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
QUuid _id;
|
||||
bool _idSet;
|
||||
quint64 _lastEdited;
|
||||
quint64 _created;
|
||||
|
||||
EntityTypes::EntityType _type;
|
||||
|
||||
void setType(const QString& typeName) { _type = EntityTypes::getEntityTypeFromName(typeName); }
|
||||
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _dimensions;
|
||||
glm::quat _rotation;
|
||||
float _mass;
|
||||
glm::vec3 _velocity;
|
||||
glm::vec3 _gravity;
|
||||
float _damping;
|
||||
float _lifetime;
|
||||
QString _userData;
|
||||
QString _script;
|
||||
glm::vec3 _registrationPoint;
|
||||
glm::vec3 _angularVelocity;
|
||||
float _angularDamping;
|
||||
bool _visible;
|
||||
bool _ignoreForCollisions;
|
||||
bool _collisionsWillMove;
|
||||
|
||||
bool _positionChanged;
|
||||
bool _dimensionsChanged;
|
||||
bool _rotationChanged;
|
||||
bool _massChanged;
|
||||
bool _velocityChanged;
|
||||
bool _gravityChanged;
|
||||
bool _dampingChanged;
|
||||
bool _lifetimeChanged;
|
||||
bool _userDataChanged;
|
||||
bool _scriptChanged;
|
||||
bool _registrationPointChanged;
|
||||
bool _angularVelocityChanged;
|
||||
bool _angularDampingChanged;
|
||||
bool _visibleChanged;
|
||||
bool _ignoreForCollisionsChanged;
|
||||
bool _collisionsWillMoveChanged;
|
||||
|
||||
// TODO: this need to be more generic. for now, we're going to have the properties class support these as
|
||||
// named getter/setters, but we want to move them to generic types...
|
||||
xColor _color;
|
||||
QString _modelURL;
|
||||
QString _animationURL;
|
||||
bool _animationIsPlaying;
|
||||
float _animationFrameIndex;
|
||||
float _animationFPS;
|
||||
QString _animationSettings;
|
||||
float _glowLevel;
|
||||
float _localRenderAlpha;
|
||||
bool _isSpotlight;
|
||||
|
||||
bool _colorChanged;
|
||||
bool _modelURLChanged;
|
||||
bool _animationURLChanged;
|
||||
bool _animationIsPlayingChanged;
|
||||
bool _animationFrameIndexChanged;
|
||||
bool _animationFPSChanged;
|
||||
bool _animationSettingsChanged;
|
||||
bool _glowLevelChanged;
|
||||
bool _localRenderAlphaChanged;
|
||||
bool _isSpotlightChanged;
|
||||
|
||||
xColor _diffuseColor;
|
||||
xColor _ambientColor;
|
||||
xColor _specularColor;
|
||||
float _constantAttenuation;
|
||||
float _linearAttenuation;
|
||||
float _quadraticAttenuation;
|
||||
float _exponent;
|
||||
float _cutoff;
|
||||
bool _locked;
|
||||
QString _textures;
|
||||
|
||||
bool _diffuseColorChanged;
|
||||
bool _ambientColorChanged;
|
||||
bool _specularColorChanged;
|
||||
bool _constantAttenuationChanged;
|
||||
bool _linearAttenuationChanged;
|
||||
bool _quadraticAttenuationChanged;
|
||||
bool _exponentChanged;
|
||||
bool _cutoffChanged;
|
||||
bool _lockedChanged;
|
||||
bool _texturesChanged;
|
||||
|
||||
bool _defaultSettings;
|
||||
|
||||
// NOTE: The following are pseudo client only properties. They are only used in clients which can access
|
||||
|
@ -406,6 +242,11 @@ QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const Enti
|
|||
void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemProperties& properties);
|
||||
|
||||
|
||||
// define these inline here so the macros work
|
||||
inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
||||
{ _position = glm::clamp(value, 0.0f, (float)TREE_SCALE); _positionChanged = true; }
|
||||
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||
debug << "EntityItemProperties[" << "\n"
|
||||
<< " position:" << properties.getPosition() << "in meters" << "\n"
|
||||
|
|
|
@ -260,6 +260,46 @@
|
|||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONSTRUCT_PROPERTY(n, V) \
|
||||
_##n(V), \
|
||||
_##n##Changed(false)
|
||||
|
||||
#define DEFINE_PROPERTY(P, N, n, T) \
|
||||
public: \
|
||||
T get##N() const { return _##n; } \
|
||||
void set##N(T value) { _##n = value; _##n##Changed = true; } \
|
||||
bool n##Changed() const { return _##n##Changed; } \
|
||||
private: \
|
||||
T _##n; \
|
||||
bool _##n##Changed;
|
||||
|
||||
#define DEFINE_PROPERTY_REF(P, N, n, T) \
|
||||
public: \
|
||||
const T& get##N() const { return _##n; } \
|
||||
void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
|
||||
bool n##Changed() const { return _##n##Changed; } \
|
||||
private: \
|
||||
T _##n; \
|
||||
bool _##n##Changed;
|
||||
|
||||
#define DEFINE_PROPERTY_REF_WITH_SETTER(P, N, n, T) \
|
||||
public: \
|
||||
const T& get##N() const { return _##n; } \
|
||||
void set##N(const T& value); \
|
||||
bool n##Changed() const; \
|
||||
private: \
|
||||
T _##n; \
|
||||
bool _##n##Changed;
|
||||
|
||||
#define DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(P, N, n, T) \
|
||||
public: \
|
||||
T get##N() const; \
|
||||
void set##N(const T& value); \
|
||||
bool n##Changed() const; \
|
||||
private: \
|
||||
T _##n; \
|
||||
bool _##n##Changed;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -93,7 +93,6 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(EntityItemID
|
|||
|
||||
EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const EntityItemProperties& properties) {
|
||||
EntityItemID actualID = entityID;
|
||||
|
||||
// if the entity is unknown, attempt to look it up
|
||||
if (!entityID.isKnownID) {
|
||||
actualID = EntityItemID::getIDfromCreatorTokenID(entityID.creatorTokenID);
|
||||
|
@ -113,6 +112,18 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E
|
|||
|
||||
// if at this point, we know the id, send the update to the entity server
|
||||
if (entityID.isKnownID) {
|
||||
// make sure the properties has a type, so that the encode can know which properties to include
|
||||
if (properties.getType() == EntityTypes::Unknown) {
|
||||
EntityItem* entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (entity) {
|
||||
EntityItemProperties tempProperties = properties;
|
||||
tempProperties.setType(entity->getType());
|
||||
queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, tempProperties);
|
||||
return entityID;
|
||||
}
|
||||
}
|
||||
|
||||
// if the properties already includes the type, then use it as is
|
||||
queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, properties);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ void EntityTree::addEntityItem(EntityItem* entity) {
|
|||
EntityItemID entityID = entity->getEntityItemID();
|
||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
if (containingElement) {
|
||||
qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing entity items. entityID=" << entityID;
|
||||
qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing EntityItems. entityID=" << entityID;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -90,8 +90,7 @@ void EntityTree::addEntityItem(EntityItem* entity) {
|
|||
AddEntityOperator theOperator(this, entity);
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
|
||||
// check to see if we need to simulate this entity..
|
||||
changeEntityState(entity, EntityItem::Static, entity->computeSimulationState());
|
||||
updateEntityState(entity);
|
||||
|
||||
if (_physicsEngine && !entity->getMotionState()) {
|
||||
addEntityToPhysicsEngine(entity);
|
||||
|
@ -129,17 +128,13 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
|
|||
}
|
||||
} else {
|
||||
// check to see if we need to simulate this entity...
|
||||
EntityItem::SimulationState oldState = existingEntity->computeSimulationState();
|
||||
QString entityScriptBefore = existingEntity->getScript();
|
||||
|
||||
UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties);
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
_isDirty = true;
|
||||
|
||||
EntityItem::SimulationState newState = existingEntity->computeSimulationState();
|
||||
if (newState != oldState) {
|
||||
changeEntityState(existingEntity, oldState, newState);
|
||||
}
|
||||
updateEntityState(existingEntity);
|
||||
|
||||
QString entityScriptAfter = existingEntity->getScript();
|
||||
if (entityScriptBefore != entityScriptAfter) {
|
||||
|
@ -202,7 +197,9 @@ void EntityTree::trackDeletedEntity(const EntityItemID& entityID) {
|
|||
|
||||
void EntityTree::setPhysicsEngine(PhysicsEngine* engine) {
|
||||
if (_physicsEngine) {
|
||||
#ifdef USE_BULLET_PHYSICS
|
||||
// TODO: remove all entities before we clear the engine
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
}
|
||||
_physicsEngine = engine;
|
||||
}
|
||||
|
@ -592,10 +589,41 @@ void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncod
|
|||
extraEncodeData->clear();
|
||||
}
|
||||
|
||||
void EntityTree::changeEntityState(EntityItem* const entity,
|
||||
EntityItem::SimulationState oldState, EntityItem::SimulationState newState) {
|
||||
void EntityTree::updateEntityState(EntityItem* entity) {
|
||||
EntityItem::SimulationState oldState = entity->getSimulationState();
|
||||
EntityItem::SimulationState newState = entity->computeSimulationState();
|
||||
if (newState != oldState) {
|
||||
switch (oldState) {
|
||||
case EntityItem::Moving:
|
||||
_movingEntities.removeAll(entity);
|
||||
break;
|
||||
|
||||
case EntityItem::Mortal:
|
||||
_mortalEntities.removeAll(entity);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (newState) {
|
||||
case EntityItem::Moving:
|
||||
_movingEntities.push_back(entity);
|
||||
break;
|
||||
|
||||
case EntityItem::Mortal:
|
||||
_mortalEntities.push_back(entity);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
entity->setSimulationState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can we short circuit this if the state isn't changing?
|
||||
void EntityTree::clearEntityState(EntityItem* entity) {
|
||||
EntityItem::SimulationState oldState = entity->getSimulationState();
|
||||
switch (oldState) {
|
||||
case EntityItem::Moving:
|
||||
_movingEntities.removeAll(entity);
|
||||
|
@ -608,20 +636,7 @@ void EntityTree::changeEntityState(EntityItem* const entity,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (newState) {
|
||||
case EntityItem::Moving:
|
||||
_movingEntities.push_back(entity);
|
||||
break;
|
||||
|
||||
case EntityItem::Mortal:
|
||||
_mortalEntities.push_back(entity);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
entity->setSimulationState(EntityItem::Static);
|
||||
}
|
||||
|
||||
void EntityTree::entityChanged(EntityItem* entity) {
|
||||
|
@ -629,20 +644,24 @@ void EntityTree::entityChanged(EntityItem* entity) {
|
|||
}
|
||||
|
||||
void EntityTree::addEntityToPhysicsEngine(EntityItem* entity) {
|
||||
#ifdef USE_BULLET_PHYSICS
|
||||
EntityMotionState* motionState = entity->createMotionState();
|
||||
if (!_physicsEngine->addEntity(static_cast<CustomMotionState*>(motionState))) {
|
||||
// failed to add to engine: probably because of bad shape,
|
||||
// probably because entity is too big or too small
|
||||
entity->destroyMotionState();
|
||||
}
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
}
|
||||
|
||||
void EntityTree::removeEntityFromPhysicsEngine(EntityItem* entity) {
|
||||
#ifdef USE_BULLET_PHYSICS
|
||||
EntityMotionState* motionState = entity->getMotionState();
|
||||
if (motionState) {
|
||||
_physicsEngine->removeEntity(static_cast<CustomMotionState*>(motionState));
|
||||
entity->destroyMotionState();
|
||||
}
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
}
|
||||
|
||||
void EntityTree::update() {
|
||||
|
@ -669,52 +688,25 @@ void EntityTree::update() {
|
|||
}
|
||||
|
||||
void EntityTree::updateChangedEntities(quint64 now, QSet<EntityItemID>& entitiesToDelete) {
|
||||
QSet<EntityItem*> entitiesBecomingStatic;
|
||||
QSet<EntityItem*> entitiesBecomingMortal;
|
||||
QSet<EntityItem*> entitiesBecomingMoving;
|
||||
|
||||
// TODO: switch these to iterators so we can remove items that get deleted
|
||||
foreach (EntityItem* thisEntity, _changedEntities) {
|
||||
// check to see if the lifetime has expired, for immortal entities this is always false
|
||||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
qDebug() << "Lifetime has expired for thisEntity:" << thisEntity->getEntityItemID();
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
clearEntityState(thisEntity);
|
||||
} else {
|
||||
// TODO: Andrew to push changes to physics engine (when we know how to sort the changes)
|
||||
EntityItem::SimulationState newState = thisEntity->computeSimulationState();
|
||||
|
||||
if (newState == EntityItem::Static) {
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
} else if (newState == EntityItem::Mortal) {
|
||||
entitiesBecomingMortal << thisEntity;
|
||||
} else if (newState == EntityItem::Moving) {
|
||||
entitiesBecomingMoving << thisEntity;
|
||||
}
|
||||
updateEntityState(thisEntity);
|
||||
}
|
||||
}
|
||||
_changedEntities.clear();
|
||||
|
||||
// change state for any entities that were changing but are now either static, mortal, or moving
|
||||
foreach(EntityItem* entity, entitiesBecomingStatic) {
|
||||
changeEntityState(entity, EntityItem::Changing, EntityItem::Static);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingMortal) {
|
||||
changeEntityState(entity, EntityItem::Changing, EntityItem::Mortal);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingMoving) {
|
||||
changeEntityState(entity, EntityItem::Changing, EntityItem::Moving);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTree::updateMovingEntities(quint64 now, QSet<EntityItemID>& entitiesToDelete) {
|
||||
PerformanceTimer perfTimer("updateMovingEntities");
|
||||
if (_movingEntities.size() > 0) {
|
||||
MovingEntitiesOperator moveOperator(this);
|
||||
|
||||
QSet<EntityItem*> entitiesBecomingStatic;
|
||||
QSet<EntityItem*> entitiesBecomingMortal;
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("_movingEntities");
|
||||
|
||||
|
@ -726,7 +718,7 @@ void EntityTree::updateMovingEntities(quint64 now, QSet<EntityItemID>& entitiesT
|
|||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
clearEntityState(thisEntity);
|
||||
} else {
|
||||
AACube oldCube, newCube;
|
||||
EntityMotionState* motionState = thisEntity->getMotionState();
|
||||
|
@ -743,17 +735,10 @@ void EntityTree::updateMovingEntities(quint64 now, QSet<EntityItemID>& entitiesT
|
|||
if (!domainBounds.touches(newCube)) {
|
||||
qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds.";
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
clearEntityState(thisEntity);
|
||||
} else {
|
||||
moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube);
|
||||
|
||||
// check to see if this entity is no longer moving
|
||||
EntityItem::SimulationState newState = thisEntity->computeSimulationState();
|
||||
if (newState == EntityItem::Mortal) {
|
||||
entitiesBecomingMortal << thisEntity;
|
||||
} else if (newState == EntityItem::Static) {
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
}
|
||||
updateEntityState(thisEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -762,21 +747,10 @@ void EntityTree::updateMovingEntities(quint64 now, QSet<EntityItemID>& entitiesT
|
|||
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
||||
recurseTreeWithOperator(&moveOperator);
|
||||
}
|
||||
|
||||
// change state for any entities that were moving but are now either static, mortal, or changing
|
||||
foreach(EntityItem* entity, entitiesBecomingStatic) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Static);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingMortal) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Mortal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTree::updateMortalEntities(quint64 now, QSet<EntityItemID>& entitiesToDelete) {
|
||||
QSet<EntityItem*> entitiesBecomingStatic;
|
||||
QSet<EntityItem*> entitiesBecomingMoving;
|
||||
|
||||
// TODO: switch these to iterators so we can remove items that get deleted
|
||||
for (int i = 0; i < _mortalEntities.size(); i++) {
|
||||
EntityItem* thisEntity = _mortalEntities[i];
|
||||
|
@ -785,26 +759,12 @@ void EntityTree::updateMortalEntities(quint64 now, QSet<EntityItemID>& entitiesT
|
|||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
clearEntityState(thisEntity);
|
||||
} else {
|
||||
// check to see if this entity is no longer moving
|
||||
EntityItem::SimulationState newState = thisEntity->computeSimulationState();
|
||||
|
||||
if (newState == EntityItem::Static) {
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
} else if (newState == EntityItem::Moving) {
|
||||
entitiesBecomingMoving << thisEntity;
|
||||
}
|
||||
updateEntityState(thisEntity);
|
||||
}
|
||||
}
|
||||
|
||||
// change state for any entities that were mortal but are now either static, changing, or moving
|
||||
foreach(EntityItem* entity, entitiesBecomingStatic) {
|
||||
changeEntityState(entity, EntityItem::Mortal, EntityItem::Static);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingMoving) {
|
||||
changeEntityState(entity, EntityItem::Mortal, EntityItem::Moving);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1107,7 +1067,6 @@ bool DebugOperator::preRecursion(OctreeElement* element) {
|
|||
}
|
||||
|
||||
void EntityTree::dumpTree() {
|
||||
// First, look for the existing entity in the tree..
|
||||
DebugOperator theOperator;
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
}
|
||||
|
@ -1125,7 +1084,6 @@ bool PruneOperator::postRecursion(OctreeElement* element) {
|
|||
}
|
||||
|
||||
void EntityTree::pruneTree() {
|
||||
// First, look for the existing entity in the tree..
|
||||
PruneOperator theOperator;
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
}
|
||||
|
|
|
@ -138,8 +138,8 @@ public:
|
|||
|
||||
void sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z);
|
||||
|
||||
void changeEntityState(EntityItem* const entity,
|
||||
EntityItem::SimulationState oldState, EntityItem::SimulationState newState);
|
||||
void updateEntityState(EntityItem* entity);
|
||||
void clearEntityState(EntityItem* entity);
|
||||
|
||||
void entityChanged(EntityItem* entity);
|
||||
void addEntityToPhysicsEngine(EntityItem* entity);
|
||||
|
|
|
@ -775,9 +775,8 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
addEntityItem(entityItem); // add this new entity to this elements entities
|
||||
entityItemID = entityItem->getEntityItemID();
|
||||
_myTree->setContainingElement(entityItemID, this);
|
||||
_myTree->updateEntityState(entityItem);
|
||||
_myTree->emitAddingEntity(entityItemID); // we just added an entity
|
||||
EntityItem::SimulationState newState = entityItem->computeSimulationState();
|
||||
_myTree->changeEntityState(entityItem, EntityItem::Static, newState);
|
||||
}
|
||||
}
|
||||
// Move the buffer forward to read more entities
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "LightEntityItem.h"
|
||||
#include "ModelEntityItem.h"
|
||||
#include "SphereEntityItem.h"
|
||||
#include "TextEntityItem.h"
|
||||
|
||||
QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap;
|
||||
QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap;
|
||||
|
@ -35,6 +36,7 @@ REGISTER_ENTITY_TYPE(Model)
|
|||
REGISTER_ENTITY_TYPE(Box)
|
||||
REGISTER_ENTITY_TYPE(Sphere)
|
||||
REGISTER_ENTITY_TYPE(Light)
|
||||
REGISTER_ENTITY_TYPE(Text)
|
||||
|
||||
|
||||
const QString& EntityTypes::getEntityTypeName(EntityType entityType) {
|
||||
|
|
|
@ -34,7 +34,8 @@ public:
|
|||
Box,
|
||||
Sphere,
|
||||
Light,
|
||||
LAST = Light
|
||||
Text,
|
||||
LAST = Text
|
||||
} EntityType;
|
||||
|
||||
static const QString& getEntityTypeName(EntityType entityType);
|
||||
|
|
113
libraries/entities/src/TextEntityItem.cpp
Normal file
113
libraries/entities/src/TextEntityItem.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// TextEntityItem.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "TextEntityItem.h"
|
||||
|
||||
|
||||
const QString TextEntityItem::DEFAULT_TEXT("");
|
||||
const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f;
|
||||
const xColor TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 };
|
||||
const xColor TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
|
||||
|
||||
EntityItem* TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItem* result = new TextEntityItem(entityID, properties);
|
||||
return result;
|
||||
}
|
||||
|
||||
TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
_type = EntityTypes::Text;
|
||||
_created = properties.getCreated();
|
||||
setProperties(properties, true);
|
||||
}
|
||||
|
||||
EntityItemProperties TextEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textColor, getTextColorX);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundColor, getBackgroundColorX);
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool TextEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) {
|
||||
bool somethingChanged = false;
|
||||
somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textColor, setTextColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundColor, setBackgroundColor);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "TextEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
|
||||
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_TEXT, setText);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, _lineHeight);
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_TEXT_COLOR, _textColor);
|
||||
READ_ENTITY_PROPERTY_COLOR(PROP_BACKGROUND_COLOR, _backgroundColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_TEXT;
|
||||
requestedProperties += PROP_LINE_HEIGHT;
|
||||
requestedProperties += PROP_TEXT_COLOR;
|
||||
requestedProperties += PROP_BACKGROUND_COLOR;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, appendValue, getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor());
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue