mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 04:42:20 +02:00
rename base action classes to dynamics, start on constraints
This commit is contained in:
parent
b07ed13023
commit
74c0a70cb0
39 changed files with 1200 additions and 872 deletions
|
@ -1,91 +0,0 @@
|
|||
//
|
||||
// AssignmentAction.cpp
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves 2015-6-19
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include "AssignmentAction.h"
|
||||
|
||||
AssignmentAction::AssignmentAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
EntityActionInterface(type, id),
|
||||
_data(QByteArray()),
|
||||
_active(false),
|
||||
_ownerEntity(ownerEntity) {
|
||||
}
|
||||
|
||||
AssignmentAction::~AssignmentAction() {
|
||||
}
|
||||
|
||||
void AssignmentAction::removeFromSimulation(EntitySimulationPointer simulation) const {
|
||||
withReadLock([&]{
|
||||
simulation->removeAction(_id);
|
||||
simulation->applyActionChanges();
|
||||
});
|
||||
}
|
||||
|
||||
QByteArray AssignmentAction::serialize() const {
|
||||
QByteArray result;
|
||||
withReadLock([&]{
|
||||
result = _data;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssignmentAction::deserialize(QByteArray serializedArguments) {
|
||||
withWriteLock([&]{
|
||||
_data = serializedArguments;
|
||||
});
|
||||
}
|
||||
|
||||
bool AssignmentAction::updateArguments(QVariantMap arguments) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::updateArguments called in assignment-client.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantMap AssignmentAction::getArguments() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::getArguments called in assignment-client.";
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
glm::vec3 AssignmentAction::getPosition() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::getPosition called in assignment-client.";
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void AssignmentAction::setPosition(glm::vec3 position) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::setPosition called in assignment-client.";
|
||||
}
|
||||
|
||||
glm::quat AssignmentAction::getRotation() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::getRotation called in assignment-client.";
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
void AssignmentAction::setRotation(glm::quat rotation) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::setRotation called in assignment-client.";
|
||||
}
|
||||
|
||||
glm::vec3 AssignmentAction::getLinearVelocity() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::getLinearVelocity called in assignment-client.";
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void AssignmentAction::setLinearVelocity(glm::vec3 linearVelocity) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::setLinearVelocity called in assignment-client.";
|
||||
}
|
||||
|
||||
glm::vec3 AssignmentAction::getAngularVelocity() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::getAngularVelocity called in assignment-client.";
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void AssignmentAction::setAngularVelocity(glm::vec3 angularVelocity) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentAction::setAngularVelocity called in assignment-client.";
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
//
|
||||
// AssignmentActionFactory.cpp
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-19
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "AssignmentActionFactory.h"
|
||||
|
||||
|
||||
EntityActionPointer assignmentActionFactory(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) {
|
||||
return EntityActionPointer(new AssignmentAction(type, id, ownerEntity));
|
||||
}
|
||||
|
||||
EntityActionPointer AssignmentActionFactory::factory(EntityActionType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) {
|
||||
EntityActionPointer action = assignmentActionFactory(type, id, ownerEntity);
|
||||
if (action) {
|
||||
bool ok = action->updateArguments(arguments);
|
||||
if (ok) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityActionPointer AssignmentActionFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) {
|
||||
QDataStream serializedActionDataStream(data);
|
||||
EntityActionType type;
|
||||
QUuid id;
|
||||
|
||||
serializedActionDataStream >> type;
|
||||
serializedActionDataStream >> id;
|
||||
|
||||
EntityActionPointer action = assignmentActionFactory(type, id, ownerEntity);
|
||||
|
||||
if (action) {
|
||||
action->deserialize(data);
|
||||
}
|
||||
return action;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// AssignmentActionFactory.cpp
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-19
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef hifi_AssignmentActionFactory_h
|
||||
#define hifi_AssignmentActionFactory_h
|
||||
|
||||
#include "EntityActionFactoryInterface.h"
|
||||
#include "AssignmentAction.h"
|
||||
|
||||
class AssignmentActionFactory : public EntityActionFactoryInterface {
|
||||
public:
|
||||
AssignmentActionFactory() : EntityActionFactoryInterface() { }
|
||||
virtual ~AssignmentActionFactory() { }
|
||||
virtual EntityActionPointer factory(EntityActionType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) override;
|
||||
virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override;
|
||||
};
|
||||
|
||||
#endif // hifi_AssignmentActionFactory_h
|
|
@ -32,7 +32,7 @@
|
|||
#include <ResourceScriptingInterface.h>
|
||||
|
||||
#include "AssignmentFactory.h"
|
||||
#include "AssignmentActionFactory.h"
|
||||
#include "AssignmentDynamicFactory.h"
|
||||
|
||||
#include "AssignmentClient.h"
|
||||
#include "AssignmentClientLogging.h"
|
||||
|
@ -63,8 +63,8 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
|||
auto animationCache = DependencyManager::set<AnimationCache>();
|
||||
auto entityScriptingInterface = DependencyManager::set<EntityScriptingInterface>(false);
|
||||
|
||||
DependencyManager::registerInheritance<EntityActionFactoryInterface, AssignmentActionFactory>();
|
||||
auto actionFactory = DependencyManager::set<AssignmentActionFactory>();
|
||||
DependencyManager::registerInheritance<EntityDynamicFactoryInterface, AssignmentDynamicFactory>();
|
||||
auto dynamicFactory = DependencyManager::set<AssignmentDynamicFactory>();
|
||||
DependencyManager::set<ResourceScriptingInterface>();
|
||||
|
||||
// setup a thread for the NodeList and its PacketReceiver
|
||||
|
|
91
assignment-client/src/AssignmentDynamic.cpp
Normal file
91
assignment-client/src/AssignmentDynamic.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// AssignmentDynamic.cpp
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves 2015-6-19
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include "AssignmentDynamic.h"
|
||||
|
||||
AssignmentDynamic::AssignmentDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
EntityDynamicInterface(type, id),
|
||||
_data(QByteArray()),
|
||||
_active(false),
|
||||
_ownerEntity(ownerEntity) {
|
||||
}
|
||||
|
||||
AssignmentDynamic::~AssignmentDynamic() {
|
||||
}
|
||||
|
||||
void AssignmentDynamic::removeFromSimulation(EntitySimulationPointer simulation) const {
|
||||
withReadLock([&]{
|
||||
simulation->removeDynamic(_id);
|
||||
simulation->applyDynamicChanges();
|
||||
});
|
||||
}
|
||||
|
||||
QByteArray AssignmentDynamic::serialize() const {
|
||||
QByteArray result;
|
||||
withReadLock([&]{
|
||||
result = _data;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssignmentDynamic::deserialize(QByteArray serializedArguments) {
|
||||
withWriteLock([&]{
|
||||
_data = serializedArguments;
|
||||
});
|
||||
}
|
||||
|
||||
bool AssignmentDynamic::updateArguments(QVariantMap arguments) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::updateArguments called in assignment-client.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantMap AssignmentDynamic::getArguments() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getArguments called in assignment-client.";
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
glm::vec3 AssignmentDynamic::getPosition() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getPosition called in assignment-client.";
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void AssignmentDynamic::setPosition(glm::vec3 position) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::setPosition called in assignment-client.";
|
||||
}
|
||||
|
||||
glm::quat AssignmentDynamic::getRotation() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getRotation called in assignment-client.";
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
void AssignmentDynamic::setRotation(glm::quat rotation) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::setRotation called in assignment-client.";
|
||||
}
|
||||
|
||||
glm::vec3 AssignmentDynamic::getLinearVelocity() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getLinearVelocity called in assignment-client.";
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void AssignmentDynamic::setLinearVelocity(glm::vec3 linearVelocity) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::setLinearVelocity called in assignment-client.";
|
||||
}
|
||||
|
||||
glm::vec3 AssignmentDynamic::getAngularVelocity() {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getAngularVelocity called in assignment-client.";
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void AssignmentDynamic::setAngularVelocity(glm::vec3 angularVelocity) {
|
||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::setAngularVelocity called in assignment-client.";
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// AssignmentAction.h
|
||||
// AssignmentDynamic.h
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves 2015-6-19
|
||||
|
@ -8,21 +8,21 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// http://bulletphysics.org/Bullet/BulletFull/classbtActionInterface.html
|
||||
// http://bulletphysics.org/Bullet/BulletFull/classbtDynamicInterface.html
|
||||
|
||||
#ifndef hifi_AssignmentAction_h
|
||||
#define hifi_AssignmentAction_h
|
||||
#ifndef hifi_AssignmentDynamic_h
|
||||
#define hifi_AssignmentDynamic_h
|
||||
|
||||
#include <QUuid>
|
||||
#include <EntityItem.h>
|
||||
|
||||
#include "EntityActionInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
|
||||
class AssignmentAction : public EntityActionInterface, public ReadWriteLockable {
|
||||
class AssignmentDynamic : public EntityDynamicInterface, public ReadWriteLockable {
|
||||
public:
|
||||
AssignmentAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~AssignmentAction();
|
||||
AssignmentDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~AssignmentDynamic();
|
||||
|
||||
virtual void removeFromSimulation(EntitySimulationPointer simulation) const override;
|
||||
virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; }
|
||||
|
@ -50,4 +50,4 @@ protected:
|
|||
EntityItemWeakPointer _ownerEntity;
|
||||
};
|
||||
|
||||
#endif // hifi_AssignmentAction_h
|
||||
#endif // hifi_AssignmentDynamic_h
|
48
assignment-client/src/AssignmentDynamicFactory.cpp
Normal file
48
assignment-client/src/AssignmentDynamicFactory.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// AssignmentDynamcFactory.cpp
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-19
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "AssignmentDynamicFactory.h"
|
||||
|
||||
|
||||
EntityDynamicPointer assignmentDynamicFactory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) {
|
||||
return EntityDynamicPointer(new AssignmentDynamic(type, id, ownerEntity));
|
||||
}
|
||||
|
||||
EntityDynamicPointer AssignmentDynamicFactory::factory(EntityDynamicType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) {
|
||||
EntityDynamicPointer dynamic = assignmentDynamicFactory(type, id, ownerEntity);
|
||||
if (dynamic) {
|
||||
bool ok = dynamic->updateArguments(arguments);
|
||||
if (ok) {
|
||||
return dynamic;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityDynamicPointer AssignmentDynamicFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) {
|
||||
QDataStream serializedDynamicDataStream(data);
|
||||
EntityDynamicType type;
|
||||
QUuid id;
|
||||
|
||||
serializedDynamicDataStream >> type;
|
||||
serializedDynamicDataStream >> id;
|
||||
|
||||
EntityDynamicPointer dynamic = assignmentDynamicFactory(type, id, ownerEntity);
|
||||
|
||||
if (dynamic) {
|
||||
dynamic->deserialize(data);
|
||||
}
|
||||
return dynamic;
|
||||
}
|
29
assignment-client/src/AssignmentDynamicFactory.h
Normal file
29
assignment-client/src/AssignmentDynamicFactory.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// AssignmentDynamicFactory.cpp
|
||||
// assignment-client/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-19
|
||||
// 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
|
||||
//
|
||||
|
||||
#ifndef hifi_AssignmentDynamicFactory_h
|
||||
#define hifi_AssignmentDynamicFactory_h
|
||||
|
||||
#include "EntityDynamicFactoryInterface.h"
|
||||
#include "AssignmentDynamic.h"
|
||||
|
||||
class AssignmentDynamicFactory : public EntityDynamicFactoryInterface {
|
||||
public:
|
||||
AssignmentDynamicFactory() : EntityDynamicFactoryInterface() { }
|
||||
virtual ~AssignmentDynamicFactory() { }
|
||||
virtual EntityDynamicPointer factory(EntityDynamicType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) override;
|
||||
virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override;
|
||||
};
|
||||
|
||||
#endif // hifi_AssignmentDynamicFactory_h
|
|
@ -137,7 +137,7 @@
|
|||
#include "devices/Leapmotion.h"
|
||||
#include "DiscoverabilityManager.h"
|
||||
#include "GLCanvas.h"
|
||||
#include "InterfaceActionFactory.h"
|
||||
#include "InterfaceDynamicFactory.h"
|
||||
#include "InterfaceLogging.h"
|
||||
#include "LODManager.h"
|
||||
#include "ModelPackager.h"
|
||||
|
@ -459,7 +459,7 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
|
||||
DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>();
|
||||
DependencyManager::registerInheritance<EntityDynamicFactoryInterface, InterfaceDynamicFactory>();
|
||||
DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>();
|
||||
|
||||
// Set dependencies
|
||||
|
@ -512,7 +512,7 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
DependencyManager::set<OffscreenUi>();
|
||||
DependencyManager::set<AutoUpdater>();
|
||||
DependencyManager::set<PathUtils>();
|
||||
DependencyManager::set<InterfaceActionFactory>();
|
||||
DependencyManager::set<InterfaceDynamicFactory>();
|
||||
DependencyManager::set<AudioInjectorManager>();
|
||||
DependencyManager::set<MessagesClient>();
|
||||
controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR,
|
||||
|
@ -4423,7 +4423,7 @@ void Application::update(float deltaTime) {
|
|||
_entitySimulation->setObjectsToChange(stillNeedChange);
|
||||
});
|
||||
|
||||
_entitySimulation->applyActionChanges();
|
||||
_entitySimulation->applyDynamicChanges();
|
||||
|
||||
avatarManager->getObjectsToRemoveFromPhysics(motionStates);
|
||||
_physicsEngine->removeObjects(motionStates);
|
||||
|
@ -4433,8 +4433,8 @@ void Application::update(float deltaTime) {
|
|||
_physicsEngine->changeObjects(motionStates);
|
||||
|
||||
myAvatar->prepareForPhysicsSimulation();
|
||||
_physicsEngine->forEachAction([&](EntityActionPointer action) {
|
||||
action->prepareForPhysicsSimulation();
|
||||
_physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) {
|
||||
dynamic->prepareForPhysicsSimulation();
|
||||
});
|
||||
}
|
||||
{
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
//
|
||||
// InterfaceActionFactory.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-2
|
||||
// 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
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include <avatar/AvatarActionHold.h>
|
||||
#include <ObjectActionOffset.h>
|
||||
#include <ObjectActionSpring.h>
|
||||
#include <ObjectActionTravelOriented.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "InterfaceActionFactory.h"
|
||||
|
||||
|
||||
EntityActionPointer interfaceActionFactory(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) {
|
||||
switch (type) {
|
||||
case ACTION_TYPE_NONE:
|
||||
return EntityActionPointer();
|
||||
case ACTION_TYPE_OFFSET:
|
||||
return std::make_shared<ObjectActionOffset>(id, ownerEntity);
|
||||
case ACTION_TYPE_SPRING:
|
||||
return std::make_shared<ObjectActionSpring>(id, ownerEntity);
|
||||
case ACTION_TYPE_HOLD:
|
||||
return std::make_shared<AvatarActionHold>(id, ownerEntity);
|
||||
case ACTION_TYPE_TRAVEL_ORIENTED:
|
||||
return std::make_shared<ObjectActionTravelOriented>(id, ownerEntity);
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown entity action type");
|
||||
return EntityActionPointer();
|
||||
}
|
||||
|
||||
|
||||
EntityActionPointer InterfaceActionFactory::factory(EntityActionType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) {
|
||||
EntityActionPointer action = interfaceActionFactory(type, id, ownerEntity);
|
||||
if (action) {
|
||||
bool ok = action->updateArguments(arguments);
|
||||
if (ok) {
|
||||
if (action->lifetimeIsOver()) {
|
||||
return nullptr;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityActionPointer InterfaceActionFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) {
|
||||
QDataStream serializedArgumentStream(data);
|
||||
EntityActionType type;
|
||||
QUuid id;
|
||||
|
||||
serializedArgumentStream >> type;
|
||||
serializedArgumentStream >> id;
|
||||
|
||||
EntityActionPointer action = interfaceActionFactory(type, id, ownerEntity);
|
||||
|
||||
if (action) {
|
||||
action->deserialize(data);
|
||||
if (action->lifetimeIsOver()) {
|
||||
static QString repeatedMessage =
|
||||
LogHandler::getInstance().addRepeatedMessageRegex(".*factoryBA lifetimeIsOver during action creation.*");
|
||||
qDebug() << "InterfaceActionFactory::factoryBA lifetimeIsOver during action creation --"
|
||||
<< action->getExpires() << "<" << usecTimestampNow();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
85
interface/src/InterfaceDynamicFactory.cpp
Normal file
85
interface/src/InterfaceDynamicFactory.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// InterfaceDynamicFactory.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-2
|
||||
// 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
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include <avatar/AvatarActionHold.h>
|
||||
#include <ObjectActionOffset.h>
|
||||
#include <ObjectActionSpring.h>
|
||||
#include <ObjectActionTravelOriented.h>
|
||||
#include <ObjectConstraintHinge.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "InterfaceDynamicFactory.h"
|
||||
|
||||
|
||||
EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) {
|
||||
switch (type) {
|
||||
case DYNAMIC_TYPE_NONE:
|
||||
return EntityDynamicPointer();
|
||||
case DYNAMIC_TYPE_OFFSET:
|
||||
return std::make_shared<ObjectActionOffset>(id, ownerEntity);
|
||||
case DYNAMIC_TYPE_SPRING:
|
||||
return std::make_shared<ObjectActionSpring>(id, ownerEntity);
|
||||
case DYNAMIC_TYPE_HOLD:
|
||||
return std::make_shared<AvatarActionHold>(id, ownerEntity);
|
||||
case DYNAMIC_TYPE_TRAVEL_ORIENTED:
|
||||
return std::make_shared<ObjectActionTravelOriented>(id, ownerEntity);
|
||||
case DYNAMIC_TYPE_HINGE:
|
||||
return std::make_shared<ObjectConstraintHinge>(id, ownerEntity);
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown entity dynamic type");
|
||||
return EntityDynamicPointer();
|
||||
}
|
||||
|
||||
|
||||
EntityDynamicPointer InterfaceDynamicFactory::factory(EntityDynamicType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) {
|
||||
EntityDynamicPointer dynamic = interfaceDynamicFactory(type, id, ownerEntity);
|
||||
if (dynamic) {
|
||||
bool ok = dynamic->updateArguments(arguments);
|
||||
if (ok) {
|
||||
if (dynamic->lifetimeIsOver()) {
|
||||
return nullptr;
|
||||
}
|
||||
return dynamic;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityDynamicPointer InterfaceDynamicFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) {
|
||||
QDataStream serializedArgumentStream(data);
|
||||
EntityDynamicType type;
|
||||
QUuid id;
|
||||
|
||||
serializedArgumentStream >> type;
|
||||
serializedArgumentStream >> id;
|
||||
|
||||
EntityDynamicPointer dynamic = interfaceDynamicFactory(type, id, ownerEntity);
|
||||
|
||||
if (dynamic) {
|
||||
dynamic->deserialize(data);
|
||||
if (dynamic->lifetimeIsOver()) {
|
||||
static QString repeatedMessage =
|
||||
LogHandler::getInstance().addRepeatedMessageRegex(".*factoryBA lifetimeIsOver during dynamic creation.*");
|
||||
qDebug() << "InterfaceDynamicFactory::factoryBA lifetimeIsOver during dynamic creation --"
|
||||
<< dynamic->getExpires() << "<" << usecTimestampNow();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return dynamic;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// InterfaceActionFactory.cpp
|
||||
// InterfaceDynamicFactory.cpp
|
||||
// interface/src/
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-10
|
||||
|
@ -9,21 +9,21 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_InterfaceActionFactory_h
|
||||
#define hifi_InterfaceActionFactory_h
|
||||
#ifndef hifi_InterfaceDynamicFactory_h
|
||||
#define hifi_InterfaceDynamicFactory_h
|
||||
|
||||
#include "EntityActionFactoryInterface.h"
|
||||
#include "EntityDynamicFactoryInterface.h"
|
||||
|
||||
class InterfaceActionFactory : public EntityActionFactoryInterface {
|
||||
class InterfaceDynamicFactory : public EntityDynamicFactoryInterface {
|
||||
public:
|
||||
InterfaceActionFactory() : EntityActionFactoryInterface() { }
|
||||
virtual ~InterfaceActionFactory() { }
|
||||
virtual EntityActionPointer factory(EntityActionType type,
|
||||
InterfaceDynamicFactory() : EntityDynamicFactoryInterface() { }
|
||||
virtual ~InterfaceDynamicFactory() { }
|
||||
virtual EntityDynamicPointer factory(EntityDynamicType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) override;
|
||||
virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity,
|
||||
virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity,
|
||||
QByteArray data) override;
|
||||
};
|
||||
|
||||
#endif // hifi_InterfaceActionFactory_h
|
||||
#endif // hifi_InterfaceDynamicFactory_h
|
|
@ -23,7 +23,7 @@ const int AvatarActionHold::velocitySmoothFrames = 6;
|
|||
AvatarActionHold::AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectActionSpring(id, ownerEntity)
|
||||
{
|
||||
_type = ACTION_TYPE_HOLD;
|
||||
_type = DYNAMIC_TYPE_HOLD;
|
||||
_measuredLinearVelocities.resize(AvatarActionHold::velocitySmoothFrames);
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
@ -326,25 +326,25 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
bool somethingChanged = ObjectAction::updateArguments(arguments);
|
||||
withReadLock([&]{
|
||||
bool ok = true;
|
||||
relativePosition = EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false);
|
||||
relativePosition = EntityDynamicInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false);
|
||||
if (!ok) {
|
||||
relativePosition = _relativePosition;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
relativeRotation = EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false);
|
||||
relativeRotation = EntityDynamicInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false);
|
||||
if (!ok) {
|
||||
relativeRotation = _relativeRotation;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
timeScale = EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false);
|
||||
timeScale = EntityDynamicInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false);
|
||||
if (!ok) {
|
||||
timeScale = _linearTimeScale;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
hand = EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false);
|
||||
hand = EntityDynamicInterface::extractStringArgument("hold", arguments, "hand", ok, false);
|
||||
if (!ok || !(hand == "left" || hand == "right")) {
|
||||
hand = _hand;
|
||||
}
|
||||
|
@ -353,20 +353,20 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
holderID = myAvatar->getSessionUUID();
|
||||
|
||||
ok = true;
|
||||
kinematic = EntityActionInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false);
|
||||
kinematic = EntityDynamicInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false);
|
||||
if (!ok) {
|
||||
kinematic = _kinematic;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
kinematicSetVelocity = EntityActionInterface::extractBooleanArgument("hold", arguments,
|
||||
kinematicSetVelocity = EntityDynamicInterface::extractBooleanArgument("hold", arguments,
|
||||
"kinematicSetVelocity", ok, false);
|
||||
if (!ok) {
|
||||
kinematicSetVelocity = _kinematicSetVelocity;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
ignoreIK = EntityActionInterface::extractBooleanArgument("hold", arguments, "ignoreIK", ok, false);
|
||||
ignoreIK = EntityDynamicInterface::extractBooleanArgument("hold", arguments, "ignoreIK", ok, false);
|
||||
if (!ok) {
|
||||
ignoreIK = _ignoreIK;
|
||||
}
|
||||
|
@ -400,8 +400,8 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
ownerEntity->setDynamicDataDirty(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ QByteArray AvatarActionHold::serialize() const {
|
|||
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
|
||||
|
||||
withReadLock([&]{
|
||||
dataStream << ACTION_TYPE_HOLD;
|
||||
dataStream << DYNAMIC_TYPE_HOLD;
|
||||
dataStream << getID();
|
||||
dataStream << AvatarActionHold::holdVersion;
|
||||
|
||||
|
@ -451,7 +451,7 @@ QByteArray AvatarActionHold::serialize() const {
|
|||
void AvatarActionHold::deserialize(QByteArray serializedArguments) {
|
||||
QDataStream dataStream(serializedArguments);
|
||||
|
||||
EntityActionType type;
|
||||
EntityDynamicType type;
|
||||
dataStream >> type;
|
||||
assert(type == getType());
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// EntityActionFactoryInterface.cpp
|
||||
// EntityDynamicFactoryInterface.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-2
|
||||
|
@ -9,26 +9,26 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_EntityActionFactoryInterface_h
|
||||
#define hifi_EntityActionFactoryInterface_h
|
||||
#ifndef hifi_EntityDynamicFactoryInterface_h
|
||||
#define hifi_EntityDynamicFactoryInterface_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "EntityActionInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
class EntityActionFactoryInterface : public QObject, public Dependency {
|
||||
class EntityDynamicFactoryInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
EntityActionFactoryInterface() { }
|
||||
virtual ~EntityActionFactoryInterface() { }
|
||||
virtual EntityActionPointer factory(EntityActionType type,
|
||||
EntityDynamicFactoryInterface() { }
|
||||
virtual ~EntityDynamicFactoryInterface() { }
|
||||
virtual EntityDynamicPointer factory(EntityDynamicType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) { assert(false); return nullptr; }
|
||||
virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity,
|
||||
virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity,
|
||||
QByteArray data) { assert(false); return nullptr; }
|
||||
};
|
||||
|
||||
#endif // hifi_EntityActionFactoryInterface_h
|
||||
#endif // hifi_EntityDynamicFactoryInterface_h
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// EntityActionInterface.cpp
|
||||
// EntityDynamicInterface.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-4
|
||||
|
@ -16,66 +16,66 @@
|
|||
|
||||
|
||||
|
||||
+-----------------------+ +-------------------+ +------------------------------+
|
||||
| | | | | |
|
||||
| EntityActionInterface | | btActionInterface | | EntityActionFactoryInterface |
|
||||
| (entities) | | (bullet) | | (entities) |
|
||||
+-----------------------+ +-------------------+ +------------------------------+
|
||||
| | | | |
|
||||
+----+ +--+ +----------+ | |
|
||||
| | | | |
|
||||
+-------------------+ +--------------+ +------------------------+ +-------------------------+
|
||||
| | | | | | | |
|
||||
| AssignmentAction | | ObjectAction | | InterfaceActionFactory | | AssignmentActionFactory |
|
||||
|(assignment client)| | (physics) | | (interface) | | (assignment client) |
|
||||
+-------------------+ +--------------+ +------------------------+ +-------------------------+
|
||||
+-----------------------+ +-------------------+ +---------------------------------+
|
||||
| | | | | |
|
||||
| EntityDynamicInterface | | btDynamicInterface | | EntityDynamicFactoryInterface |
|
||||
| (entities) | | (bullet) | | (entities) |
|
||||
+-----------------------+ +-------------------+ +---------------------------------+
|
||||
| | | | |
|
||||
+----+ +--+ +----------+ | |
|
||||
| | | | |
|
||||
+-------------------+ +--------------+ +---------------------------+ +--------------------------+
|
||||
| | | | | | | |
|
||||
| AssignmentDynamic | | ObjectDynamic | | InterfaceDynamicFactory | | AssignmentDynamicFactory |
|
||||
|(assignment client)| | (physics) | | (interface) | | (assignment client) |
|
||||
+-------------------+ +--------------+ +---------------------------+ +--------------------------+
|
||||
|
|
||||
|
|
||||
|
|
||||
+--------------------+
|
||||
| |
|
||||
| ObjectActionSpring |
|
||||
| ObjectDynamicSpring |
|
||||
| (physics) |
|
||||
+--------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
An action is a callback which is registered with bullet. An action is called-back every physics
|
||||
An dynamic is a callback which is registered with bullet. An dynamic is called-back every physics
|
||||
simulation step and can do whatever it wants with the various datastructures it has available. An
|
||||
action, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that
|
||||
dynamic, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that
|
||||
point by a spring.
|
||||
|
||||
In this system, an action is a property of an EntityItem (rather, an EntityItem has a property which
|
||||
encodes a list of actions). Each action has a type and some arguments. Actions can be created by a
|
||||
In this system, an dynamic is a property of an EntityItem (rather, an EntityItem has a property which
|
||||
encodes a list of dynamics). Each dynamic has a type and some arguments. Dynamics can be created by a
|
||||
script or when receiving information via an EntityTree data-stream (either over the network or from an
|
||||
svo file).
|
||||
|
||||
In the interface, if an EntityItem has actions, this EntityItem will have pointers to ObjectAction
|
||||
subclass (like ObjectActionSpring) instantiations. Code in the entities library affects an action-object
|
||||
via the EntityActionInterface (which knows nothing about bullet). When the ObjectAction subclass
|
||||
instance is created, it is registered as an action with bullet. Bullet will call into code in this
|
||||
instance with the btActionInterface every physics-simulation step.
|
||||
In the interface, if an EntityItem has dynamics, this EntityItem will have pointers to ObjectDynamic
|
||||
subclass (like ObjectDynamicSpring) instantiations. Code in the entities library affects an dynamic-object
|
||||
via the EntityDynamicInterface (which knows nothing about bullet). When the ObjectDynamic subclass
|
||||
instance is created, it is registered as an dynamic with bullet. Bullet will call into code in this
|
||||
instance with the btDynamicInterface every physics-simulation step.
|
||||
|
||||
Because the action can exist next to the interface's EntityTree or the entity-server's EntityTree,
|
||||
parallel versions of the factories and actions are needed.
|
||||
Because the dynamic can exist next to the interface's EntityTree or the entity-server's EntityTree,
|
||||
parallel versions of the factories and dynamics are needed.
|
||||
|
||||
In an entity-server, any type of action is instantiated as an AssignmentAction. This action isn't called
|
||||
In an entity-server, any type of dynamic is instantiated as an AssignmentDynamic. This dynamic isn't called
|
||||
by bullet (which isn't part of an assignment-client). It does nothing but remember its type and its
|
||||
arguments. This may change as we try to make the entity-server's simple physics simulation better, but
|
||||
right now the AssignmentAction class is a place-holder.
|
||||
right now the AssignmentDynamic class is a place-holder.
|
||||
|
||||
The action-objects are instantiated by singleton (dependecy) subclasses of EntityActionFactoryInterface.
|
||||
In the interface, the subclass is an InterfaceActionFactory and it will produce things like
|
||||
ObjectActionSpring. In an entity-server the subclass is an AssignmentActionFactory and it always
|
||||
produces AssignmentActions.
|
||||
The dynamic-objects are instantiated by singleton (dependecy) subclasses of EntityDynamicFactoryInterface.
|
||||
In the interface, the subclass is an InterfaceDynamicFactory and it will produce things like
|
||||
ObjectDynamicSpring. In an entity-server the subclass is an AssignmentDynamicFactory and it always
|
||||
produces AssignmentDynamics.
|
||||
|
||||
Depending on the action's type, it will have various arguments. When a script changes an argument of an
|
||||
action, the argument-holding member-variables of ObjectActionSpring (in this example) are updated and
|
||||
also serialized into _actionData in the EntityItem. Each subclass of ObjectAction knows how to serialize
|
||||
and deserialize its own arguments. _actionData is what gets sent over the wire or saved in an svo file.
|
||||
When a packet-reader receives data for _actionData, it will save it in the EntityItem; this causes the
|
||||
deserializer in the ObjectAction subclass to be called with the new data, thereby updating its argument
|
||||
Depending on the dynamic's type, it will have various arguments. When a script changes an argument of an
|
||||
dynamic, the argument-holding member-variables of ObjectDynamicSpring (in this example) are updated and
|
||||
also serialized into _dynamicData in the EntityItem. Each subclass of ObjectDynamic knows how to serialize
|
||||
and deserialize its own arguments. _dynamicData is what gets sent over the wire or saved in an svo file.
|
||||
When a packet-reader receives data for _dynamicData, it will save it in the EntityItem; this causes the
|
||||
deserializer in the ObjectDynamic subclass to be called with the new data, thereby updating its argument
|
||||
variables. These argument variables are used by the code which is run when bullet does a callback.
|
||||
|
||||
|
||||
|
@ -83,49 +83,54 @@ variables. These argument variables are used by the code which is run when bull
|
|||
|
||||
#include "EntityItem.h"
|
||||
|
||||
#include "EntityActionInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
|
||||
EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeString) {
|
||||
QString normalizedActionTypeString = actionTypeString.toLower().remove('-').remove('_');
|
||||
if (normalizedActionTypeString == "none") {
|
||||
return ACTION_TYPE_NONE;
|
||||
EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicTypeString) {
|
||||
QString normalizedDynamicTypeString = dynamicTypeString.toLower().remove('-').remove('_');
|
||||
if (normalizedDynamicTypeString == "none") {
|
||||
return DYNAMIC_TYPE_NONE;
|
||||
}
|
||||
if (normalizedActionTypeString == "offset") {
|
||||
return ACTION_TYPE_OFFSET;
|
||||
if (normalizedDynamicTypeString == "offset") {
|
||||
return DYNAMIC_TYPE_OFFSET;
|
||||
}
|
||||
if (normalizedActionTypeString == "spring") {
|
||||
return ACTION_TYPE_SPRING;
|
||||
if (normalizedDynamicTypeString == "spring") {
|
||||
return DYNAMIC_TYPE_SPRING;
|
||||
}
|
||||
if (normalizedActionTypeString == "hold") {
|
||||
return ACTION_TYPE_HOLD;
|
||||
if (normalizedDynamicTypeString == "hold") {
|
||||
return DYNAMIC_TYPE_HOLD;
|
||||
}
|
||||
if (normalizedActionTypeString == "traveloriented") {
|
||||
return ACTION_TYPE_TRAVEL_ORIENTED;
|
||||
if (normalizedDynamicTypeString == "traveloriented") {
|
||||
return DYNAMIC_TYPE_TRAVEL_ORIENTED;
|
||||
}
|
||||
if (normalizedDynamicTypeString == "hinge") {
|
||||
return DYNAMIC_TYPE_HINGE;
|
||||
}
|
||||
|
||||
qCDebug(entities) << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString;
|
||||
return ACTION_TYPE_NONE;
|
||||
qCDebug(entities) << "Warning -- EntityDynamicInterface::dynamicTypeFromString got unknown dynamic-type name" << dynamicTypeString;
|
||||
return DYNAMIC_TYPE_NONE;
|
||||
}
|
||||
|
||||
QString EntityActionInterface::actionTypeToString(EntityActionType actionType) {
|
||||
switch(actionType) {
|
||||
case ACTION_TYPE_NONE:
|
||||
QString EntityDynamicInterface::dynamicTypeToString(EntityDynamicType dynamicType) {
|
||||
switch(dynamicType) {
|
||||
case DYNAMIC_TYPE_NONE:
|
||||
return "none";
|
||||
case ACTION_TYPE_OFFSET:
|
||||
case DYNAMIC_TYPE_OFFSET:
|
||||
return "offset";
|
||||
case ACTION_TYPE_SPRING:
|
||||
case DYNAMIC_TYPE_SPRING:
|
||||
return "spring";
|
||||
case ACTION_TYPE_HOLD:
|
||||
case DYNAMIC_TYPE_HOLD:
|
||||
return "hold";
|
||||
case ACTION_TYPE_TRAVEL_ORIENTED:
|
||||
case DYNAMIC_TYPE_TRAVEL_ORIENTED:
|
||||
return "travel-oriented";
|
||||
case DYNAMIC_TYPE_HINGE:
|
||||
return "hinge";
|
||||
}
|
||||
assert(false);
|
||||
return "none";
|
||||
}
|
||||
|
||||
glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVariantMap arguments,
|
||||
glm::vec3 EntityDynamicInterface::extractVec3Argument(QString objectName, QVariantMap arguments,
|
||||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
|
@ -174,7 +179,7 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian
|
|||
return glm::vec3(x, y, z);
|
||||
}
|
||||
|
||||
glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVariantMap arguments,
|
||||
glm::quat EntityDynamicInterface::extractQuatArgument(QString objectName, QVariantMap arguments,
|
||||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
|
@ -227,7 +232,7 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian
|
|||
return glm::normalize(glm::quat(w, x, y, z));
|
||||
}
|
||||
|
||||
float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMap arguments,
|
||||
float EntityDynamicInterface::extractFloatArgument(QString objectName, QVariantMap arguments,
|
||||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
|
@ -249,7 +254,7 @@ float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMa
|
|||
return value;
|
||||
}
|
||||
|
||||
int EntityActionInterface::extractIntegerArgument(QString objectName, QVariantMap arguments,
|
||||
int EntityDynamicInterface::extractIntegerArgument(QString objectName, QVariantMap arguments,
|
||||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
|
@ -271,7 +276,7 @@ int EntityActionInterface::extractIntegerArgument(QString objectName, QVariantMa
|
|||
return value;
|
||||
}
|
||||
|
||||
QString EntityActionInterface::extractStringArgument(QString objectName, QVariantMap arguments,
|
||||
QString EntityDynamicInterface::extractStringArgument(QString objectName, QVariantMap arguments,
|
||||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
|
@ -283,7 +288,7 @@ QString EntityActionInterface::extractStringArgument(QString objectName, QVarian
|
|||
return arguments[argumentName].toString();
|
||||
}
|
||||
|
||||
bool EntityActionInterface::extractBooleanArgument(QString objectName, QVariantMap arguments,
|
||||
bool EntityDynamicInterface::extractBooleanArgument(QString objectName, QVariantMap arguments,
|
||||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
|
@ -297,35 +302,35 @@ bool EntityActionInterface::extractBooleanArgument(QString objectName, QVariantM
|
|||
|
||||
|
||||
|
||||
QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType)
|
||||
QDataStream& operator<<(QDataStream& stream, const EntityDynamicType& entityDynamicType)
|
||||
{
|
||||
return stream << (quint16)entityActionType;
|
||||
return stream << (quint16)entityDynamicType;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType)
|
||||
QDataStream& operator>>(QDataStream& stream, EntityDynamicType& entityDynamicType)
|
||||
{
|
||||
quint16 actionTypeAsInt;
|
||||
stream >> actionTypeAsInt;
|
||||
entityActionType = (EntityActionType)actionTypeAsInt;
|
||||
quint16 dynamicTypeAsInt;
|
||||
stream >> dynamicTypeAsInt;
|
||||
entityDynamicType = (EntityDynamicType)dynamicTypeAsInt;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QString serializedActionsToDebugString(QByteArray data) {
|
||||
QString serializedDynamicsToDebugString(QByteArray data) {
|
||||
if (data.size() == 0) {
|
||||
return QString();
|
||||
}
|
||||
QVector<QByteArray> serializedActions;
|
||||
QDataStream serializedActionsStream(data);
|
||||
serializedActionsStream >> serializedActions;
|
||||
QVector<QByteArray> serializedDynamics;
|
||||
QDataStream serializedDynamicsStream(data);
|
||||
serializedDynamicsStream >> serializedDynamics;
|
||||
|
||||
QString result;
|
||||
foreach(QByteArray serializedAction, serializedActions) {
|
||||
QDataStream serializedActionStream(serializedAction);
|
||||
EntityActionType actionType;
|
||||
QUuid actionID;
|
||||
serializedActionStream >> actionType;
|
||||
serializedActionStream >> actionID;
|
||||
result += EntityActionInterface::actionTypeToString(actionType) + "-" + actionID.toString() + " ";
|
||||
foreach(QByteArray serializedDynamic, serializedDynamics) {
|
||||
QDataStream serializedDynamicStream(serializedDynamic);
|
||||
EntityDynamicType dynamicType;
|
||||
QUuid dynamicID;
|
||||
serializedDynamicStream >> dynamicType;
|
||||
serializedDynamicStream >> dynamicID;
|
||||
result += EntityDynamicInterface::dynamicTypeToString(dynamicType) + "-" + dynamicID.toString() + " ";
|
||||
}
|
||||
|
||||
return result;
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// EntityActionInterface.h
|
||||
// EntityDynamicInterface.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 2015-6-2
|
||||
|
@ -9,8 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_EntityActionInterface_h
|
||||
#define hifi_EntityActionInterface_h
|
||||
#ifndef hifi_EntityDynamicInterface_h
|
||||
#define hifi_EntityDynamicInterface_h
|
||||
|
||||
#include <memory>
|
||||
#include <QUuid>
|
||||
|
@ -23,22 +23,25 @@ using EntityItemWeakPointer = std::weak_ptr<EntityItem>;
|
|||
class EntitySimulation;
|
||||
using EntitySimulationPointer = std::shared_ptr<EntitySimulation>;
|
||||
|
||||
enum EntityActionType {
|
||||
// keep these synchronized with actionTypeFromString and actionTypeToString
|
||||
ACTION_TYPE_NONE = 0,
|
||||
ACTION_TYPE_OFFSET = 1000,
|
||||
ACTION_TYPE_SPRING = 2000,
|
||||
ACTION_TYPE_HOLD = 3000,
|
||||
ACTION_TYPE_TRAVEL_ORIENTED = 4000
|
||||
enum EntityDynamicType {
|
||||
// keep these synchronized with dynamicTypeFromString and dynamicTypeToString
|
||||
DYNAMIC_TYPE_NONE = 0,
|
||||
DYNAMIC_TYPE_OFFSET = 1000,
|
||||
DYNAMIC_TYPE_SPRING = 2000,
|
||||
DYNAMIC_TYPE_HOLD = 3000,
|
||||
DYNAMIC_TYPE_TRAVEL_ORIENTED = 4000,
|
||||
DYNAMIC_TYPE_HINGE = 5000
|
||||
};
|
||||
|
||||
|
||||
class EntityActionInterface {
|
||||
class EntityDynamicInterface {
|
||||
public:
|
||||
EntityActionInterface(EntityActionType type, const QUuid& id) : _id(id), _type(type) { }
|
||||
virtual ~EntityActionInterface() { }
|
||||
EntityDynamicInterface(EntityDynamicType type, const QUuid& id) : _id(id), _type(type) { }
|
||||
virtual ~EntityDynamicInterface() { }
|
||||
const QUuid& getID() const { return _id; }
|
||||
EntityActionType getType() const { return _type; }
|
||||
EntityDynamicType getType() const { return _type; }
|
||||
virtual bool isAction() const { return false; }
|
||||
virtual bool isConstraint() const { return false; }
|
||||
|
||||
bool isActive() { return _active; }
|
||||
|
||||
|
@ -51,8 +54,8 @@ public:
|
|||
virtual QByteArray serialize() const = 0;
|
||||
virtual void deserialize(QByteArray serializedArguments) = 0;
|
||||
|
||||
static EntityActionType actionTypeFromString(QString actionTypeString);
|
||||
static QString actionTypeToString(EntityActionType actionType);
|
||||
static EntityDynamicType dynamicTypeFromString(QString dynamicTypeString);
|
||||
static QString dynamicTypeToString(EntityDynamicType dynamicType);
|
||||
|
||||
virtual bool lifetimeIsOver() { return false; }
|
||||
virtual quint64 getExpires() { return 0; }
|
||||
|
@ -91,17 +94,17 @@ protected:
|
|||
virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0;
|
||||
|
||||
QUuid _id;
|
||||
EntityActionType _type;
|
||||
EntityDynamicType _type;
|
||||
bool _active { false };
|
||||
bool _isMine { false }; // did this interface create / edit this action?
|
||||
bool _isMine { false }; // did this interface create / edit this dynamic?
|
||||
};
|
||||
|
||||
|
||||
typedef std::shared_ptr<EntityActionInterface> EntityActionPointer;
|
||||
typedef std::shared_ptr<EntityDynamicInterface> EntityDynamicPointer;
|
||||
|
||||
QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType);
|
||||
QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType);
|
||||
QDataStream& operator<<(QDataStream& stream, const EntityDynamicType& entityDynamicType);
|
||||
QDataStream& operator>>(QDataStream& stream, EntityDynamicType& entityDynamicType);
|
||||
|
||||
QString serializedActionsToDebugString(QByteArray data);
|
||||
QString serializedDynamicsToDebugString(QByteArray data);
|
||||
|
||||
#endif // hifi_EntityActionInterface_h
|
||||
#endif // hifi_EntityDynamicInterface_h
|
|
@ -30,7 +30,7 @@
|
|||
#include "EntitiesLogging.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntitySimulation.h"
|
||||
#include "EntityActionFactoryInterface.h"
|
||||
#include "EntityDynamicFactoryInterface.h"
|
||||
|
||||
|
||||
int EntityItem::_maxActionsDataSize = 800;
|
||||
|
@ -280,7 +280,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, getCollisionSoundURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_HREF, getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, getDescription());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getActionData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getDynamicData());
|
||||
|
||||
// convert AVATAR_SELF_ID to actual sessionUUID.
|
||||
QUuid actualParentID = getParentID();
|
||||
|
@ -821,7 +821,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData);
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setDynamicData);
|
||||
|
||||
{ // parentID and parentJointIndex are also protected by simulation ownership
|
||||
bool oldOverwrite = overwriteLocalData;
|
||||
|
@ -1251,7 +1251,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(name, getName);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(href, getHref);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(description, getDescription);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getActionData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getDynamicData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube);
|
||||
|
@ -1358,7 +1358,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(href, setHref);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(description, setDescription);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setActionData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setDynamicData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, updateParentID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
|
||||
|
@ -1872,10 +1872,10 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask
|
|||
iAmHoldingThis = true;
|
||||
}
|
||||
// also, don't bootstrap our own avatar with a hold action
|
||||
QList<EntityActionPointer> holdActions = getActionsOfType(ACTION_TYPE_HOLD);
|
||||
QList<EntityActionPointer>::const_iterator i = holdActions.begin();
|
||||
QList<EntityDynamicPointer> holdActions = getActionsOfType(DYNAMIC_TYPE_HOLD);
|
||||
QList<EntityDynamicPointer>::const_iterator i = holdActions.begin();
|
||||
while (i != holdActions.end()) {
|
||||
EntityActionPointer action = *i;
|
||||
EntityDynamicPointer action = *i;
|
||||
if (action->isMine()) {
|
||||
iAmHoldingThis = true;
|
||||
break;
|
||||
|
@ -1941,18 +1941,18 @@ void EntityItem::rememberHasSimulationOwnershipBid() const {
|
|||
QString EntityItem::actionsToDebugString() {
|
||||
QString result;
|
||||
QVector<QByteArray> serializedActions;
|
||||
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
const QUuid id = i.key();
|
||||
EntityActionPointer action = _objectActions[id];
|
||||
EntityActionType actionType = action->getType();
|
||||
EntityDynamicPointer action = _objectActions[id];
|
||||
EntityDynamicType actionType = action->getType();
|
||||
result += QString("") + actionType + ":" + action->getID().toString() + " ";
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool EntityItem::addAction(EntitySimulationPointer simulation, EntityActionPointer action) {
|
||||
bool EntityItem::addAction(EntitySimulationPointer simulation, EntityDynamicPointer action) {
|
||||
bool result;
|
||||
withWriteLock([&] {
|
||||
checkWaitingToRemove(simulation);
|
||||
|
@ -1960,7 +1960,7 @@ bool EntityItem::addAction(EntitySimulationPointer simulation, EntityActionPoint
|
|||
result = addActionInternal(simulation, action);
|
||||
if (result) {
|
||||
action->setIsMine(true);
|
||||
_actionDataDirty = true;
|
||||
_dynamicDataDirty = true;
|
||||
} else {
|
||||
removeActionInternal(action->getID());
|
||||
}
|
||||
|
@ -1969,7 +1969,7 @@ bool EntityItem::addAction(EntitySimulationPointer simulation, EntityActionPoint
|
|||
return result;
|
||||
}
|
||||
|
||||
bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityActionPointer action) {
|
||||
bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action) {
|
||||
assert(action);
|
||||
assert(simulation);
|
||||
auto actionOwnerEntity = action->getOwnerEntity().lock();
|
||||
|
@ -1979,7 +1979,7 @@ bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityAct
|
|||
const QUuid& actionID = action->getID();
|
||||
assert(!_objectActions.contains(actionID) || _objectActions[actionID] == action);
|
||||
_objectActions[actionID] = action;
|
||||
simulation->addAction(action);
|
||||
simulation->addDynamic(action);
|
||||
|
||||
bool success;
|
||||
QByteArray newDataCache;
|
||||
|
@ -2003,7 +2003,7 @@ bool EntityItem::updateAction(EntitySimulationPointer simulation, const QUuid& a
|
|||
return;
|
||||
}
|
||||
|
||||
EntityActionPointer action = _objectActions[actionID];
|
||||
EntityDynamicPointer action = _objectActions[actionID];
|
||||
|
||||
success = action->updateArguments(arguments);
|
||||
if (success) {
|
||||
|
@ -2035,7 +2035,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
|||
simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||
}
|
||||
|
||||
EntityActionPointer action = _objectActions[actionID];
|
||||
EntityDynamicPointer action = _objectActions[actionID];
|
||||
|
||||
action->setOwnerEntity(nullptr);
|
||||
action->setIsMine(false);
|
||||
|
@ -2049,7 +2049,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
|||
serializeActions(success, _allActionsDataCache);
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
_dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
||||
setActionDataNeedsTransmit(true);
|
||||
setDynamicDataNeedsTransmit(true);
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
|
@ -2057,10 +2057,10 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
|||
|
||||
bool EntityItem::clearActions(EntitySimulationPointer simulation) {
|
||||
withWriteLock([&] {
|
||||
QHash<QUuid, EntityActionPointer>::iterator i = _objectActions.begin();
|
||||
QHash<QUuid, EntityDynamicPointer>::iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
const QUuid id = i.key();
|
||||
EntityActionPointer action = _objectActions[id];
|
||||
EntityDynamicPointer action = _objectActions[id];
|
||||
i = _objectActions.erase(i);
|
||||
action->setOwnerEntity(nullptr);
|
||||
action->removeFromSimulation(simulation);
|
||||
|
@ -2101,12 +2101,12 @@ void EntityItem::deserializeActionsInternal() {
|
|||
serializedActionsStream >> serializedActions;
|
||||
}
|
||||
|
||||
// Keep track of which actions got added or updated by the new actionData
|
||||
// Keep track of which actions got added or updated by the new dynamicData
|
||||
QSet<QUuid> updated;
|
||||
|
||||
foreach(QByteArray serializedAction, serializedActions) {
|
||||
QDataStream serializedActionStream(serializedAction);
|
||||
EntityActionType actionType;
|
||||
EntityDynamicType actionType;
|
||||
QUuid actionID;
|
||||
serializedActionStream >> actionType;
|
||||
serializedActionStream >> actionID;
|
||||
|
@ -2115,7 +2115,7 @@ void EntityItem::deserializeActionsInternal() {
|
|||
}
|
||||
|
||||
if (_objectActions.contains(actionID)) {
|
||||
EntityActionPointer action = _objectActions[actionID];
|
||||
EntityDynamicPointer action = _objectActions[actionID];
|
||||
// TODO: make sure types match? there isn't currently a way to
|
||||
// change the type of an existing action.
|
||||
if (!action->isMine()) {
|
||||
|
@ -2123,9 +2123,9 @@ void EntityItem::deserializeActionsInternal() {
|
|||
}
|
||||
updated << actionID;
|
||||
} else {
|
||||
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
|
||||
auto actionFactory = DependencyManager::get<EntityDynamicFactoryInterface>();
|
||||
EntityItemPointer entity = getThisPointer();
|
||||
EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction);
|
||||
EntityDynamicPointer action = actionFactory->factoryBA(entity, serializedAction);
|
||||
if (action) {
|
||||
entity->addActionInternal(simulation, action);
|
||||
updated << actionID;
|
||||
|
@ -2140,15 +2140,15 @@ void EntityItem::deserializeActionsInternal() {
|
|||
}
|
||||
|
||||
// remove any actions that weren't included in the new data.
|
||||
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
QUuid id = i.key();
|
||||
if (!updated.contains(id)) {
|
||||
EntityActionPointer action = i.value();
|
||||
EntityDynamicPointer action = i.value();
|
||||
|
||||
if (action->isMine()) {
|
||||
// we just received an update that didn't include one of our actions. tell the server about it (again).
|
||||
setActionDataNeedsTransmit(true);
|
||||
setDynamicDataNeedsTransmit(true);
|
||||
} else {
|
||||
// don't let someone else delete my action.
|
||||
_actionsToRemove << id;
|
||||
|
@ -2167,7 +2167,7 @@ void EntityItem::deserializeActionsInternal() {
|
|||
}
|
||||
}
|
||||
|
||||
_actionDataDirty = true;
|
||||
_dynamicDataDirty = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -2179,15 +2179,15 @@ void EntityItem::checkWaitingToRemove(EntitySimulationPointer simulation) {
|
|||
_actionsToRemove.clear();
|
||||
}
|
||||
|
||||
void EntityItem::setActionData(QByteArray actionData) {
|
||||
void EntityItem::setDynamicData(QByteArray dynamicData) {
|
||||
withWriteLock([&] {
|
||||
setActionDataInternal(actionData);
|
||||
setDynamicDataInternal(dynamicData);
|
||||
});
|
||||
}
|
||||
|
||||
void EntityItem::setActionDataInternal(QByteArray actionData) {
|
||||
if (_allActionsDataCache != actionData) {
|
||||
_allActionsDataCache = actionData;
|
||||
void EntityItem::setDynamicDataInternal(QByteArray dynamicData) {
|
||||
if (_allActionsDataCache != dynamicData) {
|
||||
_allActionsDataCache = dynamicData;
|
||||
deserializeActionsInternal();
|
||||
}
|
||||
checkWaitingToRemove();
|
||||
|
@ -2201,10 +2201,10 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const {
|
|||
}
|
||||
|
||||
QVector<QByteArray> serializedActions;
|
||||
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
const QUuid id = i.key();
|
||||
EntityActionPointer action = _objectActions[id];
|
||||
EntityDynamicPointer action = _objectActions[id];
|
||||
QByteArray bytesForAction = action->serialize();
|
||||
serializedActions << bytesForAction;
|
||||
i++;
|
||||
|
@ -2224,23 +2224,23 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const {
|
|||
return;
|
||||
}
|
||||
|
||||
const QByteArray EntityItem::getActionDataInternal() const {
|
||||
if (_actionDataDirty) {
|
||||
const QByteArray EntityItem::getDynamicDataInternal() const {
|
||||
if (_dynamicDataDirty) {
|
||||
bool success;
|
||||
serializeActions(success, _allActionsDataCache);
|
||||
if (success) {
|
||||
_actionDataDirty = false;
|
||||
_dynamicDataDirty = false;
|
||||
}
|
||||
}
|
||||
return _allActionsDataCache;
|
||||
}
|
||||
|
||||
const QByteArray EntityItem::getActionData() const {
|
||||
const QByteArray EntityItem::getDynamicData() const {
|
||||
QByteArray result;
|
||||
|
||||
if (_actionDataDirty) {
|
||||
if (_dynamicDataDirty) {
|
||||
withWriteLock([&] {
|
||||
getActionDataInternal();
|
||||
getDynamicDataInternal();
|
||||
result = _allActionsDataCache;
|
||||
});
|
||||
} else {
|
||||
|
@ -2255,9 +2255,9 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const {
|
|||
QVariantMap result;
|
||||
withReadLock([&] {
|
||||
if (_objectActions.contains(actionID)) {
|
||||
EntityActionPointer action = _objectActions[actionID];
|
||||
EntityDynamicPointer action = _objectActions[actionID];
|
||||
result = action->getArguments();
|
||||
result["type"] = EntityActionInterface::actionTypeToString(action->getType());
|
||||
result["type"] = EntityDynamicInterface::dynamicTypeToString(action->getType());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2265,7 +2265,7 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const {
|
|||
}
|
||||
|
||||
bool EntityItem::shouldSuppressLocationEdits() const {
|
||||
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
if (i.value()->shouldSuppressLocationEdits()) {
|
||||
return true;
|
||||
|
@ -2276,12 +2276,12 @@ bool EntityItem::shouldSuppressLocationEdits() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
QList<EntityActionPointer> EntityItem::getActionsOfType(EntityActionType typeToGet) const {
|
||||
QList<EntityActionPointer> result;
|
||||
QList<EntityDynamicPointer> EntityItem::getActionsOfType(EntityDynamicType typeToGet) const {
|
||||
QList<EntityDynamicPointer> result;
|
||||
|
||||
QHash<QUuid, EntityActionPointer>::const_iterator i = _objectActions.begin();
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
EntityActionPointer action = i.value();
|
||||
EntityDynamicPointer action = i.value();
|
||||
if (action->getType() == typeToGet && action->isActive()) {
|
||||
result += action;
|
||||
}
|
||||
|
|
|
@ -36,17 +36,17 @@
|
|||
#include "EntityTypes.h"
|
||||
#include "SimulationOwner.h"
|
||||
#include "SimulationFlags.h"
|
||||
#include "EntityActionInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
class EntitySimulation;
|
||||
class EntityTreeElement;
|
||||
class EntityTreeElementExtraEncodeData;
|
||||
class EntityActionInterface;
|
||||
class EntityDynamicInterface;
|
||||
class EntityItemProperties;
|
||||
class EntityTree;
|
||||
class btCollisionShape;
|
||||
typedef std::shared_ptr<EntityTree> EntityTreePointer;
|
||||
typedef std::shared_ptr<EntityActionInterface> EntityActionPointer;
|
||||
typedef std::shared_ptr<EntityDynamicInterface> EntityDynamicPointer;
|
||||
typedef std::shared_ptr<EntityTreeElement> EntityTreeElementPointer;
|
||||
using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr<EntityTreeElementExtraEncodeData>;
|
||||
|
||||
|
@ -398,22 +398,22 @@ public:
|
|||
void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; }
|
||||
|
||||
QString actionsToDebugString();
|
||||
bool addAction(EntitySimulationPointer simulation, EntityActionPointer action);
|
||||
bool addAction(EntitySimulationPointer simulation, EntityDynamicPointer action);
|
||||
bool updateAction(EntitySimulationPointer simulation, const QUuid& actionID, const QVariantMap& arguments);
|
||||
bool removeAction(EntitySimulationPointer simulation, const QUuid& actionID);
|
||||
bool clearActions(EntitySimulationPointer simulation);
|
||||
void setActionData(QByteArray actionData);
|
||||
const QByteArray getActionData() const;
|
||||
void setDynamicData(QByteArray dynamicData);
|
||||
const QByteArray getDynamicData() const;
|
||||
bool hasActions() const { return !_objectActions.empty(); }
|
||||
QList<QUuid> getActionIDs() const { return _objectActions.keys(); }
|
||||
QVariantMap getActionArguments(const QUuid& actionID) const;
|
||||
void deserializeActions();
|
||||
|
||||
void setActionDataDirty(bool value) const { _actionDataDirty = value; }
|
||||
bool actionDataDirty() const { return _actionDataDirty; }
|
||||
void setDynamicDataDirty(bool value) const { _dynamicDataDirty = value; }
|
||||
bool dynamicDataDirty() const { return _dynamicDataDirty; }
|
||||
|
||||
void setActionDataNeedsTransmit(bool value) const { _actionDataNeedsTransmit = value; }
|
||||
bool actionDataNeedsTransmit() const { return _actionDataNeedsTransmit; }
|
||||
void setDynamicDataNeedsTransmit(bool value) const { _dynamicDataNeedsTransmit = value; }
|
||||
bool dynamicDataNeedsTransmit() const { return _dynamicDataNeedsTransmit; }
|
||||
|
||||
bool shouldSuppressLocationEdits() const;
|
||||
|
||||
|
@ -421,7 +421,7 @@ public:
|
|||
const QUuid& getSourceUUID() const { return _sourceUUID; }
|
||||
bool matchesSourceUUID(const QUuid& sourceUUID) const { return _sourceUUID == sourceUUID; }
|
||||
|
||||
QList<EntityActionPointer> getActionsOfType(EntityActionType typeToGet) const;
|
||||
QList<EntityDynamicPointer> getActionsOfType(EntityDynamicType typeToGet) const;
|
||||
|
||||
// these are in the frame of this object
|
||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); }
|
||||
|
@ -479,8 +479,8 @@ protected:
|
|||
|
||||
void setSimulated(bool simulated) { _simulated = simulated; }
|
||||
|
||||
const QByteArray getActionDataInternal() const;
|
||||
void setActionDataInternal(QByteArray actionData);
|
||||
const QByteArray getDynamicDataInternal() const;
|
||||
void setDynamicDataInternal(QByteArray dynamicData);
|
||||
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
virtual void dimensionsChanged() override;
|
||||
|
@ -570,22 +570,22 @@ protected:
|
|||
void* _physicsInfo { nullptr }; // set by EntitySimulation
|
||||
bool _simulated; // set by EntitySimulation
|
||||
|
||||
bool addActionInternal(EntitySimulationPointer simulation, EntityActionPointer action);
|
||||
bool addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action);
|
||||
bool removeActionInternal(const QUuid& actionID, EntitySimulationPointer simulation = nullptr);
|
||||
void deserializeActionsInternal();
|
||||
void serializeActions(bool& success, QByteArray& result) const;
|
||||
QHash<QUuid, EntityActionPointer> _objectActions;
|
||||
QHash<QUuid, EntityDynamicPointer> _objectActions;
|
||||
|
||||
static int _maxActionsDataSize;
|
||||
mutable QByteArray _allActionsDataCache;
|
||||
|
||||
// when an entity-server starts up, EntityItem::setActionData is called before the entity-tree is
|
||||
// when an entity-server starts up, EntityItem::setDynamicData is called before the entity-tree is
|
||||
// ready. This means we can't find our EntityItemPointer or add the action to the simulation. These
|
||||
// are used to keep track of and work around this situation.
|
||||
void checkWaitingToRemove(EntitySimulationPointer simulation = nullptr);
|
||||
mutable QSet<QUuid> _actionsToRemove;
|
||||
mutable bool _actionDataDirty { false };
|
||||
mutable bool _actionDataNeedsTransmit { false };
|
||||
mutable bool _dynamicDataDirty { false };
|
||||
mutable bool _dynamicDataNeedsTransmit { false };
|
||||
// _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag
|
||||
static quint64 _rememberDeletedActionTime;
|
||||
mutable QHash<QUuid, quint64> _previouslyDeletedActions;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
#include <model-networking/MeshProxy.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityActionFactoryInterface.h"
|
||||
#include "EntityActionInterface.h"
|
||||
#include "EntityDynamicFactoryInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
#include "EntitySimulation.h"
|
||||
#include "EntityTree.h"
|
||||
#include "LightEntityItem.h"
|
||||
|
@ -1133,7 +1133,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
|||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
QUuid actionID = QUuid::createUuid();
|
||||
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
|
||||
auto actionFactory = DependencyManager::get<EntityDynamicFactoryInterface>();
|
||||
bool success = false;
|
||||
actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
|
||||
// create this action even if the entity doesn't have physics info. it will often be the
|
||||
|
@ -1142,11 +1142,11 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
|||
// if (!entity->getPhysicsInfo()) {
|
||||
// return false;
|
||||
// }
|
||||
EntityActionType actionType = EntityActionInterface::actionTypeFromString(actionTypeString);
|
||||
if (actionType == ACTION_TYPE_NONE) {
|
||||
EntityDynamicType dynamicType = EntityDynamicInterface::dynamicTypeFromString(actionTypeString);
|
||||
if (dynamicType == DYNAMIC_TYPE_NONE) {
|
||||
return false;
|
||||
}
|
||||
EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments);
|
||||
EntityDynamicPointer action = actionFactory->factory(dynamicType, actionID, entity, arguments);
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -279,25 +279,25 @@ void EntitySimulation::moveSimpleKinematics(const quint64& now) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntitySimulation::addAction(EntityActionPointer action) {
|
||||
void EntitySimulation::addDynamic(EntityDynamicPointer dynamic) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
_actionsToAdd += action;
|
||||
_dynamicsToAdd += dynamic;
|
||||
}
|
||||
|
||||
void EntitySimulation::removeAction(const QUuid actionID) {
|
||||
void EntitySimulation::removeDynamic(const QUuid dynamicID) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
_actionsToRemove += actionID;
|
||||
_dynamicsToRemove += dynamicID;
|
||||
}
|
||||
|
||||
void EntitySimulation::removeActions(QList<QUuid> actionIDsToRemove) {
|
||||
void EntitySimulation::removeDynamics(QList<QUuid> dynamicIDsToRemove) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
foreach(QUuid uuid, actionIDsToRemove) {
|
||||
_actionsToRemove.insert(uuid);
|
||||
foreach(QUuid uuid, dynamicIDsToRemove) {
|
||||
_dynamicsToRemove.insert(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void EntitySimulation::applyActionChanges() {
|
||||
void EntitySimulation::applyDynamicChanges() {
|
||||
QMutexLocker lock(&_mutex);
|
||||
_actionsToAdd.clear();
|
||||
_actionsToRemove.clear();
|
||||
_dynamicsToAdd.clear();
|
||||
_dynamicsToRemove.clear();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "EntityActionInterface.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
#include "EntityItem.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
|
@ -59,10 +59,10 @@ public:
|
|||
|
||||
// friend class EntityTree;
|
||||
|
||||
virtual void addAction(EntityActionPointer action);
|
||||
virtual void removeAction(const QUuid actionID);
|
||||
virtual void removeActions(QList<QUuid> actionIDsToRemove);
|
||||
virtual void applyActionChanges();
|
||||
virtual void addDynamic(EntityDynamicPointer dynamic);
|
||||
virtual void removeDynamic(const QUuid dynamicID);
|
||||
virtual void removeDynamics(QList<QUuid> dynamicIDsToRemove);
|
||||
virtual void applyDynamicChanges();
|
||||
|
||||
/// \param entity pointer to EntityItem to be added
|
||||
/// \sideeffect sets relevant backpointers in entity, but maybe later when appropriate data structures are locked
|
||||
|
@ -103,8 +103,8 @@ protected:
|
|||
|
||||
SetOfEntities _entitiesToSort; // entities moved by simulation (and might need resort in EntityTree)
|
||||
SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion
|
||||
QList<EntityActionPointer> _actionsToAdd;
|
||||
QSet<QUuid> _actionsToRemove;
|
||||
QList<EntityDynamicPointer> _dynamicsToAdd;
|
||||
QSet<QUuid> _dynamicsToRemove;
|
||||
|
||||
protected:
|
||||
SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete)
|
||||
|
|
|
@ -808,7 +808,7 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
|||
int index = changedProperties.indexOf("actionData");
|
||||
if (index >= 0) {
|
||||
QByteArray value = properties.getActionData();
|
||||
QString changeHint = serializedActionsToDebugString(value);
|
||||
QString changeHint = serializedDynamicsToDebugString(value);
|
||||
changedProperties[index] = QString("actionData:") + changeHint;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ void EntityMotionState::updateServerPhysicsVariables() {
|
|||
_serverPosition = localTransform.getTranslation();
|
||||
_serverRotation = localTransform.getRotation();
|
||||
_serverAcceleration = _entity->getAcceleration();
|
||||
_serverActionData = _entity->getActionData();
|
||||
_serverActionData = _entity->getDynamicData();
|
||||
}
|
||||
|
||||
void EntityMotionState::handleDeactivation() {
|
||||
|
@ -309,7 +309,7 @@ bool EntityMotionState::isCandidateForOwnership() const {
|
|||
assert(entityTreeIsLocked());
|
||||
return _outgoingPriority != 0
|
||||
|| Physics::getSessionUUID() == _entity->getSimulatorID()
|
||||
|| _entity->actionDataNeedsTransmit();
|
||||
|| _entity->dynamicDataNeedsTransmit();
|
||||
}
|
||||
|
||||
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||
|
@ -335,7 +335,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
_serverAcceleration = Vectors::ZERO;
|
||||
_serverAngularVelocity = worldVelocityToLocal.transform(bulletToGLM(_body->getAngularVelocity()));
|
||||
_lastStep = simulationStep;
|
||||
_serverActionData = _entity->getActionData();
|
||||
_serverActionData = _entity->getDynamicData();
|
||||
_numInactiveUpdates = 1;
|
||||
return false;
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_entity->actionDataNeedsTransmit()) {
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
_outgoingPriority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY;
|
||||
return true;
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (_entity->actionDataNeedsTransmit()) {
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
_serverPosition = localTransform.getTranslation();
|
||||
_serverRotation = localTransform.getRotation();
|
||||
_serverAcceleration = _entity->getAcceleration();
|
||||
_serverActionData = _entity->getActionData();
|
||||
_serverActionData = _entity->getDynamicData();
|
||||
|
||||
EntityItemProperties properties;
|
||||
|
||||
|
@ -562,8 +562,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
properties.setVelocity(_serverVelocity);
|
||||
properties.setAcceleration(_serverAcceleration);
|
||||
properties.setAngularVelocity(_serverAngularVelocity);
|
||||
if (_entity->actionDataNeedsTransmit()) {
|
||||
_entity->setActionDataNeedsTransmit(false);
|
||||
if (_entity->dynamicDataNeedsTransmit()) {
|
||||
_entity->setDynamicDataNeedsTransmit(false);
|
||||
properties.setActionData(_serverActionData);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,10 @@
|
|||
#include "PhysicsLogging.h"
|
||||
|
||||
|
||||
ObjectAction::ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction::ObjectAction(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
btActionInterface(),
|
||||
EntityActionInterface(type, id),
|
||||
_ownerEntity(ownerEntity) {
|
||||
}
|
||||
|
||||
ObjectAction::~ObjectAction() {
|
||||
ObjectDynamic(type, id, ownerEntity)
|
||||
{
|
||||
}
|
||||
|
||||
void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
|
||||
|
@ -64,240 +61,5 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta
|
|||
updateActionWorker(deltaTimeStep);
|
||||
}
|
||||
|
||||
qint64 ObjectAction::getEntityServerClockSkew() const {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QUuid& entityServerNodeID = ownerEntity->getSourceUUID();
|
||||
auto entityServerNode = nodeList->nodeWithUUID(entityServerNodeID);
|
||||
if (entityServerNode) {
|
||||
return entityServerNode->getClockSkewUsec();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ObjectAction::updateArguments(QVariantMap arguments) {
|
||||
bool somethingChanged = false;
|
||||
|
||||
withWriteLock([&]{
|
||||
quint64 previousExpires = _expires;
|
||||
QString previousTag = _tag;
|
||||
|
||||
bool ttlSet = true;
|
||||
float ttl = EntityActionInterface::extractFloatArgument("action", arguments, "ttl", ttlSet, false);
|
||||
if (ttlSet) {
|
||||
quint64 now = usecTimestampNow();
|
||||
_expires = now + (quint64)(ttl * USECS_PER_SECOND);
|
||||
} else {
|
||||
_expires = 0;
|
||||
}
|
||||
|
||||
bool tagSet = true;
|
||||
QString tag = EntityActionInterface::extractStringArgument("action", arguments, "tag", tagSet, false);
|
||||
if (tagSet) {
|
||||
_tag = tag;
|
||||
} else {
|
||||
tag = "";
|
||||
}
|
||||
|
||||
if (previousExpires != _expires || previousTag != _tag) {
|
||||
somethingChanged = true;
|
||||
}
|
||||
});
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
QVariantMap ObjectAction::getArguments() {
|
||||
QVariantMap arguments;
|
||||
withReadLock([&]{
|
||||
if (_expires == 0) {
|
||||
arguments["ttl"] = 0.0f;
|
||||
} else {
|
||||
quint64 now = usecTimestampNow();
|
||||
arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND;
|
||||
}
|
||||
arguments["tag"] = _tag;
|
||||
|
||||
EntityItemPointer entity = _ownerEntity.lock();
|
||||
if (entity) {
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
arguments["::active"] = motionState->isActive();
|
||||
arguments["::motion-type"] = motionTypeToString(motionState->getMotionType());
|
||||
} else {
|
||||
arguments["::no-motion-state"] = true;
|
||||
}
|
||||
}
|
||||
arguments["isMine"] = isMine();
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
||||
|
||||
void ObjectAction::debugDraw(btIDebugDraw* debugDrawer) {
|
||||
}
|
||||
|
||||
void ObjectAction::removeFromSimulation(EntitySimulationPointer simulation) const {
|
||||
QUuid myID;
|
||||
withReadLock([&]{
|
||||
myID = _id;
|
||||
});
|
||||
simulation->removeAction(myID);
|
||||
}
|
||||
|
||||
btRigidBody* ObjectAction::getRigidBody() {
|
||||
ObjectMotionState* motionState = nullptr;
|
||||
withReadLock([&]{
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return;
|
||||
}
|
||||
void* physicsInfo = ownerEntity->getPhysicsInfo();
|
||||
if (!physicsInfo) {
|
||||
return;
|
||||
}
|
||||
motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
});
|
||||
if (motionState) {
|
||||
return motionState->getRigidBody();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glm::vec3 ObjectAction::getPosition() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getCenterOfMassPosition());
|
||||
}
|
||||
|
||||
void ObjectAction::setPosition(glm::vec3 position) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
// XXX
|
||||
// void setWorldTransform (const btTransform &worldTrans)
|
||||
assert(false);
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
glm::quat ObjectAction::getRotation() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::quat(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getOrientation());
|
||||
}
|
||||
|
||||
void ObjectAction::setRotation(glm::quat rotation) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
// XXX
|
||||
// void setWorldTransform (const btTransform &worldTrans)
|
||||
assert(false);
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
glm::vec3 ObjectAction::getLinearVelocity() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getLinearVelocity());
|
||||
}
|
||||
|
||||
void ObjectAction::setLinearVelocity(glm::vec3 linearVelocity) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f)));
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
glm::vec3 ObjectAction::getAngularVelocity() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getAngularVelocity());
|
||||
}
|
||||
|
||||
void ObjectAction::setAngularVelocity(glm::vec3 angularVelocity) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
rigidBody->setAngularVelocity(glmToBullet(angularVelocity));
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
void ObjectAction::activateBody(bool forceActivation) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (rigidBody) {
|
||||
rigidBody->activate(forceActivation);
|
||||
} else {
|
||||
qCDebug(physics) << "ObjectAction::activateBody -- no rigid body" << (void*)rigidBody;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectAction::forceBodyNonStatic() {
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return;
|
||||
}
|
||||
void* physicsInfo = ownerEntity->getPhysicsInfo();
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
if (motionState && motionState->getMotionType() == MOTION_TYPE_STATIC) {
|
||||
ownerEntity->flagForMotionStateChange();
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectAction::lifetimeIsOver() {
|
||||
if (_expires == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
if (now >= _expires) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const {
|
||||
// 0 indicates no expiration
|
||||
if (timeValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 serverClockSkew = getEntityServerClockSkew();
|
||||
if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) {
|
||||
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||
}
|
||||
|
||||
return timeValue + serverClockSkew;
|
||||
}
|
||||
|
||||
quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) const {
|
||||
// 0 indicates no expiration
|
||||
if (timeValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 serverClockSkew = getEntityServerClockSkew();
|
||||
if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) {
|
||||
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||
}
|
||||
|
||||
return timeValue - serverClockSkew;
|
||||
}
|
||||
|
|
|
@ -14,63 +14,19 @@
|
|||
#define hifi_ObjectAction_h
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include "ObjectDynamic.h"
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "ObjectMotionState.h"
|
||||
#include "BulletUtil.h"
|
||||
#include "EntityActionInterface.h"
|
||||
|
||||
|
||||
class ObjectAction : public btActionInterface, public EntityActionInterface, public ReadWriteLockable {
|
||||
class ObjectAction : public btActionInterface, public ObjectDynamic {
|
||||
public:
|
||||
ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~ObjectAction();
|
||||
|
||||
virtual void removeFromSimulation(EntitySimulationPointer simulation) const override;
|
||||
virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; }
|
||||
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; }
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments) override;
|
||||
virtual QVariantMap getArguments() override;
|
||||
ObjectAction(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity);
|
||||
|
||||
// this is called from updateAction and should be overridden by subclasses
|
||||
virtual void updateActionWorker(float deltaTimeStep) = 0;
|
||||
|
||||
// these are from btActionInterface
|
||||
// these are from btDynamicInterface
|
||||
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) override;
|
||||
virtual void debugDraw(btIDebugDraw* debugDrawer) override;
|
||||
|
||||
virtual QByteArray serialize() const override = 0;
|
||||
virtual void deserialize(QByteArray serializedArguments) override = 0;
|
||||
|
||||
virtual bool lifetimeIsOver() override;
|
||||
virtual quint64 getExpires() override { return _expires; }
|
||||
|
||||
protected:
|
||||
quint64 localTimeToServerTime(quint64 timeValue) const;
|
||||
quint64 serverTimeToLocalTime(quint64 timeValue) const;
|
||||
|
||||
virtual btRigidBody* getRigidBody();
|
||||
virtual glm::vec3 getPosition() override;
|
||||
virtual void setPosition(glm::vec3 position) override;
|
||||
virtual glm::quat getRotation() override;
|
||||
virtual void setRotation(glm::quat rotation) override;
|
||||
virtual glm::vec3 getLinearVelocity() override;
|
||||
virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
|
||||
virtual glm::vec3 getAngularVelocity() override;
|
||||
virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
|
||||
virtual void activateBody(bool forceActivation = false);
|
||||
virtual void forceBodyNonStatic();
|
||||
|
||||
EntityItemWeakPointer _ownerEntity;
|
||||
QString _tag;
|
||||
quint64 _expires { 0 }; // in seconds since epoch
|
||||
|
||||
private:
|
||||
qint64 getEntityServerClockSkew() const;
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectAction_h
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
const uint16_t ObjectActionOffset::offsetVersion = 1;
|
||||
|
||||
ObjectActionOffset::ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(ACTION_TYPE_OFFSET, id, ownerEntity),
|
||||
ObjectAction(DYNAMIC_TYPE_OFFSET, id, ownerEntity),
|
||||
_pointToOffsetFrom(0.0f),
|
||||
_linearDistance(0.0f),
|
||||
_linearTimeScale(FLT_MAX),
|
||||
|
@ -93,21 +93,21 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
|||
withReadLock([&]{
|
||||
bool ok = true;
|
||||
pointToOffsetFrom =
|
||||
EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true);
|
||||
EntityDynamicInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true);
|
||||
if (!ok) {
|
||||
pointToOffsetFrom = _pointToOffsetFrom;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
linearTimeScale =
|
||||
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false);
|
||||
EntityDynamicInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false);
|
||||
if (!ok) {
|
||||
linearTimeScale = _linearTimeScale;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
linearDistance =
|
||||
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false);
|
||||
EntityDynamicInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false);
|
||||
if (!ok) {
|
||||
linearDistance = _linearDistance;
|
||||
}
|
||||
|
@ -132,8 +132,8 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
|||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
ownerEntity->setDynamicDataDirty(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
activateBody();
|
||||
|
@ -155,7 +155,7 @@ QVariantMap ObjectActionOffset::getArguments() {
|
|||
QByteArray ObjectActionOffset::serialize() const {
|
||||
QByteArray ba;
|
||||
QDataStream dataStream(&ba, QIODevice::WriteOnly);
|
||||
dataStream << ACTION_TYPE_OFFSET;
|
||||
dataStream << DYNAMIC_TYPE_OFFSET;
|
||||
dataStream << getID();
|
||||
dataStream << ObjectActionOffset::offsetVersion;
|
||||
|
||||
|
@ -174,7 +174,7 @@ QByteArray ObjectActionOffset::serialize() const {
|
|||
void ObjectActionOffset::deserialize(QByteArray serializedArguments) {
|
||||
QDataStream dataStream(serializedArguments);
|
||||
|
||||
EntityActionType type;
|
||||
EntityDynamicType type;
|
||||
dataStream >> type;
|
||||
assert(type == getType());
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ const uint16_t ObjectActionSpring::springVersion = 1;
|
|||
|
||||
|
||||
ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(ACTION_TYPE_SPRING, id, ownerEntity),
|
||||
ObjectAction(DYNAMIC_TYPE_SPRING, id, ownerEntity),
|
||||
_positionalTarget(glm::vec3(0.0f)),
|
||||
_desiredPositionalTarget(glm::vec3(0.0f)),
|
||||
_linearTimeScale(FLT_MAX),
|
||||
|
@ -64,11 +64,11 @@ bool ObjectActionSpring::prepareForSpringUpdate(btScalar deltaTimeStep) {
|
|||
bool valid = false;
|
||||
int springCount = 0;
|
||||
|
||||
QList<EntityActionPointer> springDerivedActions;
|
||||
springDerivedActions.append(ownerEntity->getActionsOfType(ACTION_TYPE_SPRING));
|
||||
springDerivedActions.append(ownerEntity->getActionsOfType(ACTION_TYPE_HOLD));
|
||||
QList<EntityDynamicPointer> springDerivedActions;
|
||||
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_SPRING));
|
||||
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_HOLD));
|
||||
|
||||
foreach (EntityActionPointer action, springDerivedActions) {
|
||||
foreach (EntityDynamicPointer action, springDerivedActions) {
|
||||
std::shared_ptr<ObjectActionSpring> springAction = std::static_pointer_cast<ObjectActionSpring>(action);
|
||||
glm::quat rotationForAction;
|
||||
glm::vec3 positionForAction;
|
||||
|
@ -194,25 +194,25 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
withReadLock([&]{
|
||||
// targets are required, spring-constants are optional
|
||||
bool ok = true;
|
||||
positionalTarget = EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false);
|
||||
positionalTarget = EntityDynamicInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false);
|
||||
if (!ok) {
|
||||
positionalTarget = _desiredPositionalTarget;
|
||||
}
|
||||
ok = true;
|
||||
linearTimeScale = EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false);
|
||||
linearTimeScale = EntityDynamicInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false);
|
||||
if (!ok || linearTimeScale <= 0.0f) {
|
||||
linearTimeScale = _linearTimeScale;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
rotationalTarget = EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false);
|
||||
rotationalTarget = EntityDynamicInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false);
|
||||
if (!ok) {
|
||||
rotationalTarget = _desiredRotationalTarget;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
angularTimeScale =
|
||||
EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false);
|
||||
EntityDynamicInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false);
|
||||
if (!ok) {
|
||||
angularTimeScale = _angularTimeScale;
|
||||
}
|
||||
|
@ -237,8 +237,8 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
ownerEntity->setDynamicDataDirty(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
activateBody();
|
||||
|
@ -263,7 +263,7 @@ QByteArray ObjectActionSpring::serialize() const {
|
|||
QByteArray serializedActionArguments;
|
||||
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
|
||||
|
||||
dataStream << ACTION_TYPE_SPRING;
|
||||
dataStream << DYNAMIC_TYPE_SPRING;
|
||||
dataStream << getID();
|
||||
dataStream << ObjectActionSpring::springVersion;
|
||||
|
||||
|
@ -284,7 +284,7 @@ QByteArray ObjectActionSpring::serialize() const {
|
|||
void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
|
||||
QDataStream dataStream(serializedArguments);
|
||||
|
||||
EntityActionType type;
|
||||
EntityDynamicType type;
|
||||
dataStream >> type;
|
||||
assert(type == getType());
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ const uint16_t ObjectActionTravelOriented::actionVersion = 1;
|
|||
|
||||
|
||||
ObjectActionTravelOriented::ObjectActionTravelOriented(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(ACTION_TYPE_TRAVEL_ORIENTED, id, ownerEntity) {
|
||||
ObjectAction(DYNAMIC_TYPE_TRAVEL_ORIENTED, id, ownerEntity) {
|
||||
#if WANT_DEBUG
|
||||
qCDebug(physics) << "ObjectActionTravelOriented::ObjectActionTravelOriented";
|
||||
#endif
|
||||
|
@ -109,13 +109,13 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) {
|
|||
bool somethingChanged = ObjectAction::updateArguments(arguments);
|
||||
withReadLock([&]{
|
||||
bool ok = true;
|
||||
forward = EntityActionInterface::extractVec3Argument("travel oriented action", arguments, "forward", ok, true);
|
||||
forward = EntityDynamicInterface::extractVec3Argument("travel oriented action", arguments, "forward", ok, true);
|
||||
if (!ok) {
|
||||
forward = _forward;
|
||||
}
|
||||
ok = true;
|
||||
angularTimeScale =
|
||||
EntityActionInterface::extractFloatArgument("travel oriented action", arguments, "angularTimeScale", ok, false);
|
||||
EntityDynamicInterface::extractFloatArgument("travel oriented action", arguments, "angularTimeScale", ok, false);
|
||||
if (!ok) {
|
||||
angularTimeScale = _angularTimeScale;
|
||||
}
|
||||
|
@ -136,8 +136,8 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) {
|
|||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
ownerEntity->setDynamicDataDirty(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
activateBody();
|
||||
|
@ -159,7 +159,7 @@ QByteArray ObjectActionTravelOriented::serialize() const {
|
|||
QByteArray serializedActionArguments;
|
||||
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
|
||||
|
||||
dataStream << ACTION_TYPE_TRAVEL_ORIENTED;
|
||||
dataStream << DYNAMIC_TYPE_TRAVEL_ORIENTED;
|
||||
dataStream << getID();
|
||||
dataStream << ObjectActionTravelOriented::actionVersion;
|
||||
|
||||
|
@ -177,7 +177,7 @@ QByteArray ObjectActionTravelOriented::serialize() const {
|
|||
void ObjectActionTravelOriented::deserialize(QByteArray serializedArguments) {
|
||||
QDataStream dataStream(serializedArguments);
|
||||
|
||||
EntityActionType type;
|
||||
EntityDynamicType type;
|
||||
dataStream >> type;
|
||||
assert(type == getType());
|
||||
|
||||
|
|
21
libraries/physics/src/ObjectConstraint.cpp
Normal file
21
libraries/physics/src/ObjectConstraint.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// ObjectConstraint.cpp
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-2
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include "ObjectConstraint.h"
|
||||
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
ObjectConstraint::ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectDynamic(type, id, ownerEntity)
|
||||
{
|
||||
}
|
29
libraries/physics/src/ObjectConstraint.h
Normal file
29
libraries/physics/src/ObjectConstraint.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// ObjectConstraint.h
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Seth Alves 2017-4-11
|
||||
// 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
|
||||
//
|
||||
// http://bulletphysics.org/Bullet/BulletFull/classbtConstraintInterface.html
|
||||
|
||||
#ifndef hifi_ObjectConstraint_h
|
||||
#define hifi_ObjectConstraint_h
|
||||
|
||||
#include <QUuid>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include "ObjectDynamic.h"
|
||||
|
||||
class ObjectConstraint : public ObjectDynamic
|
||||
{
|
||||
public:
|
||||
ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual btTypedConstraint* getConstraint() = 0;
|
||||
protected:
|
||||
btTypedConstraint* _constraint { nullptr };
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectConstraint_h
|
160
libraries/physics/src/ObjectConstraintHinge.cpp
Normal file
160
libraries/physics/src/ObjectConstraintHinge.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
//
|
||||
// ObjectConstraintHinge.cpp
|
||||
// libraries/physics/src
|
||||
//
|
||||
// Created by Seth Alves 2017-4-11
|
||||
// Copyright 2017 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 "QVariantGLM.h"
|
||||
|
||||
#include "ObjectConstraintHinge.h"
|
||||
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
|
||||
const uint16_t ObjectConstraintHinge::constraintVersion = 1;
|
||||
|
||||
|
||||
ObjectConstraintHinge::ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectConstraint(DYNAMIC_TYPE_HINGE, id, ownerEntity),
|
||||
_rbATranslation(glm::vec3(0.0f)),
|
||||
_rbARotation(glm::quat())
|
||||
{
|
||||
#if WANT_DEBUG
|
||||
qCDebug(physics) << "ObjectConstraintHinge::ObjectConstraintHinge";
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectConstraintHinge::~ObjectConstraintHinge() {
|
||||
#if WANT_DEBUG
|
||||
qCDebug(physics) << "ObjectConstraintHinge::~ObjectConstraintHinge";
|
||||
#endif
|
||||
}
|
||||
|
||||
btTypedConstraint* ObjectConstraintHinge::getConstraint() {
|
||||
if (_constraint) {
|
||||
return _constraint;
|
||||
}
|
||||
|
||||
btRigidBody* rigidBodyA = getRigidBody();
|
||||
if (!rigidBodyA) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool useReferenceFrameA { false };
|
||||
|
||||
btTransform rigidBodyAFrame(glmToBullet(_rbARotation), glmToBullet(_rbATranslation));
|
||||
|
||||
_constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA);
|
||||
return _constraint;
|
||||
}
|
||||
|
||||
|
||||
bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
||||
glm::vec3 rbATranslation;
|
||||
glm::quat rbARotation;
|
||||
|
||||
bool needUpdate = false;
|
||||
bool somethingChanged = ObjectConstraint::updateArguments(arguments);
|
||||
withReadLock([&]{
|
||||
// targets are required, hinge-constants are optional
|
||||
bool ok = true;
|
||||
rbATranslation = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "targetPosition", ok, false);
|
||||
if (!ok) {
|
||||
rbATranslation = _rbATranslation;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
rbARotation = EntityDynamicInterface::extractQuatArgument("hinge constraint", arguments, "targetRotation", ok, false);
|
||||
if (!ok) {
|
||||
rbARotation = _rbARotation;
|
||||
}
|
||||
|
||||
if (somethingChanged ||
|
||||
rbATranslation != _rbATranslation ||
|
||||
rbARotation != _rbARotation) {
|
||||
// something changed
|
||||
needUpdate = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (needUpdate) {
|
||||
withWriteLock([&] {
|
||||
_rbATranslation = rbATranslation;
|
||||
_rbARotation = rbARotation;
|
||||
_active = true;
|
||||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setDynamicDataDirty(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
activateBody();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap ObjectConstraintHinge::getArguments() {
|
||||
QVariantMap arguments = ObjectConstraint::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["targetPosition"] = glmToQMap(_rbATranslation);
|
||||
arguments["targetRotation"] = glmToQMap(_rbARotation);
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
||||
QByteArray ObjectConstraintHinge::serialize() const {
|
||||
QByteArray serializedConstraintArguments;
|
||||
QDataStream dataStream(&serializedConstraintArguments, QIODevice::WriteOnly);
|
||||
|
||||
dataStream << DYNAMIC_TYPE_HINGE;
|
||||
dataStream << getID();
|
||||
dataStream << ObjectConstraintHinge::constraintVersion;
|
||||
|
||||
withReadLock([&] {
|
||||
dataStream << _rbATranslation;
|
||||
dataStream << _rbARotation;
|
||||
dataStream << localTimeToServerTime(_expires);
|
||||
dataStream << _tag;
|
||||
});
|
||||
|
||||
return serializedConstraintArguments;
|
||||
}
|
||||
|
||||
void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) {
|
||||
QDataStream dataStream(serializedArguments);
|
||||
|
||||
EntityDynamicType type;
|
||||
dataStream >> type;
|
||||
assert(type == getType());
|
||||
|
||||
QUuid id;
|
||||
dataStream >> id;
|
||||
assert(id == getID());
|
||||
|
||||
uint16_t serializationVersion;
|
||||
dataStream >> serializationVersion;
|
||||
if (serializationVersion != ObjectConstraintHinge::constraintVersion) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
dataStream >> _rbATranslation;
|
||||
dataStream >> _rbARotation;
|
||||
|
||||
quint64 serverExpires;
|
||||
dataStream >> serverExpires;
|
||||
_expires = serverTimeToLocalTime(serverExpires);
|
||||
|
||||
dataStream >> _tag;
|
||||
|
||||
_active = true;
|
||||
});
|
||||
}
|
39
libraries/physics/src/ObjectConstraintHinge.h
Normal file
39
libraries/physics/src/ObjectConstraintHinge.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// ObjectConstraintHinge.h
|
||||
// libraries/physics/src
|
||||
//
|
||||
// Created by Seth Alves 2017-4-11
|
||||
// Copyright 2017 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_ObjectConstraintHinge_h
|
||||
#define hifi_ObjectConstraintHinge_h
|
||||
|
||||
#include "ObjectConstraint.h"
|
||||
|
||||
// http://bulletphysics.org/Bullet/BulletFull/classbtHingeConstraint.html
|
||||
|
||||
class ObjectConstraintHinge : public ObjectConstraint {
|
||||
public:
|
||||
ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~ObjectConstraintHinge();
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments) override;
|
||||
virtual QVariantMap getArguments() override;
|
||||
|
||||
virtual QByteArray serialize() const override;
|
||||
virtual void deserialize(QByteArray serializedArguments) override;
|
||||
|
||||
virtual btTypedConstraint* getConstraint() override;
|
||||
|
||||
protected:
|
||||
static const uint16_t constraintVersion;
|
||||
|
||||
glm::vec3 _rbATranslation;
|
||||
glm::quat _rbARotation;
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectConstraintHinge_h
|
259
libraries/physics/src/ObjectDynamic.cpp
Normal file
259
libraries/physics/src/ObjectDynamic.cpp
Normal file
|
@ -0,0 +1,259 @@
|
|||
//
|
||||
// ObjectDynamic.cpp
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-2
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include "ObjectDynamic.h"
|
||||
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
|
||||
ObjectDynamic::ObjectDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
EntityDynamicInterface(type, id),
|
||||
_ownerEntity(ownerEntity) {
|
||||
}
|
||||
|
||||
ObjectDynamic::~ObjectDynamic() {
|
||||
}
|
||||
|
||||
qint64 ObjectDynamic::getEntityServerClockSkew() const {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QUuid& entityServerNodeID = ownerEntity->getSourceUUID();
|
||||
auto entityServerNode = nodeList->nodeWithUUID(entityServerNodeID);
|
||||
if (entityServerNode) {
|
||||
return entityServerNode->getClockSkewUsec();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ObjectDynamic::updateArguments(QVariantMap arguments) {
|
||||
bool somethingChanged = false;
|
||||
|
||||
withWriteLock([&]{
|
||||
quint64 previousExpires = _expires;
|
||||
QString previousTag = _tag;
|
||||
|
||||
bool ttlSet = true;
|
||||
float ttl = EntityDynamicInterface::extractFloatArgument("dynamic", arguments, "ttl", ttlSet, false);
|
||||
if (ttlSet) {
|
||||
quint64 now = usecTimestampNow();
|
||||
_expires = now + (quint64)(ttl * USECS_PER_SECOND);
|
||||
} else {
|
||||
_expires = 0;
|
||||
}
|
||||
|
||||
bool tagSet = true;
|
||||
QString tag = EntityDynamicInterface::extractStringArgument("dynamic", arguments, "tag", tagSet, false);
|
||||
if (tagSet) {
|
||||
_tag = tag;
|
||||
} else {
|
||||
tag = "";
|
||||
}
|
||||
|
||||
if (previousExpires != _expires || previousTag != _tag) {
|
||||
somethingChanged = true;
|
||||
}
|
||||
});
|
||||
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
QVariantMap ObjectDynamic::getArguments() {
|
||||
QVariantMap arguments;
|
||||
withReadLock([&]{
|
||||
if (_expires == 0) {
|
||||
arguments["ttl"] = 0.0f;
|
||||
} else {
|
||||
quint64 now = usecTimestampNow();
|
||||
arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND;
|
||||
}
|
||||
arguments["tag"] = _tag;
|
||||
|
||||
EntityItemPointer entity = _ownerEntity.lock();
|
||||
if (entity) {
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
arguments["::active"] = motionState->isActive();
|
||||
arguments["::motion-type"] = motionTypeToString(motionState->getMotionType());
|
||||
} else {
|
||||
arguments["::no-motion-state"] = true;
|
||||
}
|
||||
}
|
||||
arguments["isMine"] = isMine();
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
||||
void ObjectDynamic::removeFromSimulation(EntitySimulationPointer simulation) const {
|
||||
QUuid myID;
|
||||
withReadLock([&]{
|
||||
myID = _id;
|
||||
});
|
||||
simulation->removeDynamic(myID);
|
||||
}
|
||||
|
||||
btRigidBody* ObjectDynamic::getRigidBody() {
|
||||
ObjectMotionState* motionState = nullptr;
|
||||
withReadLock([&]{
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return;
|
||||
}
|
||||
void* physicsInfo = ownerEntity->getPhysicsInfo();
|
||||
if (!physicsInfo) {
|
||||
return;
|
||||
}
|
||||
motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
});
|
||||
if (motionState) {
|
||||
return motionState->getRigidBody();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glm::vec3 ObjectDynamic::getPosition() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getCenterOfMassPosition());
|
||||
}
|
||||
|
||||
void ObjectDynamic::setPosition(glm::vec3 position) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
// XXX
|
||||
// void setWorldTransform (const btTransform &worldTrans)
|
||||
assert(false);
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
glm::quat ObjectDynamic::getRotation() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::quat(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getOrientation());
|
||||
}
|
||||
|
||||
void ObjectDynamic::setRotation(glm::quat rotation) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
// XXX
|
||||
// void setWorldTransform (const btTransform &worldTrans)
|
||||
assert(false);
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
glm::vec3 ObjectDynamic::getLinearVelocity() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getLinearVelocity());
|
||||
}
|
||||
|
||||
void ObjectDynamic::setLinearVelocity(glm::vec3 linearVelocity) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f)));
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
glm::vec3 ObjectDynamic::getAngularVelocity() {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
return bulletToGLM(rigidBody->getAngularVelocity());
|
||||
}
|
||||
|
||||
void ObjectDynamic::setAngularVelocity(glm::vec3 angularVelocity) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (!rigidBody) {
|
||||
return;
|
||||
}
|
||||
rigidBody->setAngularVelocity(glmToBullet(angularVelocity));
|
||||
rigidBody->activate();
|
||||
}
|
||||
|
||||
void ObjectDynamic::activateBody(bool forceActivation) {
|
||||
auto rigidBody = getRigidBody();
|
||||
if (rigidBody) {
|
||||
rigidBody->activate(forceActivation);
|
||||
} else {
|
||||
qCDebug(physics) << "ObjectDynamic::activateBody -- no rigid body" << (void*)rigidBody;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectDynamic::forceBodyNonStatic() {
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (!ownerEntity) {
|
||||
return;
|
||||
}
|
||||
void* physicsInfo = ownerEntity->getPhysicsInfo();
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
if (motionState && motionState->getMotionType() == MOTION_TYPE_STATIC) {
|
||||
ownerEntity->flagForMotionStateChange();
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectDynamic::lifetimeIsOver() {
|
||||
if (_expires == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
if (now >= _expires) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
quint64 ObjectDynamic::localTimeToServerTime(quint64 timeValue) const {
|
||||
// 0 indicates no expiration
|
||||
if (timeValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 serverClockSkew = getEntityServerClockSkew();
|
||||
if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) {
|
||||
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||
}
|
||||
|
||||
return timeValue + serverClockSkew;
|
||||
}
|
||||
|
||||
quint64 ObjectDynamic::serverTimeToLocalTime(quint64 timeValue) const {
|
||||
// 0 indicates no expiration
|
||||
if (timeValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 serverClockSkew = getEntityServerClockSkew();
|
||||
if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) {
|
||||
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||
}
|
||||
|
||||
return timeValue - serverClockSkew;
|
||||
}
|
70
libraries/physics/src/ObjectDynamic.h
Normal file
70
libraries/physics/src/ObjectDynamic.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// ObjectDynamic.h
|
||||
// libraries/physcis/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-2
|
||||
// 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
|
||||
//
|
||||
// http://bulletphysics.org/Bullet/BulletFull/classbtDynamicInterface.html
|
||||
|
||||
#ifndef hifi_ObjectDynamic_h
|
||||
#define hifi_ObjectDynamic_h
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "ObjectMotionState.h"
|
||||
#include "BulletUtil.h"
|
||||
#include "EntityDynamicInterface.h"
|
||||
|
||||
|
||||
class ObjectDynamic : public EntityDynamicInterface, public ReadWriteLockable {
|
||||
public:
|
||||
ObjectDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~ObjectDynamic();
|
||||
|
||||
virtual void removeFromSimulation(EntitySimulationPointer simulation) const override;
|
||||
virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; }
|
||||
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; }
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments) override;
|
||||
virtual QVariantMap getArguments() override;
|
||||
|
||||
|
||||
virtual QByteArray serialize() const override = 0;
|
||||
virtual void deserialize(QByteArray serializedArguments) override = 0;
|
||||
|
||||
virtual bool lifetimeIsOver() override;
|
||||
virtual quint64 getExpires() override { return _expires; }
|
||||
|
||||
protected:
|
||||
quint64 localTimeToServerTime(quint64 timeValue) const;
|
||||
quint64 serverTimeToLocalTime(quint64 timeValue) const;
|
||||
|
||||
virtual btRigidBody* getRigidBody();
|
||||
virtual glm::vec3 getPosition() override;
|
||||
virtual void setPosition(glm::vec3 position) override;
|
||||
virtual glm::quat getRotation() override;
|
||||
virtual void setRotation(glm::quat rotation) override;
|
||||
virtual glm::vec3 getLinearVelocity() override;
|
||||
virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
|
||||
virtual glm::vec3 getAngularVelocity() override;
|
||||
virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
|
||||
virtual void activateBody(bool forceActivation = false);
|
||||
virtual void forceBodyNonStatic();
|
||||
|
||||
EntityItemWeakPointer _ownerEntity;
|
||||
QString _tag;
|
||||
quint64 _expires { 0 }; // in seconds since epoch
|
||||
|
||||
private:
|
||||
qint64 getEntityServerClockSkew() const;
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectDynamic_h
|
|
@ -330,33 +330,33 @@ void PhysicalEntitySimulation::handleCollisionEvents(const CollisionEvents& coll
|
|||
}
|
||||
|
||||
|
||||
void PhysicalEntitySimulation::addAction(EntityActionPointer action) {
|
||||
void PhysicalEntitySimulation::addDynamic(EntityDynamicPointer dynamic) {
|
||||
if (_physicsEngine) {
|
||||
// FIXME put fine grain locking into _physicsEngine
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
const QUuid& actionID = action->getID();
|
||||
if (_physicsEngine->getActionByID(actionID)) {
|
||||
qCDebug(physics) << "warning -- PhysicalEntitySimulation::addAction -- adding an "
|
||||
"action that was already in _physicsEngine";
|
||||
const QUuid& dynamicID = dynamic->getID();
|
||||
if (_physicsEngine->getDynamicByID(dynamicID)) {
|
||||
qCDebug(physics) << "warning -- PhysicalEntitySimulation::addDynamic -- adding an "
|
||||
"dynamic that was already in _physicsEngine";
|
||||
}
|
||||
}
|
||||
EntitySimulation::addAction(action);
|
||||
EntitySimulation::addDynamic(dynamic);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalEntitySimulation::applyActionChanges() {
|
||||
void PhysicalEntitySimulation::applyDynamicChanges() {
|
||||
if (_physicsEngine) {
|
||||
// FIXME put fine grain locking into _physicsEngine
|
||||
QMutexLocker lock(&_mutex);
|
||||
foreach(QUuid actionToRemove, _actionsToRemove) {
|
||||
_physicsEngine->removeAction(actionToRemove);
|
||||
foreach(QUuid dynamicToRemove, _dynamicsToRemove) {
|
||||
_physicsEngine->removeDynamic(dynamicToRemove);
|
||||
}
|
||||
foreach (EntityActionPointer actionToAdd, _actionsToAdd) {
|
||||
if (!_actionsToRemove.contains(actionToAdd->getID())) {
|
||||
_physicsEngine->addAction(actionToAdd);
|
||||
foreach (EntityDynamicPointer dynamicToAdd, _dynamicsToAdd) {
|
||||
if (!_dynamicsToRemove.contains(dynamicToAdd->getID())) {
|
||||
_physicsEngine->addDynamic(dynamicToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
EntitySimulation::applyActionChanges();
|
||||
EntitySimulation::applyDynamicChanges();
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
|
||||
void init(EntityTreePointer tree, PhysicsEnginePointer engine, EntityEditPacketSender* packetSender);
|
||||
|
||||
virtual void addAction(EntityActionPointer action) override;
|
||||
virtual void applyActionChanges() override;
|
||||
virtual void addDynamic(EntityDynamicPointer dynamic) override;
|
||||
virtual void applyDynamicChanges() override;
|
||||
|
||||
virtual void takeEntitiesToDelete(VectorOfEntities& entitiesToDelete) override;
|
||||
|
||||
|
|
|
@ -548,42 +548,62 @@ void PhysicsEngine::setCharacterController(CharacterController* character) {
|
|||
}
|
||||
}
|
||||
|
||||
EntityActionPointer PhysicsEngine::getActionByID(const QUuid& actionID) const {
|
||||
if (_objectActions.contains(actionID)) {
|
||||
return _objectActions[actionID];
|
||||
EntityDynamicPointer PhysicsEngine::getDynamicByID(const QUuid& dynamicID) const {
|
||||
if (_objectDynamics.contains(dynamicID)) {
|
||||
return _objectDynamics[dynamicID];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PhysicsEngine::addAction(EntityActionPointer action) {
|
||||
assert(action);
|
||||
const QUuid& actionID = action->getID();
|
||||
if (_objectActions.contains(actionID)) {
|
||||
if (_objectActions[actionID] == action) {
|
||||
void PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) {
|
||||
assert(dynamic);
|
||||
const QUuid& dynamicID = dynamic->getID();
|
||||
if (_objectDynamics.contains(dynamicID)) {
|
||||
if (_objectDynamics[dynamicID] == dynamic) {
|
||||
return;
|
||||
}
|
||||
removeAction(action->getID());
|
||||
removeDynamic(dynamic->getID());
|
||||
}
|
||||
|
||||
_objectActions[actionID] = action;
|
||||
_objectDynamics[dynamicID] = dynamic;
|
||||
|
||||
// bullet needs a pointer to the action, but it doesn't use shared pointers.
|
||||
// bullet needs a pointer to the dynamic, but it doesn't use shared pointers.
|
||||
// is there a way to bump the reference count?
|
||||
ObjectAction* objectAction = static_cast<ObjectAction*>(action.get());
|
||||
_dynamicsWorld->addAction(objectAction);
|
||||
}
|
||||
|
||||
void PhysicsEngine::removeAction(const QUuid actionID) {
|
||||
if (_objectActions.contains(actionID)) {
|
||||
EntityActionPointer action = _objectActions[actionID];
|
||||
ObjectAction* objectAction = static_cast<ObjectAction*>(action.get());
|
||||
_dynamicsWorld->removeAction(objectAction);
|
||||
_objectActions.remove(actionID);
|
||||
if (dynamic->isAction()) {
|
||||
ObjectAction* objectAction = static_cast<ObjectAction*>(dynamic.get());
|
||||
_dynamicsWorld->addAction(objectAction);
|
||||
} else if (dynamic->isConstraint()) {
|
||||
ObjectConstraint* objectConstraint = static_cast<ObjectConstraint*>(dynamic.get());
|
||||
btTypedConstraint* constraint = objectConstraint->getConstraint();
|
||||
if (constraint) {
|
||||
_dynamicsWorld->addConstraint(constraint);
|
||||
} else {
|
||||
qDebug() << "PhysicsEngine::addDynamic of constraint failed"; // XXX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsEngine::forEachAction(std::function<void(EntityActionPointer)> actor) {
|
||||
QHashIterator<QUuid, EntityActionPointer> iter(_objectActions);
|
||||
void PhysicsEngine::removeDynamic(const QUuid dynamicID) {
|
||||
if (_objectDynamics.contains(dynamicID)) {
|
||||
EntityDynamicPointer dynamic = _objectDynamics[dynamicID];
|
||||
if (dynamic->isAction()) {
|
||||
ObjectAction* objectAction = static_cast<ObjectAction*>(dynamic.get());
|
||||
_dynamicsWorld->removeAction(objectAction);
|
||||
} else {
|
||||
ObjectConstraint* objectConstraint = static_cast<ObjectConstraint*>(dynamic.get());
|
||||
btTypedConstraint* constraint = objectConstraint->getConstraint();
|
||||
if (constraint) {
|
||||
_dynamicsWorld->removeConstraint(constraint);
|
||||
} else {
|
||||
qDebug() << "PhysicsEngine::removeDynamic of constraint failed"; // XXX
|
||||
}
|
||||
}
|
||||
_objectDynamics.remove(dynamicID);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsEngine::forEachDynamic(std::function<void(EntityDynamicPointer)> actor) {
|
||||
QHashIterator<QUuid, EntityDynamicPointer> iter(_objectDynamics);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
actor(iter.value());
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "ObjectMotionState.h"
|
||||
#include "ThreadSafeDynamicsWorld.h"
|
||||
#include "ObjectAction.h"
|
||||
#include "ObjectConstraint.h"
|
||||
|
||||
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
|
||||
|
||||
|
@ -84,10 +85,10 @@ public:
|
|||
|
||||
void dumpNextStats() { _dumpNextStats = true; }
|
||||
|
||||
EntityActionPointer getActionByID(const QUuid& actionID) const;
|
||||
void addAction(EntityActionPointer action);
|
||||
void removeAction(const QUuid actionID);
|
||||
void forEachAction(std::function<void(EntityActionPointer)> actor);
|
||||
EntityDynamicPointer getDynamicByID(const QUuid& dynamicID) const;
|
||||
void addDynamic(EntityDynamicPointer dynamic);
|
||||
void removeDynamic(const QUuid dynamicID);
|
||||
void forEachDynamic(std::function<void(EntityDynamicPointer)> actor);
|
||||
|
||||
private:
|
||||
void addObjectToDynamicsWorld(ObjectMotionState* motionState);
|
||||
|
@ -110,7 +111,7 @@ private:
|
|||
|
||||
ContactMap _contactMap;
|
||||
CollisionEvents _collisionEvents;
|
||||
QHash<QUuid, EntityActionPointer> _objectActions;
|
||||
QHash<QUuid, EntityDynamicPointer> _objectDynamics;
|
||||
std::vector<btRigidBody*> _activeStaticBodies;
|
||||
|
||||
glm::vec3 _originOffset;
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include <SimpleEntitySimulation.h>
|
||||
#include <EntityActionInterface.h>
|
||||
#include <EntityActionFactoryInterface.h>
|
||||
#include <EntityDynamicInterface.h>
|
||||
#include <EntityDynamicFactoryInterface.h>
|
||||
#include <WebEntityItem.h>
|
||||
#include <OctreeUtils.h>
|
||||
#include <render/Engine.h>
|
||||
|
@ -365,17 +365,17 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class TestActionFactory : public EntityActionFactoryInterface {
|
||||
class TestActionFactory : public EntityDynamicFactoryInterface {
|
||||
public:
|
||||
virtual EntityActionPointer factory(EntityActionType type,
|
||||
virtual EntityDynamicPointer factory(EntityDynamicType type,
|
||||
const QUuid& id,
|
||||
EntityItemPointer ownerEntity,
|
||||
QVariantMap arguments) override {
|
||||
return EntityActionPointer();
|
||||
return EntityDynamicPointer();
|
||||
}
|
||||
|
||||
|
||||
virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override {
|
||||
virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
@ -475,7 +475,7 @@ protected:
|
|||
public:
|
||||
//"/-17.2049,-8.08629,-19.4153/0,0.881994,0,-0.47126"
|
||||
static void setup() {
|
||||
DependencyManager::registerInheritance<EntityActionFactoryInterface, TestActionFactory>();
|
||||
DependencyManager::registerInheritance<EntityDynamicFactoryInterface, TestActionFactory>();
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
DependencyManager::registerInheritance<SpatialParentFinder, ParentFinder>();
|
||||
DependencyManager::set<tracing::Tracer>();
|
||||
|
|
Loading…
Reference in a new issue