mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 20:55:10 +02:00
add support for scripts to call methods on entity scripts
This commit is contained in:
parent
8f5055d212
commit
0d37511071
7 changed files with 92 additions and 46 deletions
|
@ -69,6 +69,7 @@ var STATE_CLOSE_GRABBING = 2;
|
||||||
var STATE_CONTINUE_CLOSE_GRABBING = 3;
|
var STATE_CONTINUE_CLOSE_GRABBING = 3;
|
||||||
var STATE_RELEASE = 4;
|
var STATE_RELEASE = 4;
|
||||||
|
|
||||||
|
var GRAB_USER_DATA_KEY = "grabKey";
|
||||||
|
|
||||||
function controller(hand, triggerAction) {
|
function controller(hand, triggerAction) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
|
@ -89,6 +90,7 @@ function controller(hand, triggerAction) {
|
||||||
this.state = 0; // 0 = searching, 1 = distanceHolding, 2 = closeGrabbing
|
this.state = 0; // 0 = searching, 1 = distanceHolding, 2 = closeGrabbing
|
||||||
this.pointer = null; // entity-id of line object
|
this.pointer = null; // entity-id of line object
|
||||||
this.triggerValue = 0; // rolling average of trigger value
|
this.triggerValue = 0; // rolling average of trigger value
|
||||||
|
this.alreadyDistanceHolding = false; // FIXME - I'll leave it to Seth to potentially make this another state
|
||||||
|
|
||||||
this.update = function() {
|
this.update = function() {
|
||||||
switch(this.state) {
|
switch(this.state) {
|
||||||
|
@ -210,13 +212,20 @@ function controller(hand, triggerAction) {
|
||||||
this.distanceHolding = function() {
|
this.distanceHolding = function() {
|
||||||
if (!this.triggerSmoothedSqueezed()) {
|
if (!this.triggerSmoothedSqueezed()) {
|
||||||
this.state = STATE_RELEASE;
|
this.state = STATE_RELEASE;
|
||||||
|
this.alreadyDistanceHolding = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.alreadyDistanceHolding) {
|
||||||
|
this.activateEntity(this.grabbedEntity);
|
||||||
|
this.alreadyDistanceHolding = true;
|
||||||
|
}
|
||||||
|
|
||||||
var handPosition = this.getHandPosition();
|
var handPosition = this.getHandPosition();
|
||||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||||
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
||||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity);
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position","rotation"]);
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "distanceHolding");
|
||||||
|
|
||||||
this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR);
|
this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR);
|
||||||
|
|
||||||
|
@ -270,7 +279,9 @@ function controller(hand, triggerAction) {
|
||||||
|
|
||||||
this.lineOff();
|
this.lineOff();
|
||||||
|
|
||||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity);
|
this.activateEntity(this.grabbedEntity);
|
||||||
|
|
||||||
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, "position");
|
||||||
|
|
||||||
var handRotation = this.getHandRotation();
|
var handRotation = this.getHandRotation();
|
||||||
var handPosition = this.getHandPosition();
|
var handPosition = this.getHandPosition();
|
||||||
|
@ -294,6 +305,7 @@ function controller(hand, triggerAction) {
|
||||||
} else {
|
} else {
|
||||||
this.state = STATE_CONTINUE_CLOSE_GRABBING;
|
this.state = STATE_CONTINUE_CLOSE_GRABBING;
|
||||||
}
|
}
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "closeGrabbing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -324,6 +336,7 @@ function controller(hand, triggerAction) {
|
||||||
|
|
||||||
this.currentObjectPosition = grabbedProperties.position;
|
this.currentObjectPosition = grabbedProperties.position;
|
||||||
this.currentObjectTime = now;
|
this.currentObjectTime = now;
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "continueCloseGrabbing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -336,7 +349,10 @@ function controller(hand, triggerAction) {
|
||||||
|
|
||||||
// the action will tend to quickly bring an object's velocity to zero. now that
|
// the action will tend to quickly bring an object's velocity to zero. now that
|
||||||
// the action is gone, set the objects velocity to something the holder might expect.
|
// the action is gone, set the objects velocity to something the holder might expect.
|
||||||
Entities.editEntity(this.grabbedEntity, {velocity: this.grabbedVelocity});
|
Entities.editEntity(this.grabbedEntity, { velocity: this.grabbedVelocity });
|
||||||
|
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "release");
|
||||||
|
this.deactivateEntity(this.grabbedEntity);
|
||||||
|
|
||||||
this.grabbedVelocity = ZERO_VEC;
|
this.grabbedVelocity = ZERO_VEC;
|
||||||
this.grabbedEntity = null;
|
this.grabbedEntity = null;
|
||||||
|
@ -348,6 +364,22 @@ function controller(hand, triggerAction) {
|
||||||
this.cleanup = function() {
|
this.cleanup = function() {
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.activateEntity = function(entity) {
|
||||||
|
var data = {
|
||||||
|
activated: true,
|
||||||
|
avatarId: MyAvatar.sessionUUID
|
||||||
|
};
|
||||||
|
setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deactivateEntity = function(entity) {
|
||||||
|
var data = {
|
||||||
|
activated: false,
|
||||||
|
avatarId: null
|
||||||
|
};
|
||||||
|
setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
Script.include("../libraries/utils.js");
|
|
||||||
|
|
||||||
var _this;
|
var _this;
|
||||||
|
|
||||||
|
@ -24,39 +23,18 @@
|
||||||
|
|
||||||
DetectGrabbed.prototype = {
|
DetectGrabbed.prototype = {
|
||||||
|
|
||||||
// update() will be called regulary, because we've hooked the update signal in our preload() function
|
distanceHolding: function () {
|
||||||
// we will check out userData for the grabData. In the case of the hydraGrab script, it will tell us
|
print("I am being distance held... entity:" + this.entityID);
|
||||||
// if we're currently being grabbed and if the person grabbing us is the current interfaces avatar.
|
},
|
||||||
// we will watch this for state changes and print out if we're being grabbed or released when it changes.
|
|
||||||
update: function() {
|
|
||||||
var GRAB_USER_DATA_KEY = "grabKey";
|
|
||||||
|
|
||||||
// because the update() signal doesn't have a valid this, we need to use our memorized _this to access our entityID
|
closeGrabbing: function () {
|
||||||
var entityID = _this.entityID;
|
print("I was just grabbed... entity:" + this.entityID);
|
||||||
|
},
|
||||||
// we want to assume that if there is no grab data, then we are not being grabbed
|
continueCloseGrabbing: function () {
|
||||||
var defaultGrabData = { activated: false, avatarId: null };
|
print("I am still being grabbed... entity:" + this.entityID);
|
||||||
|
},
|
||||||
// this handy function getEntityCustomData() is available in utils.js and it will return just the specific section
|
release: function () {
|
||||||
// of user data we asked for. If it's not available it returns our default data.
|
print("I was released... entity:" + this.entityID);
|
||||||
var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, defaultGrabData);
|
|
||||||
|
|
||||||
// if the grabData says we're being grabbed, and the owner ID is our session, then we are being grabbed by this interface
|
|
||||||
if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) {
|
|
||||||
|
|
||||||
// remember we're being grabbed so we can detect being released
|
|
||||||
_this.beingGrabbed = true;
|
|
||||||
|
|
||||||
// print out that we're being grabbed
|
|
||||||
print("I'm being grabbed...");
|
|
||||||
|
|
||||||
} else if (_this.beingGrabbed) {
|
|
||||||
|
|
||||||
// if we are not being grabbed, and we previously were, then we were just released, remember that
|
|
||||||
// and print out a message
|
|
||||||
_this.beingGrabbed = false;
|
|
||||||
print("I'm was released...");
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// preload() will be called when the entity has become visible (or known) to the interface
|
// preload() will be called when the entity has become visible (or known) to the interface
|
||||||
|
@ -65,14 +43,6 @@
|
||||||
// * connecting to the update signal so we can check our grabbed state
|
// * connecting to the update signal so we can check our grabbed state
|
||||||
preload: function(entityID) {
|
preload: function(entityID) {
|
||||||
this.entityID = entityID;
|
this.entityID = entityID;
|
||||||
Script.update.connect(this.update);
|
|
||||||
},
|
|
||||||
|
|
||||||
// unload() will be called when our entity is no longer available. It may be because we were deleted,
|
|
||||||
// or because we've left the domain or quit the application. In all cases we want to unhook our connection
|
|
||||||
// to the update signal
|
|
||||||
unload: function(entityID) {
|
|
||||||
Script.update.disconnect(this.update);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,7 @@ void EntityTreeRenderer::init() {
|
||||||
_scriptingServices->getControllerScriptingInterface());
|
_scriptingServices->getControllerScriptingInterface());
|
||||||
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
||||||
_entitiesScriptEngine->runInThread();
|
_entitiesScriptEngine->runInThread();
|
||||||
|
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(_entitiesScriptEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure our "last avatar position" is something other than our current position, so that on our
|
// make sure our "last avatar position" is something other than our current position, so that on our
|
||||||
|
|
25
libraries/entities/src/EntitiesScriptEngineProvider.h
Normal file
25
libraries/entities/src/EntitiesScriptEngineProvider.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// EntitiesScriptEngineProvider.h
|
||||||
|
// libraries/entities/src
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on Sept. 18, 2015
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// TODO: How will we handle collision callbacks with Entities
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_EntitiesScriptEngineProvider_h
|
||||||
|
#define hifi_EntitiesScriptEngineProvider_h
|
||||||
|
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include "EntityItemID.h"
|
||||||
|
|
||||||
|
class EntitiesScriptEngineProvider {
|
||||||
|
public:
|
||||||
|
virtual void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_EntitiesScriptEngineProvider_h
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "EntityScriptingInterface.h"
|
#include "EntityScriptingInterface.h"
|
||||||
|
|
||||||
|
#include "EntityItemID.h"
|
||||||
#include <VariantMapToScriptValue.h>
|
#include <VariantMapToScriptValue.h>
|
||||||
|
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
|
@ -211,6 +212,14 @@ void EntityScriptingInterface::deleteEntity(QUuid id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityScriptingInterface::callEntityMethod(QUuid id, const QString& method) {
|
||||||
|
if (_entitiesScriptEngine) {
|
||||||
|
EntityItemID entityID{ id };
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const {
|
QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const {
|
||||||
EntityItemID result;
|
EntityItemID result;
|
||||||
if (_entityTree) {
|
if (_entityTree) {
|
||||||
|
|
|
@ -20,18 +20,19 @@
|
||||||
#include <Octree.h>
|
#include <Octree.h>
|
||||||
#include <OctreeScriptingInterface.h>
|
#include <OctreeScriptingInterface.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
#include "PolyVoxEntityItem.h"
|
#include "PolyVoxEntityItem.h"
|
||||||
#include "LineEntityItem.h"
|
#include "LineEntityItem.h"
|
||||||
#include "PolyLineEntityItem.h"
|
#include "PolyLineEntityItem.h"
|
||||||
#include "EntityTree.h"
|
#include "EntityTree.h"
|
||||||
|
|
||||||
#include "EntityEditPacketSender.h"
|
#include "EntityEditPacketSender.h"
|
||||||
|
#include "EntitiesScriptEngineProvider.h"
|
||||||
|
|
||||||
|
|
||||||
class EntityTree;
|
class EntityTree;
|
||||||
class MouseEvent;
|
class MouseEvent;
|
||||||
|
|
||||||
|
|
||||||
class RayToEntityIntersectionResult {
|
class RayToEntityIntersectionResult {
|
||||||
public:
|
public:
|
||||||
RayToEntityIntersectionResult();
|
RayToEntityIntersectionResult();
|
||||||
|
@ -63,6 +64,7 @@ public:
|
||||||
|
|
||||||
void setEntityTree(EntityTreePointer modelTree);
|
void setEntityTree(EntityTreePointer modelTree);
|
||||||
EntityTreePointer getEntityTree() { return _entityTree; }
|
EntityTreePointer getEntityTree() { return _entityTree; }
|
||||||
|
void setEntitiesScriptEngine(EntitiesScriptEngineProvider* engine) { _entitiesScriptEngine = engine; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -86,6 +88,11 @@ public slots:
|
||||||
/// deletes a model
|
/// deletes a model
|
||||||
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
||||||
|
|
||||||
|
/// Allows a script to call a method on an entity's script. The method will execute in the entity script
|
||||||
|
/// engine. If the entity does not have an entity script or the method does not exist, this call will have
|
||||||
|
/// no effect.
|
||||||
|
Q_INVOKABLE void callEntityMethod(QUuid entityID, const QString& method);
|
||||||
|
|
||||||
/// finds the closest model to the center point, within the radius
|
/// finds the closest model to the center point, within the radius
|
||||||
/// will return a EntityItemID.isKnownID = false if no models are in the radius
|
/// will return a EntityItemID.isKnownID = false if no models are in the radius
|
||||||
/// this function will not find any models in script engine contexts which don't have access to models
|
/// this function will not find any models in script engine contexts which don't have access to models
|
||||||
|
@ -180,6 +187,7 @@ private:
|
||||||
bool precisionPicking);
|
bool precisionPicking);
|
||||||
|
|
||||||
EntityTreePointer _entityTree;
|
EntityTreePointer _entityTree;
|
||||||
|
EntitiesScriptEngineProvider* _entitiesScriptEngine = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityScriptingInterface_h
|
#endif // hifi_EntityScriptingInterface_h
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <AvatarHashMap.h>
|
#include <AvatarHashMap.h>
|
||||||
#include <LimitedNodeList.h>
|
#include <LimitedNodeList.h>
|
||||||
#include <EntityItemID.h>
|
#include <EntityItemID.h>
|
||||||
|
#include <EntitiesScriptEngineProvider.h>
|
||||||
|
|
||||||
#include "AbstractControllerScriptingInterface.h"
|
#include "AbstractControllerScriptingInterface.h"
|
||||||
#include "ArrayBufferClass.h"
|
#include "ArrayBufferClass.h"
|
||||||
|
@ -46,7 +47,7 @@ public:
|
||||||
QScriptValue scriptObject;
|
QScriptValue scriptObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScriptEngine : public QScriptEngine, public ScriptUser {
|
class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScriptEngineProvider {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT,
|
ScriptEngine(const QString& scriptContents = NO_SCRIPT,
|
||||||
|
|
Loading…
Reference in a new issue