first cut at exposing clipboard support to JavaScript

This commit is contained in:
ZappoMan 2014-02-19 00:10:16 -08:00
parent 866b3dbb63
commit bf814410ac
6 changed files with 142 additions and 15 deletions

View file

@ -62,6 +62,7 @@
#include <VoxelSceneStats.h>
#include "Application.h"
#include "ClipboardScriptingInterface.h"
#include "DataServerClient.h"
#include "InterfaceVersion.h"
#include "Menu.h"
@ -1686,6 +1687,10 @@ bool Application::sendVoxelsOperation(OctreeElement* element, void* extraData) {
}
void Application::exportVoxels() {
exportVoxels(_mouseVoxel);
}
void Application::exportVoxels(const VoxelDetail& sourceVoxel) {
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString suggestedName = desktopLocation.append("/voxels.svo");
@ -1693,7 +1698,7 @@ void Application::exportVoxels() {
tr("Sparse Voxel Octree Files (*.svo)"));
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
const char* fileName = fileNameAscii.data();
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
if (selectedNode) {
VoxelTree exportTree;
_voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true);
@ -1721,11 +1726,19 @@ void Application::importVoxels() {
}
void Application::cutVoxels() {
copyVoxels();
deleteVoxelUnderCursor();
cutVoxels(_mouseVoxel);
}
void Application::cutVoxels(const VoxelDetail& sourceVoxel) {
copyVoxels(sourceVoxel);
deleteVoxelAt(sourceVoxel);
}
void Application::copyVoxels() {
copyVoxels(_mouseVoxel);
}
void Application::copyVoxels(const VoxelDetail& sourceVoxel) {
// switch to and clear the clipboard first...
_sharedVoxelSystem.killLocalVoxels();
if (_sharedVoxelSystem.getTree() != &_clipboard) {
@ -1734,7 +1747,7 @@ void Application::copyVoxels() {
}
// then copy onto it if there is something to copy
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
if (selectedNode) {
_voxels.copySubTreeIntoNewTree(selectedNode, &_sharedVoxelSystem, true);
}
@ -1756,8 +1769,12 @@ void Application::pasteVoxelsToOctalCode(const unsigned char* octalCodeDestinati
}
void Application::pasteVoxels() {
pasteVoxels(_mouseVoxel);
}
void Application::pasteVoxels(const VoxelDetail& sourceVoxel) {
unsigned char* calculatedOctCode = NULL;
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
// voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a
@ -1766,7 +1783,7 @@ void Application::pasteVoxels() {
if (selectedNode) {
octalCodeDestination = selectedNode->getOctalCode();
} else {
octalCodeDestination = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
octalCodeDestination = calculatedOctCode = pointToVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
}
pasteVoxelsToOctalCode(octalCodeDestination);
@ -3789,18 +3806,27 @@ bool Application::maybeEditVoxelUnderCursor() {
}
void Application::deleteVoxelUnderCursor() {
if (_mouseVoxel.s != 0) {
deleteVoxelAt(_mouseVoxel);
}
void Application::deleteVoxels(const VoxelDetail& voxel) {
deleteVoxelAt(voxel);
}
void Application::deleteVoxelAt(const VoxelDetail& voxel) {
if (voxel.s != 0) {
// sending delete to the server is sufficient, server will send new version so we see updates soon enough
_voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, _mouseVoxel);
_voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel);
// delete it locally to see the effect immediately (and in case no voxel server is present)
_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
_voxels.deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
}
// remember the position for drag detection
_justEditedVoxel = true;
}
void Application::eyedropperVoxelUnderCursor() {
VoxelTreeElement* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
if (selectedNode && selectedNode->isColored()) {
@ -4138,6 +4164,10 @@ void Application::loadScript(const QString& fileNameString) {
scriptEngine->registerGlobalObject("Camera", cameraScriptable);
connect(scriptEngine, SIGNAL(finished(const QString&)), cameraScriptable, SLOT(deleteLater()));
ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface();
scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable);
connect(scriptEngine, SIGNAL(finished(const QString&)), clipboardScriptable, SLOT(deleteLater()));
scriptEngine->registerGlobalObject("Overlays", &_overlays);
QThread* workerThread = new QThread(this);

View file

@ -222,13 +222,19 @@ public slots:
void nodeKilled(SharedNodePointer node);
void packetSent(quint64 length);
void exportVoxels();
void importVoxels();
void cutVoxels();
void copyVoxels();
void pasteVoxels();
void nudgeVoxels();
void deleteVoxels();
void exportVoxels();
void importVoxels();
void nudgeVoxels();
void cutVoxels(const VoxelDetail& sourceVoxel);
void copyVoxels(const VoxelDetail& sourceVoxel);
void pasteVoxels(const VoxelDetail& sourceVoxel);
void deleteVoxels(const VoxelDetail& sourceVoxel);
void exportVoxels(const VoxelDetail& sourceVoxel);
void setRenderVoxels(bool renderVoxels);
void doKillLocalVoxels();
@ -322,6 +328,7 @@ private:
bool maybeEditVoxelUnderCursor();
void deleteVoxelUnderCursor();
void deleteVoxelAt(const VoxelDetail& voxel);
void eyedropperVoxelUnderCursor();
void setMenuShortcutsEnabled(bool enabled);

View file

@ -0,0 +1,59 @@
//
// ClipboardScriptingInterface.cpp
// interface
//
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
#include "Application.h"
#include "ClipboardScriptingInterface.h"
ClipboardScriptingInterface::ClipboardScriptingInterface() {
}
void ClipboardScriptingInterface::cutVoxels(float x, float y, float z, float s) {
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
y / (float)TREE_SCALE,
z / (float)TREE_SCALE,
s / (float)TREE_SCALE };
Application::getInstance()->cutVoxels(sourceVoxel);
}
void ClipboardScriptingInterface::copyVoxels(float x, float y, float z, float s) {
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
y / (float)TREE_SCALE,
z / (float)TREE_SCALE,
s / (float)TREE_SCALE };
Application::getInstance()->copyVoxels(sourceVoxel);
}
void ClipboardScriptingInterface::pasteVoxels(float x, float y, float z, float s) {
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
y / (float)TREE_SCALE,
z / (float)TREE_SCALE,
s / (float)TREE_SCALE };
Application::getInstance()->pasteVoxels(sourceVoxel);
}
void ClipboardScriptingInterface::deleteVoxels(float x, float y, float z, float s) {
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
y / (float)TREE_SCALE,
z / (float)TREE_SCALE,
s / (float)TREE_SCALE };
Application::getInstance()->deleteVoxels(sourceVoxel);
}
void ClipboardScriptingInterface::exportVoxels(float x, float y, float z, float s) {
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
y / (float)TREE_SCALE,
z / (float)TREE_SCALE,
s / (float)TREE_SCALE };
Application::getInstance()->exportVoxels(sourceVoxel);
}
void ClipboardScriptingInterface::importVoxels() {
Application::getInstance()->importVoxels();
}

View file

@ -0,0 +1,31 @@
//
// ClipboardScriptingInterface.h
// interface
//
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
// Scriptable interface for the Application clipboard
//
#ifndef __interface__Clipboard__
#define __interface__Clipboard__
#include <QObject>
#include <VoxelDetail.h>
class ClipboardScriptingInterface : public QObject {
Q_OBJECT
public:
ClipboardScriptingInterface();
public slots:
void cutVoxels(float x, float y, float z, float s);
void copyVoxels(float x, float y, float z, float s);
void pasteVoxels(float x, float y, float z, float s);
void deleteVoxels(float x, float y, float z, float s);
void exportVoxels(float x, float y, float z, float s);
void importVoxels();
};
#endif // __interface__Clipboard__

View file

@ -22,7 +22,7 @@
/// PacketTypeVoxelSet, PacketTypeVoxelSetDestructive, or PacketTypeVoxelErase. The buffer is returned to caller becomes
/// responsibility of caller and MUST be deleted by caller.
bool createVoxelEditMessage(PacketType command, short int sequence,
int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) {
int voxelCount, const VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut) {
bool success = true; // assume the best
int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now
@ -102,7 +102,7 @@ bool encodeVoxelEditMessageDetails(PacketType, int voxelCount, VoxelDetail* voxe
return success;
}
void VoxelEditPacketSender::sendVoxelEditMessage(PacketType type, VoxelDetail& detail) {
void VoxelEditPacketSender::sendVoxelEditMessage(PacketType type, const VoxelDetail& detail) {
// allows app to disable sending if for example voxels have been disabled
if (!_shouldSend) {
return; // bail early

View file

@ -19,7 +19,7 @@ class VoxelEditPacketSender : public OctreeEditPacketSender {
Q_OBJECT
public:
/// Send voxel edit message immediately
void sendVoxelEditMessage(PacketType type, VoxelDetail& detail);
void sendVoxelEditMessage(PacketType type, const VoxelDetail& detail);
/// Queues a single voxel edit message. Will potentially send a pending multi-command packet. Determines which voxel-server
/// node or nodes the packet should be sent to. Can be called even before voxel servers are known, in which case up to