mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
add workload job to help debug entity proxies
This commit is contained in:
parent
5f2f647dfb
commit
cf08a4162a
12 changed files with 275 additions and 6 deletions
|
@ -87,6 +87,8 @@ class PickScriptingInterface : public QObject, public Dependency {
|
|||
|
||||
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
|
||||
|
||||
Q_PROPERTY(unsigned int PICK_BYPASS_IGNORE READ PICK_BYPASS_IGNORE CONSTANT)
|
||||
|
||||
Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT)
|
||||
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT)
|
||||
|
@ -282,6 +284,8 @@ public:
|
|||
unsigned int getPerFrameTimeBudget() const;
|
||||
void setPerFrameTimeBudget(unsigned int numUsecs);
|
||||
|
||||
static constexpr unsigned int PICK_BYPASS_IGNORE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_BYPASS_IGNORE); }
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
|
|
|
@ -17,7 +17,7 @@ GameplayObjects::GameplayObjects() {
|
|||
}
|
||||
|
||||
bool GameplayObjects::addToGameplayObjects(const QUuid& avatarID) {
|
||||
containsData = true;
|
||||
_containsData = true;
|
||||
if (std::find(_avatarIDs.begin(), _avatarIDs.end(), avatarID) == _avatarIDs.end()) {
|
||||
_avatarIDs.push_back(avatarID);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ bool GameplayObjects::removeFromGameplayObjects(const QUuid& avatarID) {
|
|||
}
|
||||
|
||||
bool GameplayObjects::addToGameplayObjects(const EntityItemID& entityID) {
|
||||
containsData = true;
|
||||
_containsData = true;
|
||||
if (std::find(_entityIDs.begin(), _entityIDs.end(), entityID) == _entityIDs.end()) {
|
||||
_entityIDs.push_back(entityID);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class GameplayObjects {
|
|||
public:
|
||||
GameplayObjects();
|
||||
|
||||
bool getContainsData() const { return containsData; }
|
||||
bool getContainsData() const { return _containsData; }
|
||||
|
||||
std::vector<QUuid> getAvatarIDs() const { return _avatarIDs; }
|
||||
bool addToGameplayObjects(const QUuid& avatarID);
|
||||
|
@ -37,7 +37,7 @@ public:
|
|||
bool removeFromGameplayObjects(const EntityItemID& entityID);
|
||||
|
||||
private:
|
||||
bool containsData { false };
|
||||
bool _containsData { false };
|
||||
std::vector<QUuid> _avatarIDs;
|
||||
std::vector<EntityItemID> _entityIDs;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
#include "GameWorkload.h"
|
||||
#include "GameWorkloadRenderer.h"
|
||||
#include "SelectedWorkloadRenderer.h"
|
||||
#include <ViewFrustum.h>
|
||||
#include <workload/RegionTracker.h>
|
||||
#include <workload/SpaceClassifier.h>
|
||||
|
@ -35,6 +36,7 @@ public:
|
|||
model.addJob<PhysicsBoundary>("PhysicsBoundary", regionTrackerOut);
|
||||
|
||||
model.addJob<GameSpaceToRender>("SpaceToRender");
|
||||
model.addJob<SelectedWorkloadRenderer>("SelectedWorkloadRender");
|
||||
|
||||
out = regionTrackerOut;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <GeometryCache.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "SelectedWorkloadRenderer.h"
|
||||
|
||||
void GameSpaceToRender::configure(const Config& config) {
|
||||
_freezeViews = config.freezeViews;
|
||||
|
|
88
interface/src/workload/SelectedWorkloadRenderer.cpp
Normal file
88
interface/src/workload/SelectedWorkloadRenderer.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// SelectedWorkloadRenderer.cpp
|
||||
//
|
||||
// Created by Andrew Meadows 2019.11.08
|
||||
// Copyright 2019 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 "SelectedWorkloadRenderer.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <gpu/Context.h>
|
||||
|
||||
#include <workload/Space.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "GameWorkloadRenderer.h"
|
||||
#include "scripting/SelectionScriptingInterface.h"
|
||||
|
||||
void SelectedWorkloadRenderer::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) {
|
||||
auto gameWorkloadContext = std::dynamic_pointer_cast<GameWorkloadContext>(runContext);
|
||||
if (!gameWorkloadContext) {
|
||||
return;
|
||||
}
|
||||
auto space = gameWorkloadContext->_space;
|
||||
if (!space) {
|
||||
return;
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
auto scene = gameWorkloadContext->_scene;
|
||||
|
||||
auto selection = DependencyManager::get<SelectionScriptingInterface>();
|
||||
// Note: the "DebugWorkloadSelection" name is a secret hard-coded C++ debug feature.
|
||||
// If you create such a named list using JS and the "Selection" API then it will be picked up here
|
||||
// and the workload proxies for corresponding entities will be rendered.
|
||||
GameplayObjects selectedObjects = selection->getList("DebugWorkloadSelection");
|
||||
|
||||
if (!selectedObjects.getContainsData()) {
|
||||
// nothing to render
|
||||
// clear item if it exists and bail
|
||||
if (render::Item::isValidID(_spaceRenderItemID)) {
|
||||
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [](GameWorkloadRenderItem& item) {
|
||||
item.setVisible(false);
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<EntityItemID> entityIDs = selectedObjects.getEntityIDs();
|
||||
workload::indexed_container::Indices indices;
|
||||
indices.reserve(entityIDs.size());
|
||||
|
||||
auto entityTreeRenderer = qApp->getEntities();
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
for (auto id : entityIDs) {
|
||||
EntityItemPointer entity = entityTree->findEntityByID(id);
|
||||
if (entity) {
|
||||
indices.push_back(entity->getSpaceIndex());
|
||||
}
|
||||
}
|
||||
|
||||
workload::Proxy::Vector proxies;
|
||||
proxies.reserve(indices.size());
|
||||
space->copySelectedProxyValues(proxies, indices);
|
||||
|
||||
if (!render::Item::isValidID(_spaceRenderItemID)) {
|
||||
_spaceRenderItemID = scene->allocateID();
|
||||
auto renderItem = std::make_shared<GameWorkloadRenderItem>();
|
||||
renderItem->editBound().setBox(glm::vec3(-16000.0f), 32000.0f);
|
||||
transaction.resetItem(_spaceRenderItemID, std::make_shared<GameWorkloadRenderItem::Payload>(renderItem));
|
||||
}
|
||||
|
||||
bool showProxies = true;
|
||||
bool showViews = false;
|
||||
bool visible = true;
|
||||
workload::Views views(0);
|
||||
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [visible, showProxies, proxies, showViews, views](GameWorkloadRenderItem& item) {
|
||||
item.setVisible(visible);
|
||||
item.showProxies(showProxies);
|
||||
item.setAllProxies(proxies);
|
||||
item.showViews(showViews);
|
||||
item.setAllViews(views);
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
32
interface/src/workload/SelectedWorkloadRenderer.h
Normal file
32
interface/src/workload/SelectedWorkloadRenderer.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// GameWorkloadRender.h
|
||||
//
|
||||
// Created by Sam Gateau on 2/20/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
|
||||
//
|
||||
#ifndef hifi_SelectedWorkloadRenderer_h
|
||||
#define hifi_SelectedWorkloadRenderer_h
|
||||
|
||||
#include "GameWorkload.h"
|
||||
|
||||
#include "GameWorkloadRenderer.h"
|
||||
|
||||
class SelectedWorkloadRenderer {
|
||||
public:
|
||||
using Config = GameSpaceToRenderConfig;
|
||||
using Outputs = render::Transaction;
|
||||
using JobModel = workload::Job::ModelO<SelectedWorkloadRenderer, Outputs, Config>;
|
||||
|
||||
SelectedWorkloadRenderer() {}
|
||||
|
||||
void configure(const Config& config) {}
|
||||
void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs);
|
||||
|
||||
protected:
|
||||
render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID };
|
||||
};
|
||||
|
||||
#endif
|
|
@ -197,7 +197,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori
|
|||
// only called if we do intersect our bounding cube, but find if we actually intersect with entities...
|
||||
EntityItemID entityID;
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
if (entity->getIgnorePickIntersection()) {
|
||||
if (entity->getIgnorePickIntersection() && !searchFilter.bypassIgnore()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3
|
|||
// only called if we do intersect our bounding cube, but find if we actually intersect with entities...
|
||||
EntityItemID entityID;
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
if (entity->getIgnorePickIntersection()) {
|
||||
if (entity->getIgnorePickIntersection() && !searchFilter.bypassIgnore()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define hifi_PickFilter_h
|
||||
|
||||
#include <bitset>
|
||||
#include <iostream> // adebug
|
||||
|
||||
class PickFilter {
|
||||
public:
|
||||
|
@ -60,6 +61,8 @@ public:
|
|||
// NOT YET IMPLEMENTED
|
||||
PICK_ALL_INTERSECTIONS, // if not set, returns closest intersection, otherwise, returns list of all intersections
|
||||
|
||||
PICK_BYPASS_IGNORE, // for debug purposes
|
||||
|
||||
NUM_FLAGS, // Not a valid flag
|
||||
};
|
||||
typedef std::bitset<NUM_FLAGS> Flags;
|
||||
|
@ -93,6 +96,8 @@ public:
|
|||
|
||||
bool doesWantAllIntersections() const { return _flags[PICK_ALL_INTERSECTIONS]; }
|
||||
|
||||
bool bypassIgnore() const { return _flags[PICK_BYPASS_IGNORE]; }
|
||||
|
||||
// Helpers for RayPickManager
|
||||
Flags getEntityFlags() const {
|
||||
unsigned int toReturn = 0;
|
||||
|
|
|
@ -127,6 +127,18 @@ uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const {
|
|||
return numCopied;
|
||||
}
|
||||
|
||||
uint32_t Space::copySelectedProxyValues(Proxy::Vector& proxies, const workload::indexed_container::Indices& indices) const {
|
||||
std::unique_lock<std::mutex> lock(_proxiesMutex);
|
||||
uint32_t numCopied = 0;
|
||||
for (auto index : indices) {
|
||||
if (isAllocatedID(index) && (index < (Index)_proxies.size())) {
|
||||
proxies.push_back(_proxies[index]);
|
||||
++numCopied;
|
||||
}
|
||||
}
|
||||
return numCopied;
|
||||
}
|
||||
|
||||
const Owner Space::getOwner(int32_t proxyID) const {
|
||||
std::unique_lock<std::mutex> lock(_proxiesMutex);
|
||||
if (isAllocatedID(proxyID) && (proxyID < (Index)_proxies.size())) {
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
|
||||
void categorizeAndGetChanges(std::vector<Change>& changes);
|
||||
uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const;
|
||||
uint32_t copySelectedProxyValues(Proxy::Vector& proxies, const workload::indexed_container::Indices& indices) const;
|
||||
|
||||
const Owner getOwner(int32_t proxyID) const;
|
||||
uint8_t getRegion(int32_t proxyID) const;
|
||||
|
|
124
scripts/developer/debugging/debugWorkloadWithMouseHover.js
Normal file
124
scripts/developer/debugging/debugWorkloadWithMouseHover.js
Normal file
|
@ -0,0 +1,124 @@
|
|||
//
|
||||
// debugWorkloadWithMouseHover.js - render workload proxy for entity under mouse hover
|
||||
//
|
||||
// Copyright 2019 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
|
||||
//
|
||||
|
||||
"use strict";
|
||||
|
||||
(function() {
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
});
|
||||
|
||||
// Create a Laser pointer used to pick and add entity to selection
|
||||
var END_DIMENSIONS = { x: 0.05, y: 0.05, z: 0.05 };
|
||||
var COLOR1 = {red: 255, green: 0, blue: 255}; // magenta
|
||||
var COLOR2 = {red: 255, green: 255, blue: 0}; // yellow
|
||||
var end1 = {
|
||||
type: "sphere",
|
||||
dimensions: END_DIMENSIONS,
|
||||
color: COLOR1,
|
||||
ignorePickIntersection: true
|
||||
}
|
||||
var end2 = {
|
||||
type: "sphere",
|
||||
dimensions: END_DIMENSIONS,
|
||||
color: COLOR2,
|
||||
ignorePickIntersection: true
|
||||
}
|
||||
var laser = Pointers.createPointer(PickType.Ray, {
|
||||
joint: "Mouse",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_BYPASS_IGNORE | Picks.PICK_INCLUDE_COLLIDABLE | Picks.PICK_INCLUDE_NONCOLLIDABLE,
|
||||
renderStates: [{name: "one", end: end1}],
|
||||
defaultRenderStates: [{name: "one", end: end2, distance: 2.0}],
|
||||
enabled: true
|
||||
});
|
||||
Pointers.setRenderState(laser, "one");
|
||||
var hoveredObject = undefined;
|
||||
|
||||
var SelectionListName = "DebugWorkloadSelection"; // sekret undocumented selection list (hard coded in C++)
|
||||
var selectionStyle = {
|
||||
isOutlineSmooth: true,
|
||||
outlineWidth: 5,
|
||||
outlineUnoccludedColor: {red: 255, green: 128, blue: 128},
|
||||
outlineUnoccludedAlpha: 0.88,
|
||||
outlineOccludedColor: {red: 255, green: 128, blue: 128},
|
||||
outlineOccludedAlpha:0.5,
|
||||
fillUnoccludedColor: {red: 26, green: 0, blue: 0},
|
||||
fillUnoccludedAlpha: 0.0,
|
||||
fillOccludedColor: {red: 26, green: 0, blue: 0},
|
||||
fillOccludedAlpha: 0.0
|
||||
}
|
||||
Selection.enableListHighlight(SelectionListName, selectionStyle)
|
||||
|
||||
var isSelectionEnabled = false
|
||||
|
||||
function setSelectionEnabled(enabled) {
|
||||
if (isSelectionEnabled != enabled) {
|
||||
isSelectionEnabled = enabled;
|
||||
//print("isSelectionEnabled set to " + isSelectionEnabled.toString())
|
||||
if (isSelectionEnabled) {
|
||||
Pointers.enablePointer(laser)
|
||||
} else {
|
||||
Pointers.disablePointer(laser)
|
||||
Selection.clearSelectedItemsList(SelectionListName)
|
||||
}
|
||||
}
|
||||
}
|
||||
setSelectionEnabled(true);
|
||||
|
||||
function getIntersectionTypeString(type) {
|
||||
if (type === Picks.INTERSECTED_ENTITY) {
|
||||
return "entity";
|
||||
} else if (type === Picks.INTERSECTED_OVERLAY) {
|
||||
return "overlay";
|
||||
} else if (type === Picks.INTERSECTED_AVATAR) {
|
||||
return "avatar";
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
var result = Pointers.getPrevPickResult(laser);
|
||||
if (result.intersects) {
|
||||
if (hoveredObject !== undefined && result.objectID !== hoveredObject.objectID) {
|
||||
// Hovering on something different
|
||||
if (isSelectionEnabled) {
|
||||
Selection.removeFromSelectedItemsList(SelectionListName, getIntersectionTypeString(hoveredObject.type), hoveredObject.objectID)
|
||||
//print("remove helloDebugHighlight " + hoveredObject.objectID.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (isSelectionEnabled) {
|
||||
if (hoveredObject === undefined || result.objectID !== hoveredObject.objectID) {
|
||||
// Hovering over something new
|
||||
Selection.addToSelectedItemsList(SelectionListName, getIntersectionTypeString(result.type), result.objectID);
|
||||
hoveredObject = result;
|
||||
//print("add helloDebugHighlight " + hoveredObject.objectID.toString() + " type = '" + getIntersectionTypeString(result.type) + "'");
|
||||
}
|
||||
}
|
||||
} else if (hoveredObject !== undefined) {
|
||||
// Stopped hovering
|
||||
if (isSelectionEnabled) {
|
||||
Selection.removeFromSelectedItemsList(SelectionListName, getIntersectionTypeString(hoveredObject.type), hoveredObject.objectID)
|
||||
hoveredObject = undefined;
|
||||
//print("clear helloDebugHighlight");
|
||||
}
|
||||
}
|
||||
}
|
||||
Script.update.connect(update);
|
||||
|
||||
function cleanup() {
|
||||
Pointers.removePointer(laser);
|
||||
Selection.disableListHighlight(SelectionListName)
|
||||
Selection.removeListFromMap(SelectionListName)
|
||||
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
||||
}());
|
||||
|
||||
|
Loading…
Reference in a new issue