mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 07:57:30 +02:00
Merge pull request #4435 from huffman/edit-lights-overlays
Add light icons when in edit mode
This commit is contained in:
commit
748cd09936
7 changed files with 205 additions and 6 deletions
|
@ -29,12 +29,15 @@ Script.include([
|
||||||
"libraries/entityCameraTool.js",
|
"libraries/entityCameraTool.js",
|
||||||
"libraries/gridTool.js",
|
"libraries/gridTool.js",
|
||||||
"libraries/entityList.js",
|
"libraries/entityList.js",
|
||||||
|
"libraries/lightOverlayManager.js",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var selectionDisplay = SelectionDisplay;
|
var selectionDisplay = SelectionDisplay;
|
||||||
var selectionManager = SelectionManager;
|
var selectionManager = SelectionManager;
|
||||||
var entityPropertyDialogBox = EntityPropertyDialogBox;
|
var entityPropertyDialogBox = EntityPropertyDialogBox;
|
||||||
|
|
||||||
|
var lightOverlayManager = new LightOverlayManager();
|
||||||
|
|
||||||
var cameraManager = new CameraManager();
|
var cameraManager = new CameraManager();
|
||||||
|
|
||||||
var grid = Grid();
|
var grid = Grid();
|
||||||
|
@ -45,6 +48,7 @@ var entityListTool = EntityListTool();
|
||||||
|
|
||||||
selectionManager.addEventListener(function() {
|
selectionManager.addEventListener(function() {
|
||||||
selectionDisplay.updateHandles();
|
selectionDisplay.updateHandles();
|
||||||
|
lightOverlayManager.updatePositions();
|
||||||
});
|
});
|
||||||
|
|
||||||
var windowDimensions = Controller.getViewportDimensions();
|
var windowDimensions = Controller.getViewportDimensions();
|
||||||
|
@ -70,13 +74,17 @@ var DEFAULT_DIMENSIONS = {
|
||||||
z: DEFAULT_DIMENSION
|
z: DEFAULT_DIMENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
|
||||||
|
|
||||||
var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool";
|
var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool";
|
||||||
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
|
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
|
||||||
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
|
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_INSPECT_TOOL_ENABLED = "inspectToolEnabled";
|
||||||
var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect";
|
var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect";
|
||||||
var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
|
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."
|
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,
|
alpha: 0.9,
|
||||||
visible: false
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
that.setActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
that.setActive = function(active) {
|
that.setActive = function(active) {
|
||||||
|
@ -214,6 +224,7 @@ var toolBar = (function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toolBar.selectTool(activeButton, isActive);
|
toolBar.selectTool(activeButton, isActive);
|
||||||
|
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets visibility of tool buttons, excluding the power button
|
// 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) {
|
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||||
placingEntityID = Entities.addEntity({
|
placingEntityID = Entities.addEntity({
|
||||||
type: "Light",
|
type: "Light",
|
||||||
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_DIMENSIONS), DEFAULT_DIMENSIONS),
|
position: grid.snapToSurface(grid.snapToGrid(position, false, DEFAULT_LIGHT_DIMENSIONS), DEFAULT_LIGHT_DIMENSIONS),
|
||||||
dimensions: DEFAULT_DIMENSIONS,
|
dimensions: DEFAULT_LIGHT_DIMENSIONS,
|
||||||
isSpotlight: false,
|
isSpotlight: false,
|
||||||
diffuseColor: { red: 255, green: 255, blue: 255 },
|
diffuseColor: { red: 255, green: 255, blue: 255 },
|
||||||
ambientColor: { 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) {
|
function findClickedEntity(event) {
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
var foundEntity = foundIntersection.entityID;
|
|
||||||
|
var foundEntity = result.entityID;
|
||||||
|
|
||||||
if (!foundEntity.isKnownID) {
|
if (!foundEntity.isKnownID) {
|
||||||
var identify = Entities.identifyEntity(foundEntity);
|
var identify = Entities.identifyEntity(foundEntity);
|
||||||
|
@ -730,6 +760,8 @@ function setupModelMenus() {
|
||||||
isCheckable: true, isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true" });
|
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,
|
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" });
|
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);
|
Entities.setLightsArePickable(false);
|
||||||
}
|
}
|
||||||
|
@ -756,11 +788,13 @@ function cleanupModelMenus() {
|
||||||
Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED);
|
Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED);
|
||||||
Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT);
|
Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT);
|
||||||
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
|
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
|
||||||
|
Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT));
|
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_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();
|
progressDialog.cleanup();
|
||||||
toolBar.cleanup();
|
toolBar.cleanup();
|
||||||
|
@ -837,6 +871,8 @@ function handeMenuEvent(menuItem) {
|
||||||
}
|
}
|
||||||
} else if (menuItem == "Entity List...") {
|
} else if (menuItem == "Entity List...") {
|
||||||
entityListTool.toggleVisible();
|
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);
|
tooltip.show(false);
|
||||||
}
|
}
|
||||||
|
|
135
examples/libraries/lightOverlayManager.js
Normal file
135
examples/libraries/lightOverlayManager.js
Normal 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]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
|
@ -58,6 +58,7 @@ void BillboardOverlay::render(RenderArgs* args) {
|
||||||
// rotate about vertical to face the camera
|
// rotate about vertical to face the camera
|
||||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||||
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
rotation *= getRotation();
|
||||||
} else {
|
} else {
|
||||||
rotation = getRotation();
|
rotation = getRotation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& properties) {
|
||||||
|
|
||||||
// The application will keep track of creatorTokenID
|
// The application will keep track of creatorTokenID
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; }
|
virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; }
|
||||||
virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); }
|
virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); }
|
||||||
|
|
||||||
void setEntityTree(EntityTree* modelTree) { _entityTree = modelTree; }
|
void setEntityTree(EntityTree* modelTree);
|
||||||
EntityTree* getEntityTree(EntityTree*) { return _entityTree; }
|
EntityTree* getEntityTree(EntityTree*) { return _entityTree; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -129,6 +129,11 @@ signals:
|
||||||
void enterEntity(const EntityItemID& entityItemID);
|
void enterEntity(const EntityItemID& entityItemID);
|
||||||
void leaveEntity(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:
|
private:
|
||||||
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ EntityTreeElement* EntityTree::createNewElement(unsigned char * octalCode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
|
void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
|
||||||
|
emit clearingEntities();
|
||||||
|
|
||||||
// this would be a good place to clean up our entities...
|
// this would be a good place to clean up our entities...
|
||||||
if (_simulation) {
|
if (_simulation) {
|
||||||
_simulation->lock();
|
_simulation->lock();
|
||||||
|
|
|
@ -163,6 +163,7 @@ signals:
|
||||||
void addingEntity(const EntityItemID& entityID);
|
void addingEntity(const EntityItemID& entityID);
|
||||||
void entityScriptChanging(const EntityItemID& entityItemID);
|
void entityScriptChanging(const EntityItemID& entityItemID);
|
||||||
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
|
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
|
||||||
|
void clearingEntities();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue