Merge pull request #3710 from ZappoMan/lockAndMaterialProperties

Improvements to Entities
This commit is contained in:
AndrewMeadows 2014-11-03 08:41:55 -08:00
commit 80a385b23a
10 changed files with 125 additions and 47 deletions

View file

@ -2787,13 +2787,13 @@ function setupModelMenus() {
print("delete exists... don't add ours");
}
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
afterItem: "Paste Models", isCheckable: true });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S",
afterItem: "Allow Select Large Models", isCheckable: true });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List", afterItem: "Models" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" });
@ -2809,6 +2809,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", "Delete");
}
Menu.removeMenuItem("Edit", "Model List...");
Menu.removeMenuItem("Edit", "Paste Models");
Menu.removeMenuItem("Edit", "Allow Select Large Models");
Menu.removeMenuItem("Edit", "Allow Select Small Models");
@ -2883,16 +2884,21 @@ function handeMenuEvent(menuItem) {
} else {
print(" Delete Entity.... not holding...");
}
} else if (menuItem == "Model List") {
} else if (menuItem == "Model List...") {
var models = new Array();
models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE);
for (var i = 0; i < models.length; i++) {
models[i].properties = Entities.getEntityProperties(models[i]);
models[i].toString = function() {
var modelname = decodeURIComponent(
this.properties.modelURL.indexOf("/") != -1 ?
this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) :
this.properties.modelURL);
var modelname;
if (this.properties.type == "Model") {
modelname = decodeURIComponent(
this.properties.modelURL.indexOf("/") != -1 ?
this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) :
this.properties.modelURL);
} else {
modelname = this.properties.id;
}
return "[" + this.properties.type + "] " + modelname;
};
}

View file

@ -174,7 +174,7 @@ function maybeCleanupLobby() {
function toggleEnvironmentRendering(shouldRender) {
Menu.setIsOptionChecked("Voxels", shouldRender);
Menu.setIsOptionChecked("Models", shouldRender);
Menu.setIsOptionChecked("Entities", shouldRender);
Menu.setIsOptionChecked("Metavoxels", shouldRender);
Menu.setIsOptionChecked("Avatars", shouldRender);
}

View file

@ -564,6 +564,7 @@ function setupModelMenus() {
print("delete exists... don't add ours");
}
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
afterItem: "Paste Models", isCheckable: true });
@ -586,6 +587,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", "Delete");
}
Menu.removeMenuItem("Edit", "Model List...");
Menu.removeMenuItem("Edit", "Paste Models");
Menu.removeMenuItem("Edit", "Allow Select Large Models");
Menu.removeMenuItem("Edit", "Allow Select Small Models");
@ -640,6 +642,38 @@ function handeMenuEvent(menuItem) {
} else {
print(" Delete Entity.... not holding...");
}
} else if (menuItem == "Model List...") {
var models = new Array();
models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE);
for (var i = 0; i < models.length; i++) {
models[i].properties = Entities.getEntityProperties(models[i]);
models[i].toString = function() {
var modelname;
if (this.properties.type == "Model") {
modelname = decodeURIComponent(
this.properties.modelURL.indexOf("/") != -1 ?
this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) :
this.properties.modelURL);
} else {
modelname = this.properties.id;
}
return "[" + this.properties.type + "] " + modelname;
};
}
var form = [{label: "Model: ", options: models}];
form.push({label: "Action: ", options: ["Properties", "Delete", "Teleport"]});
form.push({ button: "Cancel" });
if (Window.form("Model List", form)) {
var selectedModel = form[0].value;
if (form[1].value == "Properties") {
editModelID = selectedModel;
showPropertiesForm(editModelID);
} else if (form[1].value == "Delete") {
Entities.deleteEntity(selectedModel);
} else if (form[1].value == "Teleport") {
MyAvatar.position = selectedModel.properties.position;
}
}
} else if (menuItem == "Edit Properties...") {
// good place to put the properties dialog

View file

@ -2335,7 +2335,7 @@ void Application::update(float deltaTime) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
queryOctree(NodeType::EntityServer, PacketTypeEntityQuery, _entityServerJurisdictions);
}
_lastQueriedViewFrustum = _viewFrustum;
@ -2982,7 +2982,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
}
// render models...
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
PerformanceTimer perfTimer("entities");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... entities...");

View file

@ -366,7 +366,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Avatars, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Models, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Entities, 0, true);
QMenu* shadowMenu = renderOptionsMenu->addMenu("Shadows");
QActionGroup* shadowGroup = new QActionGroup(shadowMenu);
@ -433,14 +433,16 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
QMenu* modelDebugMenu = developerMenu->addMenu("Models");
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
QMenu* modelCullingMenu = modelDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontReduceMaterialSwitches, 0, false);
QMenu* entitiesDebugMenu = developerMenu->addMenu("Entities");
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
addCheckableActionToQMenuAndActionHash(entitiesDebugMenu, MenuOption::DisableLightEntities, 0, false);
QMenu* entityCullingMenu = entitiesDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(entityCullingMenu, MenuOption::DontReduceMaterialSwitches, 0, false);
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels");
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);

View file

