mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 04:24:47 +02:00
add support for enter/leave entity events for when the avatar enters or leaves the bounds of an entity
This commit is contained in:
parent
252d05282b
commit
e12e3b05e1
6 changed files with 114 additions and 0 deletions
32
examples/entityScripts/playSoundOnEnterOrLeave.js
Normal file
32
examples/entityScripts/playSoundOnEnterOrLeave.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// playSoundOnEnterOrLeave.js
|
||||||
|
// examples/entityScripts
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 11/3/14.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This is an example of an entity script which when assigned to an entity, that entity will play a sound in world when
|
||||||
|
// your avatar enters or leaves the bounds of the entity.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
(function(){
|
||||||
|
var bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw");
|
||||||
|
|
||||||
|
function playSound(entityID) {
|
||||||
|
var options = new AudioInjectionOptions();
|
||||||
|
var position = MyAvatar.position;
|
||||||
|
options.position = position;
|
||||||
|
options.volume = 0.5;
|
||||||
|
Audio.playSound(bird, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.enterEntity = function(entityID) {
|
||||||
|
playSound();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.leaveEntity = function(entityID) {
|
||||||
|
playSound();
|
||||||
|
};
|
||||||
|
})
|
|
@ -72,6 +72,11 @@ void EntityTreeRenderer::init() {
|
||||||
Application::getInstance()->getControllerScriptingInterface());
|
Application::getInstance()->getControllerScriptingInterface());
|
||||||
Application::getInstance()->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
Application::getInstance()->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure our "last avatar position" is something other than our current position, so that on our
|
||||||
|
// first chance, we'll check for enter/leave entity events.
|
||||||
|
glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition();
|
||||||
|
_lastAvatarPosition = avatarPosition + glm::vec3(1.f,1.f,1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID) {
|
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID) {
|
||||||
|
@ -183,6 +188,58 @@ void EntityTreeRenderer::update() {
|
||||||
if (_tree) {
|
if (_tree) {
|
||||||
EntityTree* tree = static_cast<EntityTree*>(_tree);
|
EntityTree* tree = static_cast<EntityTree*>(_tree);
|
||||||
tree->update();
|
tree->update();
|
||||||
|
|
||||||
|
// check to see if the avatar has moved and if we need to handle enter/leave entity logic
|
||||||
|
checkEnterLeaveEntities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||||
|
if (_tree) {
|
||||||
|
glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition() / (float)TREE_SCALE;
|
||||||
|
|
||||||
|
if (avatarPosition != _lastAvatarPosition) {
|
||||||
|
float radius = 1.0f / (float)TREE_SCALE; // for now, assume 1 meter radius
|
||||||
|
QVector<const EntityItem*> foundEntities;
|
||||||
|
QVector<EntityItemID> entitiesContainingAvatar;
|
||||||
|
|
||||||
|
// find the entities near us
|
||||||
|
static_cast<EntityTree*>(_tree)->findEntities(avatarPosition, radius, foundEntities);
|
||||||
|
|
||||||
|
// create a list of entities that actually contain the avatar's position
|
||||||
|
foreach(const EntityItem* entity, foundEntities) {
|
||||||
|
if (entity->contains(avatarPosition)) {
|
||||||
|
entitiesContainingAvatar << entity->getEntityItemID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for all of our previous containing entities, if they are no longer containing then send them a leave event
|
||||||
|
foreach(const EntityItemID& entityID, _currentEntitiesInside) {
|
||||||
|
if (!entitiesContainingAvatar.contains(entityID)) {
|
||||||
|
emit leaveEntity(entityID);
|
||||||
|
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||||
|
QScriptValue entityScript = loadEntityScript(entityID);
|
||||||
|
if (entityScript.property("leaveEntity").isValid()) {
|
||||||
|
entityScript.property("leaveEntity").call(entityScript, entityArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for all of our new containing entities, if they weren't previously containing then send them an enter event
|
||||||
|
foreach(const EntityItemID& entityID, entitiesContainingAvatar) {
|
||||||
|
if (!_currentEntitiesInside.contains(entityID)) {
|
||||||
|
emit enterEntity(entityID);
|
||||||
|
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||||
|
QScriptValue entityScript = loadEntityScript(entityID);
|
||||||
|
if (entityScript.property("enterEntity").isValid()) {
|
||||||
|
entityScript.property("enterEntity").call(entityScript, entityArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_currentEntitiesInside = entitiesContainingAvatar;
|
||||||
|
_lastAvatarPosition = avatarPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,6 +604,9 @@ void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityS
|
||||||
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
||||||
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||||
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||||
|
|
||||||
|
connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity);
|
||||||
|
connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValueList EntityTreeRenderer::createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID) {
|
QScriptValueList EntityTreeRenderer::createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID) {
|
||||||
|
@ -556,6 +616,12 @@ QScriptValueList EntityTreeRenderer::createMouseEventArgs(const EntityItemID& en
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entityID) {
|
||||||
|
QScriptValueList args;
|
||||||
|
args << entityID.toScriptValue(_entitiesScriptEngine);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||||
PickRay ray = computePickRay(event->x(), event->y());
|
PickRay ray = computePickRay(event->x(), event->y());
|
||||||
|
|
|
@ -104,6 +104,9 @@ signals:
|
||||||
void hoverEnterEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void hoverEnterEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
void hoverOverEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void hoverOverEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
void hoverLeaveEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void hoverLeaveEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
|
|
||||||
|
void enterEntity(const EntityItemID& entityItemID);
|
||||||
|
void leaveEntity(const EntityItemID& entityItemID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<Model*> _releasedModels;
|
QList<Model*> _releasedModels;
|
||||||
|
@ -113,6 +116,12 @@ private:
|
||||||
|
|
||||||
EntityItemID _currentHoverOverEntityID;
|
EntityItemID _currentHoverOverEntityID;
|
||||||
EntityItemID _currentClickingOnEntityID;
|
EntityItemID _currentClickingOnEntityID;
|
||||||
|
|
||||||
|
|
||||||
|
QScriptValueList createEntityArgs(const EntityItemID& entityID);
|
||||||
|
void checkEnterLeaveEntities();
|
||||||
|
glm::vec3 _lastAvatarPosition;
|
||||||
|
QVector<EntityItemID> _currentEntitiesInside;
|
||||||
|
|
||||||
bool _wantScripts;
|
bool _wantScripts;
|
||||||
ScriptEngine* _entitiesScriptEngine;
|
ScriptEngine* _entitiesScriptEngine;
|
||||||
|
|
|
@ -253,6 +253,7 @@ public:
|
||||||
|
|
||||||
void applyHardCollision(const CollisionInfo& collisionInfo);
|
void applyHardCollision(const CollisionInfo& collisionInfo);
|
||||||
virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; }
|
virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; }
|
||||||
|
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
||||||
|
|
|
@ -115,6 +115,9 @@ signals:
|
||||||
void hoverOverEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void hoverOverEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
void hoverLeaveEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void hoverLeaveEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
|
|
||||||
|
void enterEntity(const EntityItemID& entityItemID);
|
||||||
|
void leaveEntity(const EntityItemID& entityItemID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,9 @@ public:
|
||||||
|
|
||||||
virtual const Shape& getCollisionShapeInMeters() const { return _sphereShape; }
|
virtual const Shape& getCollisionShapeInMeters() const { return _sphereShape; }
|
||||||
|
|
||||||
|
// TODO: implement proper contains for 3D ellipsoid
|
||||||
|
//virtual bool contains(const glm::vec3& point) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void recalculateCollisionShape();
|
virtual void recalculateCollisionShape();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue