fixed some input recorder design issue

This commit is contained in:
Dante Ruiz 2017-06-01 00:23:37 +01:00
parent 4a52f4090d
commit cca0fa6600
4 changed files with 111 additions and 47 deletions

View file

@ -42,8 +42,6 @@ enum class Action {
LEFT_HAND = NUM_COMBINED_AXES,
RIGHT_HAND,
LEFT_ARM,
RIGHT_ARM,
LEFT_FOOT,
RIGHT_FOOT,
HIPS,
@ -103,6 +101,8 @@ enum class Action {
// Bisected aliases for TRANSLATE_CAMERA_Z
BOOM_IN,
BOOM_OUT,
LEFT_ARM,
RIGHT_ARM,
NUM_ACTIONS,

View file

@ -9,7 +9,6 @@
#include "InputRecorder.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QFile>
#include <QDir>
@ -19,9 +18,12 @@
#include <QByteArray>
#include <QStandardPaths>
#include <PathUtils.h>
#include <QUrl>
#include <BuildInfo.h>
#include <GLMHelpers.h>
#include <DependencyManager.h>
#include "UserInputMapper.h"
QString SAVE_DIRECTORY = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + BuildInfo::MODIFIED_ORGANIZATION + "/" + BuildInfo::INTERFACE_NAME + "/hifi-input-recordings/";
QString FILE_PREFIX_NAME = "input-recording-";
@ -108,6 +110,7 @@ namespace controller {
QJsonDocument saveData(object);
QByteArray compressedData = qCompress(saveData.toJson(QJsonDocument::Compact));
saveFile.write(compressedData);
saveFile.close();
}
QJsonObject openFile(const QString& file, bool& status) {
@ -122,6 +125,7 @@ namespace controller {
QJsonDocument jsonDoc = QJsonDocument::fromJson(compressedData);
object = jsonDoc.object();
status = true;
openFile.close();
return object;
}
@ -146,31 +150,43 @@ namespace controller {
_actionStateList.clear();
}
void InputRecorder::saveRecording() {
QJsonObject InputRecorder::recordDataToJson() {
QJsonObject data;
data["frameCount"] = _framesRecorded;
data["version"] = "1.0";
QJsonArray actionArrayList;
QJsonArray poseArrayList;
for(const ActionStates actionState: _actionStateList) {
QJsonArray actionArray;
for (const float value: actionState) {
actionArray.append(value);
for (const auto action: actionState) {
QJsonObject actionJson;
actionJson["name"] = action.first;
actionJson["value"] = action.second;
actionArray.append(actionJson);
}
actionArrayList.append(actionArray);
}
for (const PoseStates poseState: _poseStateList) {
QJsonArray poseArray;
for (const Pose pose: poseState) {
poseArray.append(poseToJsonObject(pose));
for (const auto pose: poseState) {
QJsonObject poseJson;
poseJson["name"] = pose.first;
poseJson["pose"] = poseToJsonObject(pose.second);
poseArray.append(poseJson);
}
poseArrayList.append(poseArray);
}
data["actionList"] = actionArrayList;
data["poseList"] = poseArrayList;
exportToFile(data);
return data;
}
void InputRecorder::saveRecording() {
exportToFile(recordDataToJson());
}
void InputRecorder::loadRecording(const QString& path) {
@ -181,8 +197,8 @@ namespace controller {
resetFrame();
_poseStateList.clear();
_actionStateList.clear();
QString filePath = path;
filePath.remove(0,8);
QUrl urlPath(path);
QString filePath = urlPath.toLocalFile();
QFileInfo info(filePath);
QString extension = info.suffix();
if (extension != "gz") {
@ -190,8 +206,9 @@ namespace controller {
return;
}
bool success = false;
QJsonObject data = openFile(info.absoluteFilePath(), success);
if (success) {
QJsonObject data = openFile(filePath, success);
auto keyValue = data.find("version");
if (success && keyValue != data.end()) {
_framesRecorded = data["frameCount"].toInt();
QJsonArray actionArrayList = data["actionList"].toArray();
QJsonArray poseArrayList = data["poseList"].toArray();
@ -199,25 +216,71 @@ namespace controller {
for (int actionIndex = 0; actionIndex < actionArrayList.size(); actionIndex++) {
QJsonArray actionState = actionArrayList[actionIndex].toArray();
for (int index = 0; index < actionState.size(); index++) {
_currentFrameActions[index] = actionState[index].toDouble();
QJsonObject actionObject = actionState[index].toObject();;
_currentFrameActions[actionObject["name"].toString()] = actionObject["value"].toDouble();
}
_actionStateList.push_back(_currentFrameActions);
_currentFrameActions = ActionStates(toInt(Action::NUM_ACTIONS));
_currentFrameActions.clear();
}
for (int poseIndex = 0; poseIndex < poseArrayList.size(); poseIndex++) {
QJsonArray poseState = poseArrayList[poseIndex].toArray();
for (int index = 0; index < poseState.size(); index++) {
_currentFramePoses[index] = jsonObjectToPose(poseState[index].toObject());
QJsonObject poseObject = poseState[index].toObject();
_currentFramePoses[poseObject["name"].toString()] = jsonObjectToPose(poseObject["pose"].toObject());
}
_poseStateList.push_back(_currentFramePoses);
_currentFramePoses = PoseStates(toInt(Action::NUM_ACTIONS));
_currentFramePoses.clear();
}
} else if (success) {
//convert recording to new reacording standard and rewrite file
auto userInputMapper = DependencyManager::get<UserInputMapper>();
_framesRecorded = data["frameCount"].toInt();
QJsonArray actionArrayList = data["actionList"].toArray();
QJsonArray poseArrayList = data["poseList"].toArray();
for (int actionIndex = 0; actionIndex < actionArrayList.size(); actionIndex++) {
QJsonArray actionState = actionArrayList[actionIndex].toArray();
for (int index = 0; index < actionState.size(); index++) {
QString actionName = userInputMapper->getActionName(Action(index));
_currentFrameActions[actionName] = actionState[index].toDouble();
}
_actionStateList.push_back(_currentFrameActions);
_currentFrameActions.clear();
}
for (int poseIndex = 0; poseIndex < poseArrayList.size(); poseIndex++) {
QJsonArray poseState = poseArrayList[poseIndex].toArray();
for (int index = 0; index < poseState.size(); index++) {
QString actionName = userInputMapper->getActionName(Action(index));
_currentFramePoses[actionName] = jsonObjectToPose(poseState[index].toObject());
}
_poseStateList.push_back(_currentFramePoses);
_currentFramePoses.clear();
}
convertFile(filePath);
}
_loading = false;
}
void InputRecorder::convertFile(const QString& path) {
if (!QDir(SAVE_DIRECTORY).exists()) {
QDir().mkdir(SAVE_DIRECTORY);
}
QJsonObject data = recordDataToJson();
QFile saveFile (path);
if (!saveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qWarning() << "could not open file: " << path;
return;
}
QJsonDocument saveData(data);
QByteArray compressedData = qCompress(saveData.toJson(QJsonDocument::Compact));
saveFile.write(compressedData);
}
void InputRecorder::stopRecording() {
_recording = false;
_framesRecorded = (int)_actionStateList.size();
@ -234,41 +297,36 @@ namespace controller {
_playCount = 0;
}
void InputRecorder::setActionState(controller::Action action, float value) {
void InputRecorder::setActionState(const QString& action, float value) {
if (_recording) {
_currentFrameActions[toInt(action)] += value;
_currentFrameActions[action] += value;
}
}
void InputRecorder::setActionState(controller::Action action, const controller::Pose pose) {
void InputRecorder::setActionState(const QString& action, const controller::Pose& pose) {
if (_recording) {
_currentFramePoses[toInt(action)] = pose;
_currentFramePoses[action] = pose;
}
}
void InputRecorder::resetFrame() {
if (_recording) {
for(auto& channel : _currentFramePoses) {
channel = Pose();
}
for(auto& channel : _currentFrameActions) {
channel = 0.0f;
}
_currentFramePoses.clear();
_currentFrameActions.clear();
}
}
float InputRecorder::getActionState(controller::Action action) {
float InputRecorder::getActionState(const QString& action) {
if (_actionStateList.size() > 0 ) {
return _actionStateList[_playCount][toInt(action)];
return _actionStateList[_playCount][action];
}
return 0.0f;
}
controller::Pose InputRecorder::getPoseState(controller::Action action) {
controller::Pose InputRecorder::getPoseState(const QString& action) {
if (_poseStateList.size() > 0) {
return _poseStateList[_playCount][toInt(action)];
return _poseStateList[_playCount][action];
}
return Pose();

View file

@ -12,8 +12,10 @@
#include <mutex>
#include <atomic>
#include <vector>
#include <map>
#include <QString>
#include <QJsonObject>
#include "Pose.h"
#include "Actions.h"
@ -21,8 +23,8 @@
namespace controller {
class InputRecorder {
public:
using PoseStates = std::vector<Pose>;
using ActionStates = std::vector<float>;
using PoseStates = std::map<QString, Pose>;
using ActionStates = std::map<QString, float>;
InputRecorder();
~InputRecorder();
@ -31,6 +33,7 @@ namespace controller {
void saveRecording();
void loadRecording(const QString& path);
void convertFile(const QString& path);
void startRecording();
void startPlayback();
void stopPlayback();
@ -40,20 +43,21 @@ namespace controller {
void resetFrame();
bool isRecording() { return _recording; }
bool isPlayingback() { return (_playback && !_loading); }
void setActionState(controller::Action action, float value);
void setActionState(controller::Action action, const controller::Pose pose);
float getActionState(controller::Action action);
controller::Pose getPoseState(controller::Action action);
void setActionState(const QString& action, float value);
void setActionState(const QString& action, const controller::Pose& pose);
float getActionState(const QString& action);
controller::Pose getPoseState(const QString& action);
QString getSaveDirectory();
void frameTick();
private:
QJsonObject recordDataToJson();
bool _recording { false };
bool _playback { false };
bool _loading { false };
std::vector<PoseStates> _poseStateList = std::vector<PoseStates>();
std::vector<ActionStates> _actionStateList = std::vector<ActionStates>();
PoseStates _currentFramePoses = PoseStates(toInt(Action::NUM_ACTIONS));
ActionStates _currentFrameActions = ActionStates(toInt(Action::NUM_ACTIONS));
PoseStates _currentFramePoses;
ActionStates _currentFrameActions;
int _framesRecorded { 0 };
int _playCount { 0 };

View file

@ -17,31 +17,33 @@ using namespace controller;
void ActionEndpoint::apply(float newValue, const Pointer& source) {
InputRecorder* inputRecorder = InputRecorder::getInstance();
auto userInputMapper = DependencyManager::get<UserInputMapper>();
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
if(inputRecorder->isPlayingback()) {
newValue = inputRecorder->getActionState(Action(_input.getChannel()));
newValue = inputRecorder->getActionState(actionName);
}
_currentValue += newValue;
if (_input != Input::INVALID_INPUT) {
auto userInputMapper = DependencyManager::get<UserInputMapper>();
userInputMapper->deltaActionState(Action(_input.getChannel()), newValue);
}
inputRecorder->setActionState(Action(_input.getChannel()), newValue);
inputRecorder->setActionState(actionName, newValue);
}
void ActionEndpoint::apply(const Pose& value, const Pointer& source) {
_currentPose = value;
InputRecorder* inputRecorder = InputRecorder::getInstance();
inputRecorder->setActionState(Action(_input.getChannel()), _currentPose);
auto userInputMapper = DependencyManager::get<UserInputMapper>();
QString actionName = userInputMapper->getActionName(Action(_input.getChannel()));
inputRecorder->setActionState(actionName, _currentPose);
if (inputRecorder->isPlayingback()) {
_currentPose = inputRecorder->getPoseState(Action(_input.getChannel()));
_currentPose = inputRecorder->getPoseState(actionName);
}
if (!_currentPose.isValid()) {
return;
}
if (_input != Input::INVALID_INPUT) {
auto userInputMapper = DependencyManager::get<UserInputMapper>();
userInputMapper->setActionState(Action(_input.getChannel()), _currentPose);
}
}