diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 63370109e0..b49735a53f 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -21,6 +21,8 @@ #include <render/ShapePipeline.h> +#include <render/FilterTask.h> + #include "StencilMaskPass.h" #include "ZoneRenderer.h" #include "FadeEffect.h" @@ -53,8 +55,9 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; // const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; const auto& metas = items.get0()[RenderFetchCullSortTask::META]; - // const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - // const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; + const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; + const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; + //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; // const auto& spatialSelection = items[1]; @@ -75,6 +78,17 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // draw a stencil mask in hidden regions of the framebuffer. task.addJob<PrepareStencil>("PrepareStencil", framebuffer); + // Layered Overlays + const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT); + const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT); + const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0); + const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0); + + const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, nullptr).asVarying(); + const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, nullptr).asVarying(); + task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true); + task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false); + // Draw opaques forward const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying(); task.addJob<DrawForward>("DrawOpaques", opaqueInputs, shapePlumber); diff --git a/scripts/system/+android/displayNames.js b/scripts/system/+android/displayNames.js new file mode 100644 index 0000000000..509d85cd2b --- /dev/null +++ b/scripts/system/+android/displayNames.js @@ -0,0 +1,167 @@ +"use strict"; +// +// displayNames.js +// scripts/system/ +// +// Created by Cristian Duarte & Gabriel Calero on May 3, 2018 +// Copyright 2018 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() { // BEGIN LOCAL_SCOPE + +var MAX_DISTANCE_PX = 20; // Should we use dp instead? +var UNKNOWN_NAME = "Unknown"; +var METERS_ABOVE_HEAD = 0.4; + +var TEXT_LINE_HEIGHT = .1; +var TEXT_MARGIN = 0.025; + +var HIDE_MS = 10000; + +var currentTouchToAnalyze = null; + +var currentlyShownAvatar = { + avatarID: null, + avatar: null, + overlay: null +}; + +var logEnabled = false; + +var hideTimer = null; + +function printd(str) { + if (logEnabled) { + print("[displayNames.js] " + str); + } +} + +function clearOverlay() { + currentlyShownAvatar.avatar = null; + if (currentlyShownAvatar.overlay) { + Overlays.editOverlay(currentlyShownAvatar.overlay, {visible: false}); + } +} + +function touchedAvatar(avatarID, avatarData) { + printd("[AVATARNAME] touchEnd FOUND " + JSON.stringify(avatarData)); + + if (hideTimer) { + Script.clearTimeout(hideTimer); + } + + // Case: touching an already selected avatar + if (currentlyShownAvatar.avatar && currentlyShownAvatar.avatarID == avatarID) { + clearOverlay(); + return; + } + + // Save currently selected avatar + currentlyShownAvatar.avatarID = avatarID; + currentlyShownAvatar.avatar = avatarData; + + if (currentlyShownAvatar.overlay == null) { + var over = Overlays.addOverlay("text3d", { + lineHeight: TEXT_LINE_HEIGHT, + color: { red: 255, green: 255, blue: 255}, + backgroundColor: {red: 0, green: 0, blue: 0}, + leftMargin: TEXT_MARGIN, + topMargin: TEXT_MARGIN, + rightMargin: TEXT_MARGIN, + bottomMargin: TEXT_MARGIN, + alpha: 0.6, + solid: true, + isFacingAvatar: true, + visible: false + }); + currentlyShownAvatar.overlay = over; + } + + var nameToShow = avatarData.displayName ? avatarData.displayName : + (avatarData.sessionDisplayName ? avatarData.sessionDisplayName : UNKNOWN_NAME); + var textSize = Overlays.textSize(currentlyShownAvatar.overlay, nameToShow); + + Overlays.editOverlay(currentlyShownAvatar.overlay, { + dimensions: { + x: textSize.width + 2 * TEXT_MARGIN, + y: TEXT_LINE_HEIGHT + 2 * TEXT_MARGIN + }, + localPosition: { x: 0, y: METERS_ABOVE_HEAD, z: 0 }, + text: nameToShow, + parentID: avatarData.sessionUUID, + parentJointIndex: avatarData.getJointIndex("Head"), + visible: true + }); + + hideTimer = Script.setTimeout(function() { + clearOverlay(); + }, HIDE_MS); +} + +function touchBegin(event) { + currentTouchToAnalyze = event; +} + +function touchEnd(event) { + if (Vec3.distance({x: event.x, y: event.y }, {x: currentTouchToAnalyze.x, y: currentTouchToAnalyze.y}) > MAX_DISTANCE_PX) { + printd("[AVATARNAME] touchEnd moved too much"); + currentTouchToAnalyze = null; + return; + } + + var pickRay = Camera.computePickRay(event.x, event.y); + var avatarRay = AvatarManager.findRayIntersection(pickRay, [], [MyAvatar.sessionUUID]) + + if (avatarRay.intersects) { + touchedAvatar(avatarRay.avatarID, AvatarManager.getAvatar(avatarRay.avatarID)); + } else { + printd("[AVATARNAME] touchEnd released outside the avatar"); + } + + currentTouchToAnalyze = null; +} + +var runAtLeastOnce = false; + +function ending() { + if (!runAtLeastOnce) { + return; + } + + Controller.touchBeginEvent.disconnect(touchBegin); + Controller.touchEndEvent.disconnect(touchEnd); + Controller.mousePressEvent.disconnect(touchBegin); + Controller.mouseReleaseEvent.disconnect(touchEnd); + + if (currentlyShownAvatar.overlay) { + Overlays.deleteOverlay(currentlyShownAvatar.overlay); + currentlyShownAvatar.overlay = null; + } + if (currentlyShownAvatar.avatar) { + currentlyShownAvatar.avatar = null; + } +} + +function init() { + Controller.touchBeginEvent.connect(touchBegin); + Controller.touchEndEvent.connect(touchEnd); + Controller.mousePressEvent.connect(touchBegin); + Controller.mouseReleaseEvent.connect(touchEnd); + + Script.scriptEnding.connect(function () { + ending(); + }); + + runAtLeastOnce = true; +} + +module.exports = { + init: init, + ending: ending +} + +//init(); // Enable to use in desktop as a standalone + +}()); // END LOCAL_SCOPE \ No newline at end of file diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js index f5b3609c26..2c155ae386 100644 --- a/scripts/system/+android/modes.js +++ b/scripts/system/+android/modes.js @@ -28,6 +28,7 @@ modeLabel[MODE_MY_VIEW]="MY VIEW"; var logEnabled = false; var radar = Script.require('./radar.js'); var uniqueColor = Script.require('./uniqueColor.js'); +var displayNames = Script.require('./displayNames.js'); function printd(str) { if (logEnabled) { @@ -87,8 +88,10 @@ function switchToMode(newMode) { if (currentMode == MODE_RADAR) { radar.startRadarMode(); + displayNames.ending(); } else if (currentMode == MODE_MY_VIEW) { // nothing to do yet + displayNames.init(); } else { printd("Unknown view mode " + currentMode); }