@ -384,6 +384,7 @@ namespace MenuOption {
const QString DecreaseVoxelSize = "Decrease Voxel Size";
const QString DisableActivityLogger = "Disable Activity Logger";
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
const QString DisableLightEntities = "Disable Light Entities";
const QString DisableNackPackets = "Disable NACK Packets";
const QString DisplayFrustum = "Display Frustum";
const QString DisplayHands = "Show Hand Info";
@ -400,6 +401,7 @@ namespace MenuOption {
const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableGlowEffect = "Enable Glow Effect (Warning: Poor Oculus Performance)";
const QString EnableVRMode = "Enable VR Mode";
const QString Entities = "Entities";
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
const QString ExpandOtherAvatarTiming = "Expand /otherAvatar";
@ -430,8 +432,6 @@ namespace MenuOption {
const QString MetavoxelEditor = "Metavoxel Editor...";
const QString Metavoxels = "Metavoxels";
const QString Mirror = "Mirror";
const QString ModelOptions = "Model Options";
const QString Models = "Models";
const QString MoveWithLean = "Move with Lean";
const QString MuteAudio = "Mute Microphone";
const QString MuteEnvironment = "Mute Environment";

View file

@ -61,15 +61,18 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
float exponent = getExponent();
float cutoff = glm::radians(getCutoff());
if (_isSpotlight) {
Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation,
direction, exponent, cutoff);
} else {
Application::getInstance()->getDeferredLightingEffect()->addPointLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
}
bool disableLights = Menu::getInstance()->isOptionChecked(MenuOption::DisableLightEntities);
if (!disableLights) {
if (_isSpotlight) {
Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation,
direction, exponent, cutoff);
} else {
Application::getInstance()->getDeferredLightingEffect()->addPointLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
}
}
bool wantDebug = false;
if (wantDebug) {
glColor4f(diffuseR, diffuseG, diffuseB, 1.0f);

View file

@ -38,12 +38,9 @@ RenderableModelEntityItem::~RenderableModelEntityItem() {
bool RenderableModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) {
QString oldModelURL = getModelURL();
QString oldTextures = getTextures();
bool somethingChanged = ModelEntityItem::setProperties(properties, forceCopy);
if (somethingChanged) {
if ((oldModelURL != getModelURL()) || (oldTextures != getTextures())) {
_needsModelReload = true;
}
if (somethingChanged && oldModelURL != getModelURL()) {
_needsModelReload = true;
}
return somethingChanged;
}
@ -60,6 +57,47 @@ int RenderableModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned c
return bytesRead;
}
void RenderableModelEntityItem::remapTextures() {
if (!_model) {
return; // nothing to do if we don't have a model
}
if (_currentTextures == _textures) {
return; // nothing to do if our recently mapped textures match our desired textures
}
qDebug() << "void RenderableModelEntityItem::remapTextures()....";
// since we're changing here, we need to run through our current texture map
// and any textures in the recently mapped texture, that is not in our desired
// textures, we need to "unset"
QJsonDocument currentTexturesAsJson = QJsonDocument::fromJson(_currentTextures.toUtf8());
QJsonObject currentTexturesAsJsonObject = currentTexturesAsJson.object();
QVariantMap currentTextureMap = currentTexturesAsJsonObject.toVariantMap();
QJsonDocument texturesAsJson = QJsonDocument::fromJson(_textures.toUtf8());
QJsonObject texturesAsJsonObject = texturesAsJson.object();
QVariantMap textureMap = texturesAsJsonObject.toVariantMap();
foreach(const QString& key, currentTextureMap.keys()) {
// if the desired texture map (what we're setting the textures to) doesn't
// contain this texture, then remove it by setting the URL to null
if (!textureMap.contains(key)) {
QUrl noURL;
qDebug() << "Removing texture named" << key << "by replacing it with no URL";
_model->setTextureWithNameToURL(key, noURL);
}
}
// here's where we remap any textures if needed...
foreach(const QString& key, textureMap.keys()) {
QUrl newTextureURL = textureMap[key].toUrl();
qDebug() << "Updating texture named" << key << "to texture at URL" << newTextureURL;
_model->setTextureWithNameToURL(key, newTextureURL);
}
_currentTextures = _textures;
}
void RenderableModelEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RMEIrender");
@ -72,6 +110,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE;
if (drawAsModel) {
remapTextures();
glPushMatrix();
{
float alpha = getLocalRenderAlpha();
@ -159,6 +198,10 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
}
assert(_myRenderer == renderer); // you should only ever render on one renderer
if (QThread::currentThread() != _myRenderer->thread()) {
return _model;
}
_needsModelReload = false; // this is the reload
// if we have a URL, then we will want to end up returning a model...
@ -183,18 +226,6 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
}
}
// here's where we remap any textures if needed...
if (!_textures.isEmpty() && _model) {
QJsonDocument texturesAsJson = QJsonDocument::fromJson(_textures.toUtf8());
QJsonObject texturesAsJsonObject = texturesAsJson.object();
QVariantMap textureMap = texturesAsJsonObject.toVariantMap();
foreach(const QString& key, textureMap.keys()) {
QUrl newTextureURL = textureMap[key].toUrl();
qDebug() << "Updating texture named" << key << "to texture at URL" << newTextureURL;
_model->setTextureWithNameToURL(key, newTextureURL);
}
}
return result;
}

View file

@ -51,12 +51,14 @@ public:
virtual void render(RenderArgs* args);
Model* getModel(EntityTreeRenderer* renderer);
private:
void remapTextures();
bool needsSimulation() const;
Model* _model;
bool _needsInitialSimulation;
bool _needsModelReload;
EntityTreeRenderer* _myRenderer;
QString _currentTextures;
};
#endif // hifi_RenderableModelEntityItem_h

View file

@ -86,13 +86,13 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
switch(voxelPacketType) {
case PacketTypeEntityErase: {
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
app->_entities.processEraseMessage(mutablePacket, sendingNode);
}
} break;
case PacketTypeEntityData: {
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
app->_entities.processDatagram(mutablePacket, sendingNode);
}
} break;