From e5e200345b93bcd42af1eb2102e7857e0f383470 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 31 May 2013 11:52:18 -0700 Subject: [PATCH] more work on copy and paste --- interface/src/Application.cpp | 67 ++++++++++++++++++++++++++---- interface/src/Application.h | 2 + libraries/shared/src/OctalCode.cpp | 21 +++++++++- libraries/shared/src/OctalCode.h | 7 ++-- libraries/voxels/src/VoxelTree.cpp | 22 ++++++++-- 5 files changed, 102 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b6aba80c06..5395bfa54f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "Application.h" #include "InterfaceConfig.h" @@ -1319,26 +1320,76 @@ void Application::copyVoxels() { if (selectedNode) { selectedNode->printDebugDetails("selected voxel"); _voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true); + + // debug tree + _clipboardTree.printTreeForDebugging(_clipboardTree.rootNode); } } +const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500; +struct SendVoxelsOperataionArgs { + unsigned char* newBaseOctCode; + unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE]; + int bufferInUse; + +}; + void Application::pasteVoxels() { VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); printf("pasteVoxels() _mouseVoxel: %f,%f,%f-%f \n", _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); if (selectedNode) { //selectedNode->printDebugDetails("selected voxel"); - // First, create a temporary Paste Tree - VoxelTree _temporaryPasteTree; + // Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to + // the server as an set voxel message, this will also rebase the voxels to the new location + SendVoxelsOperataionArgs args; + args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; + unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)]; + *sequenceAt = 0; + args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence + args.newBaseOctCode = selectedNode->getOctalCode(); + _clipboardTree.recurseTreeWithOperation(sendVoxelsOperataion, &args); - // Create a destination node to paste into - _temporaryPasteTree.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, 0, 0, 0); - - // Paste into the temporary tree - destinationNode = _temporaryPasteTree.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - _temporaryPasteTree.copyFromTreeIntoSubTree(&_clipboardTree, destinationNode); + // If we have voxels left in the packet, then send the packet + if (args.bufferInUse > 1) { + AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1); + } } } + +bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) { + SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData; + if (node->isColored()) { + const int SIZE_OF_COLOR_DATA = 3; + const int RED_INDEX = 0; + const int GREEN_INDEX = 1; + const int BLUE_INDEX = 2; + unsigned char* nodeOctalCode = node->getOctalCode(); + printOctalCode(nodeOctalCode); + unsigned char* rebasedCodeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); + printOctalCode(rebasedCodeColorBuffer); + int rebasedCodeLength = numberOfThreeBitSectionsInCode(rebasedCodeColorBuffer); + int bytesInRebasedCode = bytesRequiredForCodeLength(rebasedCodeLength); + int codeAndColorLength = bytesInRebasedCode + SIZE_OF_COLOR_DATA; + + // copy the colors over + rebasedCodeColorBuffer[bytesInRebasedCode + RED_INDEX ] = node->getColor()[RED_INDEX ]; + rebasedCodeColorBuffer[bytesInRebasedCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX]; + rebasedCodeColorBuffer[bytesInRebasedCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ]; + + // if we have room don't have room in the buffer, then send the previously generated message first + if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) { + AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1); + args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence + } + + // copy this node's code color details into our buffer. + memcpy(&args->messageBuffer[args->bufferInUse], rebasedCodeColorBuffer, codeAndColorLength); + args->bufferInUse += codeAndColorLength; + } + return true; // keep going +} + void Application::initMenu() { QMenuBar* menuBar = new QMenuBar(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9a6d02ecc0..7761d9a84b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -160,6 +160,8 @@ private slots: void pasteVoxels(); private: + + static bool sendVoxelsOperataion(VoxelNode* node, void* extraData); void initMenu(); void updateFrustumRenderModeAction(); diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index f331545b33..150789bec8 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -224,6 +224,25 @@ unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels) { return newCode; } -unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode) { +unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, bool includeColorSpace) { + int oldCodeLength = numberOfThreeBitSectionsInCode(originalOctalCode); + int newParentCodeLength = numberOfThreeBitSectionsInCode(newParentOctalCode); + int newCodeLength = newParentCodeLength + oldCodeLength; + const int COLOR_SPACE = 3; + int bufferLength = newCodeLength + (includeColorSpace ? COLOR_SPACE : 0); + unsigned char* newCode = new unsigned char[bufferLength]; + *newCode = newCodeLength; // set the length byte + + // copy parent code section first + for (int sectionFromParent = 0; sectionFromParent < newParentCodeLength; sectionFromParent++) { + char sectionValue = getOctalCodeSectionValue(newParentOctalCode, sectionFromParent); + setOctalCodeSectionValue(newCode, sectionFromParent, sectionValue); + } + // copy original code section next + for (int sectionFromOriginal = 0; sectionFromOriginal < oldCodeLength; sectionFromOriginal++) { + char sectionValue = getOctalCodeSectionValue(originalOctalCode, sectionFromOriginal); + setOctalCodeSectionValue(newCode, sectionFromOriginal + newParentCodeLength, sectionValue); + } + return newCode; } diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index 1849989cc3..bfed24a87c 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -16,11 +16,10 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes); bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode); int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode); unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber); - -unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); -unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode); int numberOfThreeBitSectionsInCode(unsigned char * octalCode); - +unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels); +unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, + bool includeColorSpace = false); // Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return // but other than that these do the same thing. diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 562cfcc88c..704c15e4db 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -878,9 +878,22 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned } // write the octal code - int codeLength = bytesRequiredForCodeLength(*node->getOctalCode()); - memcpy(outputBuffer,node->getOctalCode(),codeLength); - + int codeLength; + if (chopLevels) { + unsigned char* newCode = chopOctalCode(node->getOctalCode(), chopLevels); + if (newCode) { + codeLength = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(newCode)); + memcpy(outputBuffer, newCode, codeLength); + delete newCode; + } else { + codeLength = 1; // chopped to root! + *outputBuffer = 0; // root + } + } else { + codeLength = bytesRequiredForCodeLength(*node->getOctalCode()); + memcpy(outputBuffer, node->getOctalCode(), codeLength); + } + outputBuffer += codeLength; // move the pointer bytesWritten += codeLength; // keep track of byte count availableBytes -= codeLength; // keep track or remaining space @@ -1183,6 +1196,7 @@ void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinat if (rebaseToRoot) { chopLevels = numberOfThreeBitSectionsInCode(startNode->getOctalCode()); + printLog("copySubTreeIntoNewTree()...rebaseToRoot=true, chopLevels=%d\n", chopLevels); } static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static @@ -1218,7 +1232,7 @@ void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destin MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); // ask destination tree to read the bitstream - readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS); + readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS,destinationNode); } }