Merge pull request #4435 from huffman/edit-lights-overlays

Add light icons when in edit mode
This commit is contained in:
Andrew Meadows 2015-03-13 15:56:05 -07:00
commit 748cd09936
7 changed files with 205 additions and 6 deletions

View file

@ -29,12 +29,15 @@ Script.include([
"libraries/entityCameraTool.js",
"libraries/gridTool.js",
"libraries/entityList.js",
"libraries/lightOverlayManager.js",
]);
var selectionDisplay = SelectionDisplay;
var selectionManager = SelectionManager;
var entityPropertyDialogBox = EntityPropertyDialogBox;
var lightOverlayManager = new LightOverlayManager();
var cameraManager = new CameraManager();
var grid = Grid();
@ -45,6 +48,7 @@ var entityListTool = EntityListTool();
selectionManager.addEventListener(function() {
selectionDisplay.updateHandles();
lightOverlayManager.updatePositions();
});
var windowDimensions = Controller.getViewportDimensions();
@ -70,13 +74,17 @@ var DEFAULT_DIMENSIONS = {
z: DEFAULT_DIMENSION
};
var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool";
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode";
var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled";
var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect";
var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode";
var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain."
@ -186,6 +194,8 @@ var toolBar = (function () {
alpha: 0.9,
visible: false
});
that.setActive(false);
}
that.setActive = function(active) {
@ -214,6 +224,7 @@ var toolBar = (function () {
}
}
toolBar.selectTool(activeButton, isActive);
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
};
// Sets visibility of tool buttons, excluding the power button
@ -354,8 +365,8 @@ var toolBar = (function () {
if (position.x > 0 && position.y > 0 && position.z > 0) {
placingEntityID = Entities.addEntity({
type: "Light",
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
dimensions: DEFAULT_DIMENSIONS,
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_LIGHT_DIMENSIONS), DEFAULT_LIGHT_DIMENSIONS),
dimensions: DEFAULT_LIGHT_DIMENSIONS,
isSpotlight: false,
diffuseColor: { red: 255, green: 255, blue: 255 },
ambientColor: { red: 255, green: 255, blue: 255 },
@ -469,12 +480,31 @@ function rayPlaneIntersection(pickRay, point, normal) {
function findClickedEntity(event) {
var pickRay = Camera.computePickRay(event.x, event.y);
var foundIntersection = Entities.findRayIntersection(pickRay, true); // want precision picking
var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking
var lightResult = lightOverlayManager.findRayIntersection(pickRay);
lightResult.accurate = true;
if (!foundIntersection.accurate) {
var result;
if (!entityResult.intersects && !lightResult.intersects) {
return null;
} else if (entityResult.intersects && !lightResult.intersects) {
result = entityResult;
} else if (!entityResult.intersects && lightResult.intersects) {
result = lightResult;
} else {
if (entityResult.distance < lightResult.distance) {
result = entityResult;
} else {
result = lightResult;
}
}
if (!result.accurate) {
return null;
}
var foundEntity = foundIntersection.entityID;
var foundEntity = result.entityID;
if (!foundEntity.isKnownID) {
var identify = Entities.identifyEntity(foundEntity);
@ -730,6 +760,8 @@ function setupModelMenus() {
isCheckable: true, isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true" });
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS,
isCheckable: true, isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true" });
Entities.setLightsArePickable(false);
}
@ -756,11 +788,13 @@ function cleanupModelMenus() {
Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED);
Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
}
Script.scriptEnding.connect(function() {
Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT));
Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
Settings.setValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
progressDialog.cleanup();
toolBar.cleanup();
@ -837,6 +871,8 @@ function handeMenuEvent(menuItem) {
}
} else if (menuItem == "Entity List...") {
entityListTool.toggleVisible();
} else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
}
tooltip.show(false);
}

View file

@ -0,0 +1,135 @@
var POINT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/point-light.svg";
var SPOT_LIGHT_URL = "http://s3.amazonaws.com/hifi-public/images/tools/spot-light.svg";
LightOverlayManager = function() {
var self = this;
var visible = false;
// List of all created overlays
var allOverlays = [];
// List of overlays not currently being used
var unusedOverlays = [];
// Map from EntityItemID.id to overlay id
var entityOverlays = {};
// Map from EntityItemID.id to EntityItemID object
var entityIDs = {};
this.updatePositions = function(ids) {
for (var id in entityIDs) {
var entityID = entityIDs[id];
var properties = Entities.getEntityProperties(entityID);
Overlays.editOverlay(entityOverlays[entityID.id], {
position: properties.position
});
}
};
this.findRayIntersection = function(pickRay) {
var result = Overlays.findRayIntersection(pickRay);
var found = false;
if (result.intersects) {
for (var id in entityOverlays) {
if (result.overlayID == entityOverlays[id]) {
result.entityID = entityIDs[id];
found = true;
break;
}
}
if (!found) {
result.intersects = false;
}
}
return result;
};
this.setVisible = function(isVisible) {
if (visible != isVisible) {
visible = isVisible;
for (var id in entityOverlays) {
Overlays.editOverlay(entityOverlays[id], { visible: visible });
}
}
};
// Allocate or get an unused overlay
function getOverlay() {
if (unusedOverlays.length == 0) {
var overlay = Overlays.addOverlay("billboard", {
});
allOverlays.push(overlay);
} else {
var overlay = unusedOverlays.pop();
};
return overlay;
}
function releaseOverlay(overlay) {
unusedOverlays.push(overlay);
Overlays.editOverlay(overlay, { visible: false });
}
function addEntity(entityID) {
var properties = Entities.getEntityProperties(entityID);
if (properties.type == "Light" && !(entityID.id in entityOverlays)) {
var overlay = getOverlay();
entityOverlays[entityID.id] = overlay;
entityIDs[entityID.id] = entityID;
Overlays.editOverlay(overlay, {
position: properties.position,
url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL,
rotation: Quat.fromPitchYawRollDegrees(0, 0, 270),
visible: visible,
alpha: 0.9,
scale: 0.5,
color: { red: 255, green: 255, blue: 255 }
});
}
}
function deleteEntity(entityID) {
if (entityID.id in entityOverlays) {
releaseOverlay(entityOverlays[entityID.id]);
delete entityOverlays[entityID.id];
}
}
function changeEntityID(oldEntityID, newEntityID) {
entityOverlays[newEntityID.id] = entityOverlays[oldEntityID.id];
entityIDs[newEntityID.id] = newEntityID;
delete entityOverlays[oldEntityID.id];
delete entityIDs[oldEntityID.id];
}
function clearEntities() {
for (var id in entityOverlays) {
releaseOverlay(entityOverlays[id]);
}
entityOverlays = {};
entityIDs = {};
}
Entities.addingEntity.connect(addEntity);
Entities.changingEntityID.connect(changeEntityID);
Entities.deletingEntity.connect(deleteEntity);
Entities.clearingEntities.connect(clearEntities);
// Add existing entities
var ids = Entities.findEntities(MyAvatar.position, 100);
for (var i = 0; i < ids.length; i++) {
addEntity(ids[i]);
}
Script.scriptEnding.connect(function() {
for (var i = 0; i < allOverlays.length; i++) {
Overlays.deleteOverlay(allOverlays[i]);
}
});
};

View file

@ -58,6 +58,7 @@ void BillboardOverlay::render(RenderArgs* args) {
// rotate about vertical to face the camera
rotation = Application::getInstance()->getCamera()->getRotation();
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
rotation *= getRotation();
} else {
rotation = getRotation();
}

View file

@ -35,6 +35,25 @@ bool EntityScriptingInterface::canAdjustLocks() {
}
void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) {
if (_entityTree) {
disconnect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
disconnect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity);
disconnect(_entityTree, &EntityTree::changingEntityID, this, &EntityScriptingInterface::changingEntityID);
disconnect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities);
}
_entityTree = modelTree;
if (_entityTree) {
connect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
connect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity);
connect(_entityTree, &EntityTree::changingEntityID, this, &EntityScriptingInterface::changingEntityID);
connect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities);
}
}
EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& properties) {
// The application will keep track of creatorTokenID

View file

@ -58,7 +58,7 @@ public:
virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; }
virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); }
void setEntityTree(EntityTree* modelTree) { _entityTree = modelTree; }
void setEntityTree(EntityTree* modelTree);
EntityTree* getEntityTree(EntityTree*) { return _entityTree; }
public slots:
@ -129,6 +129,11 @@ signals:
void enterEntity(const EntityItemID& entityItemID);
void leaveEntity(const EntityItemID& entityItemID);
void deletingEntity(const EntityItemID& entityID);
void addingEntity(const EntityItemID& entityID);
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
void clearingEntities();
private:
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);

View file

@ -37,6 +37,8 @@ EntityTreeElement* EntityTree::createNewElement(unsigned char * octalCode) {
}
void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
emit clearingEntities();
// this would be a good place to clean up our entities...
if (_simulation) {
_simulation->lock();

View file

@ -163,6 +163,7 @@ signals:
void addingEntity(const EntityItemID& entityID);
void entityScriptChanging(const EntityItemID& entityItemID);
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
void clearingEntities();
private: