Merge branch 'master' into tony/hand-controller-move-improvements

This commit is contained in:
Anthony J. Thibault 2016-03-09 10:06:28 -08:00
commit 4691ca1716
32 changed files with 564 additions and 551 deletions

View file

@ -13,11 +13,11 @@
{ "from": "Hydra.RB", "to": "Standard.RB" },
{ "from": "Hydra.RS", "to": "Standard.RS" },
{ "from": [ "Hydra.L1", "Hydra.L2", "Hydra.L3", "Hydra.L4" ], "to": "Standard.LeftPrimaryThumb" },
{ "from": [ "Hydra.L0" ], "to": "Standard.LeftSecondaryThumb" },
{ "from": "Hydra.L0", "to": "Standard.Back" },
{ "from": "Hydra.R0", "to": "Standard.Start" },
{ "from": [ "Hydra.L1", "Hydra.L2", "Hydra.L3", "Hydra.L4" ], "to": "Standard.LeftPrimaryThumb" },
{ "from": [ "Hydra.R1", "Hydra.R2", "Hydra.R3", "Hydra.R4" ], "to": "Standard.RightPrimaryThumb" },
{ "from": [ "Hydra.R0" ], "to": "Standard.RightSecondaryThumb" },
{ "from": "Hydra.LeftHand", "to": "Standard.LeftHand" },
{ "from": "Hydra.RightHand", "to": "Standard.RightHand" }

View file

@ -27,14 +27,11 @@
{ "from": "Standard.RY", "to": "Actions.Up", "filters": "invert"},
{ "from": "Standard.Back", "to": "Actions.CycleCamera" },
{ "from": "Standard.Start", "to": "Actions.ContextMenu" },
{ "from": [ "Standard.DU", "Standard.DL", "Standard.DR", "Standard.DD" ], "to": "Standard.LeftPrimaryThumb" },
{ "from": "Standard.Back", "to": "Standard.LeftSecondaryThumb" },
{ "from": [ "Standard.A", "Standard.B", "Standard.X", "Standard.Y" ], "to": "Standard.RightPrimaryThumb" },
{ "from": "Standard.Start", "to": "Standard.RightSecondaryThumb" },
{ "from": "Standard.LeftSecondaryThumb", "to": "Actions.CycleCamera" },
{ "from": "Standard.RightSecondaryThumb", "to": "Actions.ContextMenu" },
{ "from": "Standard.LT", "to": "Actions.LeftHandClick" },
{ "from": "Standard.RT", "to": "Actions.RightHandClick" },

View file

@ -12,7 +12,7 @@
{ "from": "Standard.LB", "to": "Actions.UiNavGroup","filters": "invert" },
{ "from": "Standard.RB", "to": "Actions.UiNavGroup" },
{ "from": [ "Standard.A", "Standard.X" ], "to": "Actions.UiNavSelect" },
{ "from": [ "Standard.B", "Standard.Y", "Standard.RightPrimaryThumb", "Standard.LeftPrimaryThumb" ], "to": "Actions.UiNavBack" },
{ "from": [ "Standard.B", "Standard.Y" ], "to": "Actions.UiNavBack" },
{
"from": [ "Standard.RT", "Standard.LT" ],
"to": "Actions.UiNavSelect",

View file

@ -15,10 +15,8 @@
{ "from": "Vive.RB", "to": "Standard.RB" },
{ "from": "Vive.RS", "to": "Standard.RS" },
{ "from": "Vive.LeftPrimaryThumb", "to": "Standard.LeftPrimaryThumb" },
{ "from": "Vive.RightPrimaryThumb", "to": "Standard.RightPrimaryThumb" },
{ "from": "Vive.LeftSecondaryThumb", "to": "Standard.LeftSecondaryThumb" },
{ "from": "Vive.RightSecondaryThumb", "to": "Standard.RightSecondaryThumb" },
{ "from": "Vive.LeftApplicationMenu", "to": "Standard.Back" },
{ "from": "Vive.RightApplicationMenu", "to": "Standard.Start" },
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand" },
{ "from": "Vive.RightHand", "to": "Standard.RightHand" }

View file

@ -160,6 +160,7 @@ FocusScope {
ScrollView {
id: scrollView
height: 480
width: root.width + 4
ListView {
id: listView

View file

@ -12,7 +12,7 @@ import QtQuick 2.5
import "../styles-uit"
RalewaySemibold {
RalewaySemiBold {
property int colorScheme: hifi.colorSchemes.light
size: hifi.fontSizes.inputLabel

View file

@ -17,8 +17,8 @@ TextEdit {
property real size: 32
FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; }
font.family: ralewaySemibold.name
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
font.family: ralewaySemiBold.name
font.pointSize: size
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft

View file

@ -1,8 +1,8 @@
//
// Desktop.qml
// MessageDialog.qml
//
// Created by Bradley Austin Davis on 25 Apr 2015
// Copyright 2015 High Fidelity, Inc.
// Created by Bradley Austin Davis on 15 Jan 2016
// Copyright 2016 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
@ -42,10 +42,11 @@ ModalWindow {
property alias detailedText: detailedText.text
property alias text: mainTextContainer.text
property alias informativeText: informativeTextContainer.text
onIconChanged: updateIcon();
property int buttons: OriginalDialogs.StandardButton.Ok
property int icon: OriginalDialogs.StandardIcon.NoIcon
property string iconText: ""
property int iconSize: 50
onIconChanged: updateIcon();
property int defaultButton: OriginalDialogs.StandardButton.NoButton;
property int clickedButton: OriginalDialogs.StandardButton.NoButton;
focus: defaultButton === OriginalDialogs.StandardButton.NoButton
@ -54,22 +55,7 @@ ModalWindow {
if (!root) {
return;
}
switch (root.icon) {
case OriginalDialogs.StandardIcon.Information:
iconText = "\uF05A";
break;
case OriginalDialogs.StandardIcon.Question:
iconText = "\uF059"
break;
case OriginalDialogs.StandardIcon.Warning:
iconText = "\uF071"
break;
case OriginalDialogs.StandardIcon.Critical:
iconText = "\uF057"
break;
default:
iconText = ""
}
iconText = hifi.glyphForIcon(root.icon);
}
Item {
@ -80,8 +66,6 @@ ModalWindow {
QtObject {
id: d
readonly property real spacing: hifi.dimensions.contentSpacing.x
readonly property real outerSpacing: hifi.dimensions.contentSpacing.y
readonly property int minWidth: 480
readonly property int maxWdith: 1280
readonly property int minHeight: 120
@ -98,9 +82,9 @@ ModalWindow {
}
}
RalewaySemibold {
RalewaySemiBold {
id: mainTextContainer
onHeightChanged: d.resize(); onWidthChanged: d.resize();
onTextChanged: d.resize();
wrapMode: Text.WordWrap
size: hifi.fontSizes.menuItem
color: hifi.colors.baseGrayHighlight
@ -114,9 +98,9 @@ ModalWindow {
lineHeightMode: Text.ProportionalHeight
}
RalewaySemibold {
RalewaySemiBold {
id: informativeTextContainer
onHeightChanged: d.resize(); onWidthChanged: d.resize();
onTextChanged: d.resize();
wrapMode: Text.WordWrap
size: hifi.fontSizes.menuItem
color: hifi.colors.baseGrayHighlight
@ -132,7 +116,7 @@ ModalWindow {
Flow {
id: buttons
focus: true
spacing: d.spacing
spacing: hifi.dimensions.contentSpacing.x
onHeightChanged: d.resize(); onWidthChanged: d.resize();
layoutDirection: Qt.RightToLeft
anchors {
@ -186,8 +170,8 @@ ModalWindow {
id: flickable
contentHeight: detailedText.height
anchors.fill: parent
anchors.topMargin: root.spacing
anchors.bottomMargin: root.outerSpacing
anchors.topMargin: hifi.dimensions.contentSpacing.x
anchors.bottomMargin: hifi.dimensions.contentSpacing.y
TextEdit {
id: detailedText
size: hifi.fontSizes.menuItem
@ -210,7 +194,10 @@ ModalWindow {
}
]
Component.onCompleted: updateIcon();
Component.onCompleted: {
updateIcon();
d.resize();
}
onStateChanged: d.resize()
}

View file

@ -1,10 +1,20 @@
//
// QueryDialog.qml
//
// Created by Bradley Austin Davis on 22 Jan 2016
// Copyright 2015 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
//
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs
import "../controls" as VrControls
import "../styles"
import "../windows"
import "../controls-uit"
import "../styles-uit"
import "../windows-uit"
ModalWindow {
id: root
@ -16,8 +26,13 @@ ModalWindow {
signal selected(var result);
signal canceled();
property int icon: hifi.icons.none
property string iconText: ""
property int iconSize: 35
onIconChanged: updateIcon();
property var items;
property alias label: mainTextContainer.text
property string label
property var result;
// FIXME not current honored
property var current;
@ -28,66 +43,85 @@ ModalWindow {
// For combo boxes
property bool editable: true;
Rectangle {
function updateIcon() {
if (!root) {
return;
}
iconText = hifi.glyphForIcon(root.icon);
}
Item {
clip: true
anchors.fill: parent
radius: 4
color: "white"
width: pane.width
height: pane.height
anchors.margins: 0
QtObject {
id: d
readonly property real spacing: hifi.layout.spacing
readonly property real outerSpacing: hifi.layout.spacing * 2
readonly property int minWidth: 480
readonly property int maxWdith: 1280
readonly property int minHeight: 120
readonly property int maxHeight: 720
function resize() {
var targetWidth = mainTextContainer.width + d.spacing * 6
var targetHeight = mainTextContainer.implicitHeight + textResult.height + d.spacing + buttons.height
var targetWidth = pane.width
var targetHeight = (items ? comboBox.controlHeight : textResult.controlHeight) + 5 * hifi.dimensions.contentSpacing.y + buttons.height
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth)
root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)
}
}
Text {
id: mainTextContainer
onHeightChanged: d.resize(); onWidthChanged: d.resize();
wrapMode: Text.WordWrap
font { pointSize: 14; weight: Font.Bold }
anchors { left: parent.left; top: parent.top; margins: d.spacing }
}
Item {
anchors { top: mainTextContainer.bottom; bottom: buttons.top; left: parent.left; right: parent.right; margins: d.spacing }
anchors {
top: parent.top
bottom: buttons.top;
left: parent.left;
right: parent.right;
margins: 0
bottomMargin: 2 * hifi.dimensions.contentSpacing.y
}
// FIXME make a text field type that can be bound to a history for autocompletion
VrControls.TextField {
TextField {
id: textResult
label: root.label
focus: items ? false : true
visible: items ? false : true
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
anchors {
left: parent.left;
right: parent.right;
bottom: parent.bottom
}
}
VrControls.ComboBox {
ComboBox {
id: comboBox
label: root.label
focus: true
visible: items ? true : false
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
model: items ? items : []
}
}
Flow {
id: buttons
focus: true
spacing: d.spacing
spacing: hifi.dimensions.contentSpacing.x
onHeightChanged: d.resize(); onWidthChanged: d.resize();
layoutDirection: Qt.RightToLeft
anchors { bottom: parent.bottom; right: parent.right; margins: d.spacing; }
Button { action: acceptAction }
anchors {
bottom: parent.bottom
right: parent.right
margins: 0
bottomMargin: hifi.dimensions.contentSpacing.y
}
Button { action: cancelAction }
Button { action: acceptAction }
}
Action {
@ -130,4 +164,10 @@ ModalWindow {
break;
}
}
Component.onCompleted: {
updateIcon();
d.resize();
textResult.forceActiveFocus();
}
}

View file

@ -17,9 +17,35 @@ Item {
readonly property alias dimensions: dimensions
readonly property alias fontSizes: fontSizes
readonly property alias glyphs: glyphs
readonly property alias icons: icons
readonly property alias buttons: buttons
readonly property alias effects: effects
function glyphForIcon(icon) {
// Translates icon enum to glyph char.
var glyph;
switch (icon) {
case hifi.icons.information:
glyph = hifi.glyphs.info;
break;
case hifi.icons.question:
glyph = hifi.glyphs.question;
break;
case hifi.icons.warning:
glyph = hifi.glyphs.alert;
break;
case hifi.icons.critical:
glyph = hifi.glyphs.critical;
break;
case hifi.icons.placemark:
glyph = hifi.glyphs.placemark;
break;
default:
glyph = hifi.glyphs.noIcon;
}
return glyph;
}
Item {
id: colors
@ -134,6 +160,7 @@ Item {
Item {
id: glyphs
readonly property string alert: "+"
readonly property string backward: "E"
readonly property string caratDn: "5"
readonly property string caratR: "3"
@ -141,17 +168,33 @@ Item {
readonly property string close: "w"
readonly property string closeInverted: "x"
readonly property string closeSmall: "C"
readonly property string critical: "="
readonly property string disclosureButtonCollapse: "M"
readonly property string disclosureButtonExpand: "L"
readonly property string disclosureCollapse: "Z"
readonly property string disclosureExpand: "B"
readonly property string forward: "D"
readonly property string info: "["
readonly property string noIcon: ""
readonly property string pin: "y"
readonly property string pinInverted: "z"
readonly property string placemark: "U"
readonly property string question: "]"
readonly property string reloadSmall: "a"
readonly property string resizeHandle: "A"
}
Item {
id: icons
// Values per OffscreenUi::Icon
readonly property int none: 0
readonly property int question: 1
readonly property int information: 2
readonly property int warning: 3
readonly property int critical: 4
readonly property int placemark: 5
}
Item {
id: buttons
readonly property int white: 0

View file

@ -1,5 +1,5 @@
//
// RalewaySemibold.qml
// RalewaySemiBold.qml
//
// Created by David Rowe on 12 Feb 2016
// Copyright 2016 High Fidelity, Inc.
@ -14,10 +14,10 @@ import QtQuick.Controls.Styles 1.4
Text {
id: root
FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; }
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
property real size: 32
font.pixelSize: size
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
font.family: ralewaySemibold.name
font.family: ralewaySemiBold.name
}

View file

@ -47,16 +47,16 @@ Frame {
}
Item {
width: title.width + (window.iconText !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0)
width: title.width + (icon.text !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0)
x: (parent.width - width) / 2
FontAwesome {
HiFiGlyphs {
id: icon
text: window.iconText
size: 30
color: hifi.colors.lightGrayText
text: window.iconText ? window.iconText : ""
size: window.iconSize ? window.iconSize : 30
color: hifi.colors.lightGray
visible: text != ""
y: -hifi.dimensions.modalDialogTitleHeight - 5
anchors.verticalCenter: title.verticalCenter
anchors.left: parent.left
}
RalewayRegular {

View file

@ -107,7 +107,7 @@ void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
void Bookmarks::bookmarkLocation() {
bool ok = false;
auto bookmarkName = OffscreenUi::getText(nullptr, "Bookmark Location", "Name:", QLineEdit::Normal, QString(), &ok);
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok);
if (!ok) {
return;
}
@ -123,7 +123,7 @@ void Bookmarks::bookmarkLocation() {
Menu* menubar = Menu::getInstance();
if (contains(bookmarkName)) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(QMessageBox::Warning, "Duplicate Bookmark",
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark",
"The bookmark name you entered already exists in your list.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
@ -156,7 +156,7 @@ void Bookmarks::deleteBookmark() {
}
bool ok = false;
auto bookmarkName = OffscreenUi::getItem(nullptr, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
if (!ok) {
return;
}

View file

@ -231,23 +231,19 @@ bool Overlays::editOverlay(unsigned int id, const QVariant& properties) {
Overlay::Pointer thisOverlay = getOverlay(id);
if (thisOverlay) {
thisOverlay->setProperties(properties.toMap());
if (thisOverlay->is3D()) {
render::ItemKey oldItemKey = render::payloadGetKey(thisOverlay);
thisOverlay->setProperties(properties.toMap());
render::ItemKey itemKey = render::payloadGetKey(thisOverlay);
if (itemKey != oldItemKey) {
auto itemID = thisOverlay->getRenderItemID();
if (render::Item::isValidID(itemID)) {
render::ScenePointer scene = qApp->getMain3DScene();
auto itemID = thisOverlay->getRenderItemID();
if (render::Item::isValidID(itemID)) {
render::ScenePointer scene = qApp->getMain3DScene();
const render::Item& item = scene->getItem(itemID);
if (item.getKey() != render::payloadGetKey(thisOverlay)) {
render::PendingChanges pendingChanges;
pendingChanges.resortItem(itemID, oldItemKey, itemKey);
pendingChanges.updateItem(itemID);
scene->enqueuePendingChanges(pendingChanges);
}
}
} else {
thisOverlay->setProperties(properties.toMap());
}
return true;
@ -601,4 +597,4 @@ float Overlays::width() const {
float Overlays::height() const {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
return offscreenUi->getWindow()->size().height();
}
}

View file

@ -10,27 +10,30 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "RenderDeferredTask.h"
#include <PerfStat.h>
#include <PathUtils.h>
#include <RenderArgs.h>
#include <ViewFrustum.h>
#include <gpu/Context.h>
#include <render/CullTask.h>
#include <render/SortTask.h>
#include <render/DrawTask.h>
#include <render/DrawStatus.h>
#include <render/DrawSceneOctree.h>
#include "DebugDeferredBuffer.h"
#include "DeferredLightingEffect.h"
#include "FramebufferCache.h"
#include "HitEffect.h"
#include "TextureCache.h"
#include "render/DrawTask.h"
#include "render/DrawStatus.h"
#include "render/DrawSceneOctree.h"
#include "AmbientOcclusionEffect.h"
#include "AntialiasingEffect.h"
#include "ToneMappingEffect.h"
#include "RenderDeferredTask.h"
using namespace render;
extern void initStencilPipeline(gpu::PipelinePointer& pipeline);
@ -54,34 +57,42 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// CPU jobs:
// Fetch and cull the items from the scene
auto sceneFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered();
const auto sceneSelection = addJob<FetchSpatialTree>("FetchSceneSelection", sceneFilter);
const auto culledSceneSelection = addJob<CullSpatialSelection>("CullSceneSelection", sceneSelection, cullFunctor, RenderDetails::ITEM, sceneFilter);
auto spatialFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered();
const auto spatialSelection = addJob<FetchSpatialTree>("FetchSceneSelection", spatialFilter);
const auto culledSpatialSelection = addJob<CullSpatialSelection>("CullSceneSelection", spatialSelection, cullFunctor, RenderDetails::ITEM, spatialFilter);
// Overlays are not culled
const auto nonspatialSelection = addJob<FetchNonspatialItems>("FetchOverlaySelection");
// Multi filter visible items into different buckets
const int NUM_FILTERS = 3;
const int OPAQUE_SHAPE_BUCKET = 0;
const int TRANSPARENT_SHAPE_BUCKET = 1;
const int LIGHT_BUCKET = 2;
MultiFilterItem<NUM_FILTERS>::ItemFilterArray triageFilters = { {
const int BACKGROUND_BUCKET = 2;
MultiFilterItem<NUM_FILTERS>::ItemFilterArray spatialFilters = { {
ItemFilter::Builder::opaqueShape(),
ItemFilter::Builder::transparentShape(),
ItemFilter::Builder::light()
} };
const auto filteredItemsBuckets = addJob<MultiFilterItem<NUM_FILTERS>>("FilterSceneSelection", culledSceneSelection, triageFilters).get<MultiFilterItem<NUM_FILTERS>::ItemBoundsArray>();
MultiFilterItem<NUM_FILTERS>::ItemFilterArray nonspatialFilters = { {
ItemFilter::Builder::opaqueShape(),
ItemFilter::Builder::transparentShape(),
ItemFilter::Builder::background()
} };
const auto filteredSpatialBuckets = addJob<MultiFilterItem<NUM_FILTERS>>("FilterSceneSelection", culledSpatialSelection, spatialFilters).get<MultiFilterItem<NUM_FILTERS>::ItemBoundsArray>();
const auto filteredNonspatialBuckets = addJob<MultiFilterItem<NUM_FILTERS>>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters).get<MultiFilterItem<NUM_FILTERS>::ItemBoundsArray>();
// Extract / Sort opaques / Transparents / Lights / Overlays
const auto opaques = addJob<DepthSortItems>("DepthSortOpaque", filteredItemsBuckets[OPAQUE_SHAPE_BUCKET]);
const auto transparents = addJob<DepthSortItems>("DepthSortTransparent", filteredItemsBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false));
const auto lights = filteredItemsBuckets[LIGHT_BUCKET];
const auto opaques = addJob<DepthSortItems>("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]);
const auto transparents = addJob<DepthSortItems>("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false));
const auto lights = filteredSpatialBuckets[LIGHT_BUCKET];
// Overlays are not culled because we want to make sure they are seen
// Could be considered a bug in the current cullfunctor
const auto overlayOpaques = addJob<FetchItems>("FetchOverlayOpaque", ItemFilter::Builder::opaqueShapeLayered());
const auto fetchedOverlayOpaques = addJob<FetchItems>("FetchOverlayTransparents", ItemFilter::Builder::transparentShapeLayered());
const auto overlayTransparents = addJob<DepthSortItems>("DepthSortTransparentOverlay", fetchedOverlayOpaques, DepthSortItems(false));
const auto overlayOpaques = addJob<DepthSortItems>("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]);
const auto overlayTransparents = addJob<DepthSortItems>("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false));
const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET];
// GPU Jobs: Start preparing the deferred and lighting buffer
// GPU jobs: Start preparing the deferred and lighting buffer
addJob<PrepareDeferred>("PrepareDeferred");
// Render opaque objects in DeferredBuffer
@ -91,7 +102,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
addJob<DrawStencilDeferred>("DrawOpaqueStencil");
// Use Stencil and start drawing background in Lighting buffer
addJob<DrawBackgroundDeferred>("DrawBackgroundDeferred");
addJob<DrawBackgroundDeferred>("DrawBackgroundDeferred", background);
// AO job
addJob<AmbientOcclusionEffect>("AmbientOcclusion");
@ -123,8 +134,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// Scene Octree Debuging job
{
addJob<DrawSceneOctree>("DrawSceneOctree", sceneSelection);
addJob<DrawItemSelection>("DrawItemSelection", sceneSelection);
addJob<DrawSceneOctree>("DrawSceneOctree", spatialSelection);
addJob<DrawItemSelection>("DrawItemSelection", spatialSelection);
}
// Status icon rendering job
@ -170,9 +181,9 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
args->_batch = &batch;
config->setNumDrawn((int)inItems.size());
emit config->numDrawnChanged();
@ -222,7 +233,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
// Render the items
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
args->_whiteTexture = DependencyManager::get<TextureCache>()->getWhiteTexture();
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
glm::mat4 projMat;
Transform viewMat;
@ -231,14 +243,10 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
batch.setResourceTexture(0, args->_whiteTexture);
renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
args->_batch = nullptr;
});
args->_batch = nullptr;
args->_whiteTexture.reset();
}
}
@ -276,20 +284,10 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren
args->_batch = nullptr;
}
void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
// render backgrounds
auto& scene = sceneContext->_scene;
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background());
ItemBounds inItems;
inItems.reserve(items.size());
for (auto id : items) {
inItems.emplace_back(id);
}
RenderArgs* args = renderContext->args;
doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;

View file

@ -12,9 +12,8 @@
#ifndef hifi_RenderDeferredTask_h
#define hifi_RenderDeferredTask_h
#include "gpu/Pipeline.h"
#include "render/DrawTask.h"
#include <gpu/Pipeline.h>
#include <render/CullTask.h>
class SetupDeferred {
public:
@ -85,9 +84,9 @@ protected:
class DrawBackgroundDeferred {
public:
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemBounds& inItems);
using JobModel = render::Job::Model<DrawBackgroundDeferred>;
using JobModel = render::Job::ModelI<DrawBackgroundDeferred, render::ItemBounds>;
};
class DrawOverlay3DConfig : public render::Job::Config {

View file

@ -9,16 +9,20 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "RenderShadowTask.h"
#include <gpu/Context.h>
#include <ViewFrustum.h>
#include "render/Context.h"
#include <render/Context.h>
#include <render/CullTask.h>
#include <render/SortTask.h>
#include <render/DrawTask.h>
#include "DeferredLightingEffect.h"
#include "FramebufferCache.h"
#include "RenderShadowTask.h"
#include "model_shadow_vert.h"
#include "skin_model_shadow_vert.h"
@ -28,7 +32,7 @@
using namespace render;
void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
const render::ShapesIDsBounds& inShapes) {
const render::ShapeBounds& inShapes) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
@ -104,20 +108,18 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha
skinProgram, state);
}
// CPU: Fetch shadow-casting opaques
const auto fetchedItems = addJob<FetchItems>("FetchShadowMap");
// CPU jobs:
// Fetch and cull the items from the scene
auto shadowFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
const auto shadowSelection = addJob<FetchSpatialTree>("FetchShadowSelection", shadowFilter);
const auto culledShadowSelection = addJob<CullSpatialSelection>("CullShadowSelection", shadowSelection, cullFunctor, RenderDetails::SHADOW, shadowFilter);
// CPU: Cull against KeyLight frustum (nearby viewing camera)
const auto culledItems = addJob<CullItems<RenderDetails::SHADOW>>("CullShadowMap", fetchedItems, cullFunctor);
// Sort
const auto sortedPipelines = addJob<PipelineSortShapes>("PipelineSortShadowSort", culledShadowSelection);
const auto sortedShapes = addJob<DepthSortShapes>("DepthSortShadowMap", sortedPipelines);
// CPU: Sort by pipeline
const auto sortedShapes = addJob<PipelineSortShapes>("PipelineSortShadowSort", culledItems);
// CPU: Sort front to back
const auto shadowShapes = addJob<DepthSortShapes>("DepthSortShadowMap", sortedShapes);
// GPU: Render to shadow map
addJob<RenderShadowMap>("RenderShadowMap", shadowShapes, shapePlumber);
// GPU jobs: Render to shadow map
addJob<RenderShadowMap>("RenderShadowMap", sortedShapes, shapePlumber);
}
void RenderShadowTask::configure(const Config& configuration) {

View file

@ -15,17 +15,17 @@
#include <gpu/Framebuffer.h>
#include <gpu/Pipeline.h>
#include <render/DrawTask.h>
#include <render/CullTask.h>
class ViewFrustum;
class RenderShadowMap {
public:
using JobModel = render::Job::ModelI<RenderShadowMap, render::ShapesIDsBounds>;
using JobModel = render::Job::ModelI<RenderShadowMap, render::ShapeBounds>;
RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
const render::ShapesIDsBounds& inShapes);
const render::ShapeBounds& inShapes);
protected:
render::ShapePlumberPointer _shapePlumber;

View file

@ -62,99 +62,21 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
details._rendered += (int)outItems.size();
}
struct ItemBoundSort {
float _centerDepth = 0.0f;
float _nearDepth = 0.0f;
float _farDepth = 0.0f;
ItemID _id = 0;
AABox _bounds;
ItemBoundSort() {}
ItemBoundSort(float centerDepth, float nearDepth, float farDepth, ItemID id, const AABox& bounds) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id), _bounds(bounds) {}
};
struct FrontToBackSort {
bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) {
return (left._centerDepth < right._centerDepth);
}
};
struct BackToFrontSort {
bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) {
return (left._centerDepth > right._centerDepth);
}
};
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
// Allocate and simply copy
outItems.clear();
outItems.reserve(inItems.size());
// Make a local dataset of the center distance and closest point distance
std::vector<ItemBoundSort> itemBoundSorts;
itemBoundSorts.reserve(outItems.size());
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
auto bound = itemDetails.bound; // item.getBound();
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound));
}
// sort against Z
if (frontToBack) {
FrontToBackSort frontToBackSort;
std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), frontToBackSort);
} else {
BackToFrontSort backToFrontSort;
std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), backToFrontSort);
}
// FInally once sorted result to a list of itemID
for (auto& item : itemBoundSorts) {
outItems.emplace_back(ItemBound(item._id, item._bounds));
}
}
void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {
depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems);
}
void FetchItems::configure(const Config& config) {
}
void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) {
void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
auto& scene = sceneContext->_scene;
outItems.clear();
const auto& bucket = scene->getMasterBucket();
const auto& items = bucket.find(_filter);
if (items != bucket.end()) {
outItems.reserve(items->second.size());
for (auto& id : items->second) {
auto& item = scene->getItem(id);
outItems.emplace_back(ItemBound(id, item.getBound()));
}
const auto& items = scene->getNonspatialSet();
outItems.reserve(items.size());
for (auto& id : items) {
auto& item = scene->getItem(id);
outItems.emplace_back(ItemBound(id, item.getBound()));
}
std::static_pointer_cast<Config>(renderContext->jobConfig)->numItems = (int)outItems.size();
}
void FetchSpatialTree::configure(const Config& config) {
_justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum);
_freezeFrustum = config.freezeFrustum;

View file

@ -21,52 +21,13 @@ namespace render {
void cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details,
const ItemBounds& inItems, ItemBounds& outItems);
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems);
class FetchItemsConfig : public Job::Config {
Q_OBJECT
Q_PROPERTY(int numItems READ getNumItems)
class FetchNonspatialItems {
public:
int getNumItems() { return numItems; }
int numItems{ 0 };
};
class FetchItems {
public:
using Config = FetchItemsConfig;
using JobModel = Job::ModelO<FetchItems, ItemBounds, Config>;
FetchItems() {}
FetchItems(const ItemFilter& filter) : _filter(filter) {}
ItemFilter _filter{ ItemFilter::Builder::opaqueShape().withoutLayered() };
void configure(const Config& config);
using JobModel = Job::ModelO<FetchNonspatialItems, ItemBounds>;
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems);
};
template<RenderDetails::Type T>
class CullItems {
public:
using JobModel = Job::ModelIO<CullItems<T>, ItemBounds, ItemBounds>;
CullItems(CullFunctor cullFunctor) : _cullFunctor{ cullFunctor } {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {
const auto& args = renderContext->args;
auto& details = args->_details.edit(T);
outItems.clear();
outItems.reserve(inItems.size());
render::cullItems(renderContext, _cullFunctor, details, inItems, outItems);
}
protected:
CullFunctor _cullFunctor;
};
class FetchSpatialTreeConfig : public Job::Config {
Q_OBJECT
Q_PROPERTY(int numItems READ getNumItems)
@ -209,28 +170,19 @@ namespace render {
outItems[i].template edit<ItemBounds>().clear();
}
// For each item, filter it into the buckets
// For each item, filter it into one bucket
for (auto itemBound : inItems) {
auto& item = scene->getItem(itemBound.id);
auto itemKey = item.getKey();
for (size_t i = 0; i < NUM_FILTERS; i++) {
if (_filters[i].test(itemKey)) {
outItems[i].template edit<ItemBounds>().emplace_back(itemBound);
break;
}
}
}
}
};
class DepthSortItems {
public:
using JobModel = Job::ModelIO<DepthSortItems, ItemBounds, ItemBounds>;
bool _frontToBack;
DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems);
};
}
#endif // hifi_render_CullTask_h;

View file

@ -73,38 +73,3 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext
args->_batch = nullptr;
});
}
void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapesIDsBounds& outShapes) {
auto& scene = sceneContext->_scene;
outShapes.clear();
for (const auto& item : inItems) {
auto key = scene->getItem(item.id).getShapeKey();
auto outItems = outShapes.find(key);
if (outItems == outShapes.end()) {
outItems = outShapes.insert(std::make_pair(key, ItemBounds{})).first;
outItems->second.reserve(inItems.size());
}
outItems->second.push_back(item);
}
for (auto& items : outShapes) {
items.second.shrink_to_fit();
}
}
void DepthSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes) {
outShapes.clear();
outShapes.reserve(inShapes.size());
for (auto& pipeline : inShapes) {
auto& inItems = pipeline.second;
auto outItems = outShapes.find(pipeline.first);
if (outItems == outShapes.end()) {
outItems = outShapes.insert(std::make_pair(pipeline.first, ItemBounds{})).first;
}
depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems->second);
}
}

View file

@ -13,10 +13,6 @@
#define hifi_render_DrawTask_h
#include "Engine.h"
#include "CullTask.h"
#include "ShapePipeline.h"
#include "gpu/Batch.h"
namespace render {
@ -31,22 +27,6 @@ public:
protected:
};
class PipelineSortShapes {
public:
using JobModel = Job::ModelIO<PipelineSortShapes, ItemBounds, ShapesIDsBounds>;
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapesIDsBounds& outShapes);
};
class DepthSortShapes {
public:
using JobModel = Job::ModelIO<DepthSortShapes, ShapesIDsBounds, ShapesIDsBounds>;
bool _frontToBack;
DepthSortShapes(bool frontToBack = true) : _frontToBack(frontToBack) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes);
};
}
#endif // hifi_render_DrawTask_h

View file

@ -63,6 +63,13 @@ void Item::PayloadInterface::addStatusGetters(const Status::Getters& getters) {
}
}
void Item::update(const UpdateFunctorPointer& updateFunctor) {
if (updateFunctor) {
_payload->update(updateFunctor);
}
_key = _payload->getKey();
}
void Item::resetPayload(const PayloadPointer& payload) {
if (!payload) {
kill();

View file

@ -112,6 +112,7 @@ public:
bool isPickable() const { return _flags[PICKABLE]; }
bool isLayered() const { return _flags[LAYERED]; }
bool isSpatial() const { return !isLayered(); }
// Probably not public, flags used by the scene
bool isSmall() const { return _flags[SMALLER]; }
@ -312,11 +313,11 @@ public:
Item() {}
~Item() {}
// Main scene / item managment interface Reset/Update/Kill
// Main scene / item managment interface reset/update/kill
void resetPayload(const PayloadPointer& payload);
void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); }
void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } // Communicate update to the payload
void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Kill means forget the payload and key and cell
void resetCell(ItemCell cell = INVALID_CELL, bool _small = false) { _cell = cell; _key.setSmaller(_small); }
void update(const UpdateFunctorPointer& updateFunctor); // communicate update to payload
void kill() { _payload.reset(); resetCell(); _key._flags.reset(); } // forget the payload, key, cell
// Check heuristic key
const ItemKey& getKey() const { return _key; }
@ -464,7 +465,7 @@ public:
using ItemBounds = std::vector<ItemBound>;
// A map of items by ShapeKey to optimize rendering pipeline assignments
using ShapesIDsBounds = std::unordered_map<ShapeKey, ItemBounds, ShapeKey::Hash, ShapeKey::KeyEqual>;
using ShapeBounds = std::unordered_map<ShapeKey, ItemBounds, ShapeKey::Hash, ShapeKey::KeyEqual>;
}

View file

@ -15,59 +15,11 @@
using namespace render;
void ItemBucketMap::insert(const ItemID& id, const ItemKey& key) {
// Insert the itemID in every bucket where it filters true
for (auto& bucket : (*this)) {
if (bucket.first.test(key)) {
bucket.second.insert(id);
}
}
}
void ItemBucketMap::erase(const ItemID& id, const ItemKey& key) {
// Remove the itemID in every bucket where it filters true
for (auto& bucket : (*this)) {
if (bucket.first.test(key)) {
bucket.second.erase(id);
}
}
}
void ItemBucketMap::reset(const ItemID& id, const ItemKey& oldKey, const ItemKey& newKey) {
// Reset the itemID in every bucket,
// Remove from the buckets where oldKey filters true AND newKey filters false
// Insert into the buckets where newKey filters true
for (auto& bucket : (*this)) {
if (bucket.first.test(oldKey)) {
if (!bucket.first.test(newKey)) {
bucket.second.erase(id);
}
} else if (bucket.first.test(newKey)) {
bucket.second.insert(id);
}
}
}
void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() {
(*this)[ItemFilter::Builder::opaqueShape().withoutLayered()];
(*this)[ItemFilter::Builder::transparentShape().withoutLayered()];
(*this)[ItemFilter::Builder::light()];
(*this)[ItemFilter::Builder::background()];
(*this)[ItemFilter::Builder::opaqueShape().withLayered()];
(*this)[ItemFilter::Builder::transparentShape().withLayered()];
}
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
_resetItems.push_back(id);
_resetPayloads.push_back(payload);
}
void PendingChanges::resortItem(ItemID id, ItemKey oldKey, ItemKey newKey) {
_resortItems.push_back(id);
_resortOldKeys.push_back(oldKey);
_resortNewKeys.push_back(newKey);
}
void PendingChanges::removeItem(ItemID id) {
_removedItems.push_back(id);
}
@ -80,9 +32,6 @@ void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor)
void PendingChanges::merge(PendingChanges& changes) {
_resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end());
_resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.end());
_resortItems.insert(_resortItems.end(), changes._resortItems.begin(), changes._resortItems.end());
_resortOldKeys.insert(_resortOldKeys.end(), changes._resortOldKeys.begin(), changes._resortOldKeys.end());
_resortNewKeys.insert(_resortNewKeys.end(), changes._resortNewKeys.begin(), changes._resortNewKeys.end());
_removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end());
_updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end());
_updateFunctors.insert(_updateFunctors.end(), changes._updateFunctors.begin(), changes._updateFunctors.end());
@ -92,7 +41,6 @@ Scene::Scene(glm::vec3 origin, float size) :
_masterSpatialTree(origin, size)
{
_items.push_back(Item()); // add the itemID #0 to nothing
_masterBucketMap.allocateStandardOpaqueTranparentBuckets();
}
ItemID Scene::allocateID() {
@ -133,7 +81,6 @@ void Scene::processPendingChangesQueue() {
// capture anything coming from the pendingChanges
resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads);
updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors);
resortItems(consolidatedPendingChanges._resortItems, consolidatedPendingChanges._resortOldKeys, consolidatedPendingChanges._resortNewKeys);
removeItems(consolidatedPendingChanges._removedItems);
// ready to go back to rendering activities
@ -141,7 +88,6 @@ void Scene::processPendingChangesQueue() {
}
void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
auto resetPayload = payloads.begin();
for (auto resetID : ids) {
// Access the true item
@ -153,28 +99,20 @@ void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
item.resetPayload(*resetPayload);
auto newKey = item.getKey();
// Reset the item in the Bucket map
_masterBucketMap.reset(resetID, oldKey, newKey);
// Reset the item in the spatial tree
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey);
item.resetCell(newCell, newKey.isSmall());
// Update the item's container
assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none());
if (newKey.isSpatial()) {
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey);
item.resetCell(newCell, newKey.isSmall());
} else {
_masterNonspatialSet.insert(resetID);
}
// next loop
resetPayload++;
}
}
void Scene::resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys) {
auto resortID = ids.begin();
auto oldKey = oldKeys.begin();
auto newKey = newKeys.begin();
for (; resortID != ids.end(); resortID++, oldKey++, newKey++) {
_masterBucketMap.reset(*resortID, *oldKey, *newKey);
}
}
void Scene::removeItems(const ItemIDs& ids) {
for (auto removedID :ids) {
// Access the true item
@ -182,11 +120,12 @@ void Scene::removeItems(const ItemIDs& ids) {
auto oldCell = item.getCell();
auto oldKey = item.getKey();
// Remove from Bucket map
_masterBucketMap.erase(removedID, item.getKey());
// Remove from spatial tree
_masterSpatialTree.removeItem(oldCell, oldKey, removedID);
// Remove the item
if (oldKey.isSpatial()) {
_masterSpatialTree.removeItem(oldCell, oldKey, removedID);
} else {
_masterNonspatialSet.erase(removedID);
}
// Kill it
item.kill();
@ -202,14 +141,30 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) {
auto oldCell = item.getCell();
auto oldKey = item.getKey();
// Update it
_items[updateID].update((*updateFunctor));
// Update the item
item.update((*updateFunctor));
auto newKey = item.getKey();
// Update the citem in the spatial tree if needed
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey);
item.resetCell(newCell, newKey.isSmall());
// Update the item's container
if (oldKey.isSpatial() == newKey.isSpatial()) {
if (newKey.isSpatial()) {
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey);
item.resetCell(newCell, newKey.isSmall());
}
} else {
if (newKey.isSpatial()) {
_masterNonspatialSet.erase(updateID);
auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey);
item.resetCell(newCell, newKey.isSmall());
} else {
_masterSpatialTree.removeItem(oldCell, oldKey, updateID);
item.resetCell();
_masterNonspatialSet.insert(updateID);
}
}
// next loop
updateFunctor++;

View file

@ -17,21 +17,6 @@
namespace render {
// A map of ItemIDSets allowing to create bucket lists of items which are filtered according to their key
class ItemBucketMap : public std::map<ItemFilter, ItemIDSet, ItemFilter::Less> {
public:
ItemBucketMap() {}
void insert(const ItemID& id, const ItemKey& key);
void erase(const ItemID& id, const ItemKey& key);
void reset(const ItemID& id, const ItemKey& oldKey, const ItemKey& newKey);
// standard builders allocating the main buckets
void allocateStandardOpaqueTranparentBuckets();
};
class Engine;
class PendingChanges {
@ -40,7 +25,6 @@ public:
~PendingChanges() {}
void resetItem(ItemID id, const PayloadPointer& payload);
void resortItem(ItemID id, ItemKey oldKey, ItemKey newKey);
void removeItem(ItemID id);
template <class T> void updateItem(ItemID id, std::function<void(T&)> func) {
@ -48,14 +32,12 @@ public:
}
void updateItem(ItemID id, const UpdateFunctorPointer& functor);
void updateItem(ItemID id) { updateItem(id, nullptr); }
void merge(PendingChanges& changes);
ItemIDs _resetItems;
Payloads _resetPayloads;
ItemIDs _resortItems;
ItemKeys _resortOldKeys;
ItemKeys _resortNewKeys;
ItemIDs _removedItems;
ItemIDs _updatedItems;
UpdateFunctors _updateFunctors;
@ -75,27 +57,27 @@ public:
Scene(glm::vec3 origin, float size);
~Scene() {}
/// This call is thread safe, can be called from anywhere to allocate a new ID
// This call is thread safe, can be called from anywhere to allocate a new ID
ItemID allocateID();
/// Enqueue change batch to the scene
// Enqueue change batch to the scene
void enqueuePendingChanges(const PendingChanges& pendingChanges);
// Process the penging changes equeued
void processPendingChangesQueue();
/// Access a particular item form its ID
/// WARNING, There is No check on the validity of the ID, so this could return a bad Item
// Access a particular item form its ID
// WARNING, There is No check on the validity of the ID, so this could return a bad Item
const Item& getItem(const ItemID& id) const { return _items[id]; }
size_t getNumItems() const { return _items.size(); }
/// Access the main bucketmap of items
const ItemBucketMap& getMasterBucket() const { return _masterBucketMap; }
/// Access the item spatial tree
// Access the spatialized items
const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
// Access non-spatialized items (overlays, backgrounds)
const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; }
protected:
// Thread safe elements that can be accessed from anywhere
std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One
@ -106,12 +88,10 @@ protected:
// database of items is protected for editing by a mutex
std::mutex _itemsMutex;
Item::Vector _items;
ItemBucketMap _masterBucketMap;
ItemSpatialTree _masterSpatialTree;
ItemIDSet _masterNonspatialSet;
void resetItems(const ItemIDs& ids, Payloads& payloads);
void resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys);
void removeItems(const ItemIDs& ids);
void updateItems(const ItemIDs& ids, UpdateFunctors& functors);

View file

@ -0,0 +1,120 @@
//
// CullTask.cpp
// render/src/render
//
// Created by Sam Gateau on 2/2/16.
// Copyright 2016 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
//
#include "SortTask.h"
#include "ShapePipeline.h"
#include <assert.h>
#include <ViewFrustum.h>
using namespace render;
struct ItemBoundSort {
float _centerDepth = 0.0f;
float _nearDepth = 0.0f;
float _farDepth = 0.0f;
ItemID _id = 0;
AABox _bounds;
ItemBoundSort() {}
ItemBoundSort(float centerDepth, float nearDepth, float farDepth, ItemID id, const AABox& bounds) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id), _bounds(bounds) {}
};
struct FrontToBackSort {
bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) {
return (left._centerDepth < right._centerDepth);
}
};
struct BackToFrontSort {
bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) {
return (left._centerDepth > right._centerDepth);
}
};
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
// Allocate and simply copy
outItems.clear();
outItems.reserve(inItems.size());
// Make a local dataset of the center distance and closest point distance
std::vector<ItemBoundSort> itemBoundSorts;
itemBoundSorts.reserve(outItems.size());
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
auto bound = itemDetails.bound; // item.getBound();
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound));
}
// sort against Z
if (frontToBack) {
FrontToBackSort frontToBackSort;
std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), frontToBackSort);
} else {
BackToFrontSort backToFrontSort;
std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), backToFrontSort);
}
// Finally once sorted result to a list of itemID
for (auto& item : itemBoundSorts) {
outItems.emplace_back(ItemBound(item._id, item._bounds));
}
}
void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapeBounds& outShapes) {
auto& scene = sceneContext->_scene;
outShapes.clear();
for (const auto& item : inItems) {
auto key = scene->getItem(item.id).getShapeKey();
auto outItems = outShapes.find(key);
if (outItems == outShapes.end()) {
outItems = outShapes.insert(std::make_pair(key, ItemBounds{})).first;
outItems->second.reserve(inItems.size());
}
outItems->second.push_back(item);
}
for (auto& items : outShapes) {
items.second.shrink_to_fit();
}
}
void DepthSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapeBounds& inShapes, ShapeBounds& outShapes) {
outShapes.clear();
outShapes.reserve(inShapes.size());
for (auto& pipeline : inShapes) {
auto& inItems = pipeline.second;
auto outItems = outShapes.find(pipeline.first);
if (outItems == outShapes.end()) {
outItems = outShapes.insert(std::make_pair(pipeline.first, ItemBounds{})).first;
}
depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems->second);
}
}
void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {
depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems);
}

View file

@ -0,0 +1,47 @@
//
// SortTask.h
// render/src/render
//
// Created by Zach Pomerantz on 2/26/2016.
// Copyright 2016 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
//
#ifndef hifi_render_SortTask_h
#define hifi_render_SortTask_h
#include "Engine.h"
namespace render {
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems);
class PipelineSortShapes {
public:
using JobModel = Job::ModelIO<PipelineSortShapes, ItemBounds, ShapeBounds>;
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapeBounds& outShapes);
};
class DepthSortShapes {
public:
using JobModel = Job::ModelIO<DepthSortShapes, ShapeBounds, ShapeBounds>;
bool _frontToBack;
DepthSortShapes(bool frontToBack = true) : _frontToBack(frontToBack) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapeBounds& inShapes, ShapeBounds& outShapes);
};
class DepthSortItems {
public:
using JobModel = Job::ModelIO<DepthSortItems, ItemBounds, ItemBounds>;
bool _frontToBack;
DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {}
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems);
};
}
#endif // hifi_render_SortTask_h;

View file

@ -204,7 +204,7 @@ private slots:
}
};
QQuickItem* OffscreenUi::createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
QQuickItem* OffscreenUi::createMessageBox(Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
QVariantMap map;
map.insert("title", title);
map.insert("text", text);
@ -232,12 +232,12 @@ int OffscreenUi::waitForMessageBoxResult(QQuickItem* messageBox) {
}
QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
QMessageBox::StandardButton OffscreenUi::messageBox(Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
if (QThread::currentThread() != thread()) {
QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton;
QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QMessageBox::StandardButton, result),
Q_ARG(QMessageBox::Icon, icon),
Q_ARG(Icon, icon),
Q_ARG(QString, title),
Q_ARG(QString, text),
Q_ARG(QMessageBox::StandardButtons, buttons),
@ -250,19 +250,19 @@ QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, cons
QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QString& text,
QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
return DependencyManager::get<OffscreenUi>()->messageBox(QMessageBox::Icon::Critical, title, text, buttons, defaultButton);
return DependencyManager::get<OffscreenUi>()->messageBox(OffscreenUi::Icon::ICON_CRITICAL, title, text, buttons, defaultButton);
}
QMessageBox::StandardButton OffscreenUi::information(const QString& title, const QString& text,
QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
return DependencyManager::get<OffscreenUi>()->messageBox(QMessageBox::Icon::Information, title, text, buttons, defaultButton);
return DependencyManager::get<OffscreenUi>()->messageBox(OffscreenUi::Icon::ICON_INFORMATION, title, text, buttons, defaultButton);
}
QMessageBox::StandardButton OffscreenUi::question(const QString& title, const QString& text,
QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
return DependencyManager::get<OffscreenUi>()->messageBox(QMessageBox::Icon::Question, title, text, buttons, defaultButton);
return DependencyManager::get<OffscreenUi>()->messageBox(OffscreenUi::Icon::ICON_QUESTION, title, text, buttons, defaultButton);
}
QMessageBox::StandardButton OffscreenUi::warning(const QString& title, const QString& text,
QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
return DependencyManager::get<OffscreenUi>()->messageBox(QMessageBox::Icon::Warning, title, text, buttons, defaultButton);
return DependencyManager::get<OffscreenUi>()->messageBox(OffscreenUi::Icon::ICON_WARNING, title, text, buttons, defaultButton);
}
@ -286,24 +286,24 @@ private slots:
}
};
// FIXME many input parameters currently ignored
QString OffscreenUi::getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode, const QString & text, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
QString OffscreenUi::getText(const Icon icon, const QString& title, const QString& label, const QString& text, bool* ok) {
if (ok) { *ok = false; }
QVariant result = DependencyManager::get<OffscreenUi>()->inputDialog(title, label, text).toString();
QVariant result = DependencyManager::get<OffscreenUi>()->inputDialog(icon, title, label, text).toString();
if (ok && result.isValid()) {
*ok = true;
}
return result.toString();
}
// FIXME many input parameters currently ignored
QString OffscreenUi::getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current, bool editable, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
QString OffscreenUi::getItem(const Icon icon, const QString& title, const QString& label, const QStringList& items,
int current, bool editable, bool* ok) {
if (ok) {
*ok = false;
}
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto inputDialog = offscreenUi->createInputDialog(title, label, current);
auto inputDialog = offscreenUi->createInputDialog(icon, title, label, current);
if (!inputDialog) {
return QString();
}
@ -321,24 +321,28 @@ QString OffscreenUi::getItem(void *ignored, const QString & title, const QString
return result.toString();
}
QVariant OffscreenUi::inputDialog(const QString& title, const QString& label, const QVariant& current) {
QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) {
if (QThread::currentThread() != thread()) {
QVariant result;
QMetaObject::invokeMethod(this, "inputDialog", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QVariant, result),
Q_ARG(QString, title),
Q_ARG(Icon, icon),
Q_ARG(QString, label),
Q_ARG(QVariant, current));
return result;
}
return waitForInputDialogResult(createInputDialog(title, label, current));
return waitForInputDialogResult(createInputDialog(icon, title, label, current));
}
QQuickItem* OffscreenUi::createInputDialog(const QString& title, const QString& label, const QVariant& current) {
QQuickItem* OffscreenUi::createInputDialog(const Icon icon, const QString& title, const QString& label,
const QVariant& current) {
QVariantMap map;
map.insert("title", title);
map.insert("icon", icon);
map.insert("label", label);
map.insert("current", current);
QVariant result;

View file

@ -41,11 +41,19 @@ public:
QQuickItem* getDesktop();
QQuickItem* getToolWindow();
enum Icon {
ICON_NONE = 0,
ICON_QUESTION,
ICON_INFORMATION,
ICON_WARNING,
ICON_CRITICAL,
ICON_PLACEMARK
};
// Message box compatibility
Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
Q_INVOKABLE QMessageBox::StandardButton messageBox(Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
// Must be called from the main thread
QQuickItem* createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
QQuickItem* createMessageBox(Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
// Must be called from the main thread
Q_INVOKABLE int waitForMessageBoxResult(QQuickItem* messageBox);
@ -95,16 +103,25 @@ public:
// Compatibility with QFileDialog::getSaveFileName
static QString getSaveFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// input dialog compatibility
Q_INVOKABLE QVariant inputDialog(const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
QQuickItem* createInputDialog(const QString& title, const QString& label, const QVariant& current);
Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
QQuickItem* createInputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current);
QVariant waitForInputDialogResult(QQuickItem* inputDialog);
// Compatibility with QInputDialog::getText
static QString getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
static QString getText(void* ignored, const QString & title, const QString & label,
QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0,
Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone) {
return getText(OffscreenUi::ICON_NONE, title, label, text, ok);
}
// Compatibility with QInputDialog::getItem
static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items,
int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone) {
return getItem(OffscreenUi::ICON_NONE, title, label, items, current, editable, ok);
}
static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0);
static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0);
signals:
void showDesktop();

View file

@ -303,6 +303,13 @@ void ViveControllerManager::InputDevice::handleAxisEvent(float deltaTime, uint32
}
}
// An enum for buttons which do not exist in the StandardControls enum
enum ViveButtonChannel {
LEFT_APP_MENU = controller::StandardButtonChannel::NUM_STANDARD_BUTTONS,
RIGHT_APP_MENU
};
// These functions do translation from the Steam IDs to the standard controller IDs
void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool isLeftHand) {
if (!pressed) {
@ -311,7 +318,7 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint
using namespace controller;
if (button == vr::k_EButton_ApplicationMenu) {
_buttonPressedMap.insert(isLeftHand ? LEFT_PRIMARY_THUMB : RIGHT_PRIMARY_THUMB);
_buttonPressedMap.insert(isLeftHand ? LEFT_APP_MENU : RIGHT_APP_MENU);
} else if (button == vr::k_EButton_Grip) {
_buttonPressedMap.insert(isLeftHand ? LB : RB);
} else if (button == vr::k_EButton_SteamVR_Trigger) {
@ -426,24 +433,10 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI
makePair(LEFT_HAND, "LeftHand"),
makePair(RIGHT_HAND, "RightHand"),
makePair(LEFT_PRIMARY_THUMB, "LeftPrimaryThumb"),
makePair(LEFT_SECONDARY_THUMB, "LeftSecondaryThumb"),
makePair(RIGHT_PRIMARY_THUMB, "RightPrimaryThumb"),
makePair(RIGHT_SECONDARY_THUMB, "RightSecondaryThumb"),
Input::NamedPair(Input(_deviceID, LEFT_APP_MENU, ChannelType::BUTTON), "LeftApplicationMenu"),
Input::NamedPair(Input(_deviceID, RIGHT_APP_MENU, ChannelType::BUTTON), "RightApplicationMenu"),
};
//availableInputs.append(Input::NamedPair(makeInput(BUTTON_A, 0), "Left Button A"));
//availableInputs.append(Input::NamedPair(makeInput(GRIP_BUTTON, 0), "Left Grip Button"));
//availableInputs.append(Input::NamedPair(makeInput(TRACKPAD_BUTTON, 0), "Left Trackpad Button"));
//availableInputs.append(Input::NamedPair(makeInput(TRIGGER_BUTTON, 0), "Left Trigger Button"));
//availableInputs.append(Input::NamedPair(makeInput(BACK_TRIGGER, 0), "Left Back Trigger"));
//availableInputs.append(Input::NamedPair(makeInput(RIGHT_HAND), "Right Hand"));
//availableInputs.append(Input::NamedPair(makeInput(BUTTON_A, 1), "Right Button A"));
//availableInputs.append(Input::NamedPair(makeInput(GRIP_BUTTON, 1), "Right Grip Button"));
//availableInputs.append(Input::NamedPair(makeInput(TRACKPAD_BUTTON, 1), "Right Trackpad Button"));
//availableInputs.append(Input::NamedPair(makeInput(TRIGGER_BUTTON, 1), "Right Trigger Button"));
//availableInputs.append(Input::NamedPair(makeInput(BACK_TRIGGER, 1), "Right Back Trigger"));
return availableInputs;
}
@ -451,31 +444,3 @@ QString ViveControllerManager::InputDevice::getDefaultMappingConfig() const {
static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/vive.json";
return MAPPING_JSON;
}
//void ViveControllerManager::assignDefaultInputMapping(UserInputMapper& mapper) {
// const float JOYSTICK_MOVE_SPEED = 1.0f;
//
// // Left Trackpad: Movement, strafing
// mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(AXIS_Y_POS, 0), makeInput(TRACKPAD_BUTTON, 0), JOYSTICK_MOVE_SPEED);
// mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(AXIS_Y_NEG, 0), makeInput(TRACKPAD_BUTTON, 0), JOYSTICK_MOVE_SPEED);
// mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(AXIS_X_POS, 0), makeInput(TRACKPAD_BUTTON, 0), JOYSTICK_MOVE_SPEED);
// mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(AXIS_X_NEG, 0), makeInput(TRACKPAD_BUTTON, 0), JOYSTICK_MOVE_SPEED);
//
// // Right Trackpad: Vertical movement, zooming
// mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(AXIS_Y_POS, 1), makeInput(TRACKPAD_BUTTON, 1), JOYSTICK_MOVE_SPEED);
// mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(AXIS_Y_NEG, 1), makeInput(TRACKPAD_BUTTON, 1), JOYSTICK_MOVE_SPEED);
//
// // Buttons
// mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_A, 0));
// mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_A, 1));
//
// mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(GRIP_BUTTON, 0));
// mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(GRIP_BUTTON, 1));
//
// mapper.addInputChannel(UserInputMapper::LEFT_HAND_CLICK, makeInput(BACK_TRIGGER, 0));
// mapper.addInputChannel(UserInputMapper::RIGHT_HAND_CLICK, makeInput(BACK_TRIGGER, 1));
//
// // Hands
// mapper.addInputChannel(UserInputMapper::LEFT_HAND, makeInput(LEFT_HAND));
// mapper.addInputChannel(UserInputMapper::RIGHT_HAND, makeInput(RIGHT_HAND));
//}

View file

@ -9,6 +9,7 @@ import "../../../interface/resources/qml/windows-uit"
import "../../../interface/resources/qml/dialogs"
import "../../../interface/resources/qml/hifi"
import "../../../interface/resources/qml/hifi/dialogs"
import "../../../interface/resources/qml/styles-uit"
ApplicationWindow {
id: appWindow
@ -17,6 +18,8 @@ ApplicationWindow {
height: 800
title: qsTr("Scratch App")
HifiConstants { id: hifi }
Desktop {
id: desktop
anchors.fill: parent
@ -99,11 +102,11 @@ ApplicationWindow {
var messageBox = desktop.messageBox({
title: "Set Avatar",
text: "Would you like to use 'Albert' for your avatar?",
icon: OriginalDialogs.StandardIcon.Question, // Test question icon
//icon: OriginalDialogs.StandardIcon.Information, // Test informaton icon
//icon: OriginalDialogs.StandardIcon.Warning, // Test warning icon
//icon: OriginalDialogs.StandardIcon.Critical, // Test critical icon
//icon: OriginalDialogs.StandardIcon.NoIcon, // Test no icon
icon: hifi.icons.question, // Test question icon
//icon: hifi.icons.information, // Test informaton icon
//icon: hifi.icons.warning, // Test warning icon
//icon: hifi.icons.critical, // Test critical icon
//icon: hifi.icons.none, // Test no icon
buttons: OriginalDialogs.StandardButton.Ok + OriginalDialogs.StandardButton.Cancel,
defaultButton: OriginalDialogs.StandardButton.Ok
});
@ -118,7 +121,7 @@ ApplicationWindow {
onClicked: {
var messageBox = desktop.messageBox({
text: "Diagnostic cycle will be complete in 30 seconds",
icon: OriginalDialogs.StandardIcon.Critical,
icon: hifi.icons.critical,
});
messageBox.selected.connect(function(button) {
console.log("You clicked " + button)
@ -132,11 +135,45 @@ ApplicationWindow {
desktop.messageBox({
informativeText: "Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds ",
text: "Baloney",
icon: OriginalDialogs.StandardIcon.Warning,
icon: hifi.icons.warning,
detailedText: "sakjd;laskj dksa;dl jka;lsd j;lkjas ;dlkaj s;dlakjd ;alkjda; slkjda; lkjda;lksjd ;alksjd; alksjd ;alksjd; alksjd; alksdjas;ldkjas;lkdja ;kj ;lkasjd; lkj as;dlka jsd;lka jsd;laksjd a"
});
}
}
Button {
text: "Bookmark Location"
onClicked: {
desktop.inputDialog({
title: "Bookmark Location",
icon: hifi.icons.placemark,
label: "Name"
});
}
}
Button {
text: "Delete Bookmark"
onClicked: {
desktop.inputDialog({
title: "Delete Bookmark",
icon: hifi.icons.placemark,
label: "Select the bookmark to delete",
items: ["Bookmark A", "Bookmark B", "Bookmark C"]
});
}
}
Button {
text: "Duplicate Bookmark"
onClicked: {
desktop.messageBox({
title: "Duplicate Bookmark",
icon: hifi.icons.warning,
text: "The bookmark name you entered alread exists in yoru list.",
informativeText: "Would you like to overwrite it?",
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
defaultButton: OriginalDialogs.StandardButton.Yes
});
}
}
/*
// There is no such desktop.queryBox() function; may need to update test to cover QueryDialog.qml?
Button {
@ -145,7 +182,7 @@ ApplicationWindow {
var queryBox = desktop.queryBox({
text: "Have you stopped beating your wife?",
placeholderText: "Are you sure?",
// icon: OriginalDialogs.StandardIcon.Critical,
// icon: hifi.icons.critical,
});
queryBox.selected.connect(function(result) {
console.log("User responded with " + result);