mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-17 07:46:36 +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/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);
|
||||
}
|
||||
|
|
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
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
rotation *= getRotation();
|
||||
} else {
|
||||
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) {
|
||||
|
||||
// The application will keep track of creatorTokenID
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
Loading…
Reference in a new issue