From 2b65f1d26a6bbf7f94831aed6a59875e74532039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 20 Nov 2015 01:07:31 +0100 Subject: [PATCH] Refactored layers system to work better as DefinitionNode It now features undo/redo of layer creation and removal --- src/definition/CloudLayerDefinition.cpp | 7 +- src/definition/CloudLayerDefinition.h | 2 +- src/definition/CloudsDefinition.cpp | 9 +- src/definition/DefinitionDiff.cpp | 3 + src/definition/DefinitionDiff.h | 1 + src/definition/DefinitionNode.cpp | 2 + src/definition/DiffManager.cpp | 31 +++-- src/definition/DiffManager.h | 7 + src/definition/Layers.cpp | 157 ++++++++++----------- src/definition/Layers.h | 60 +++++--- src/definition/LayersDiff.cpp | 32 +++++ src/definition/LayersDiff.h | 47 +++++++ src/definition/TextureLayerDefinition.cpp | 4 +- src/definition/TextureLayerDefinition.h | 2 +- src/definition/TexturesDefinition.cpp | 62 ++++----- src/definition/TimeManager.cpp | 2 +- src/definition/definition_global.h | 1 + src/interface/commandline/tests.cpp | 17 +-- src/render/software/CloudsRenderer.cpp | 10 +- src/render/software/TexturesRenderer.cpp | 6 +- src/system/FileSystem.cpp | 3 + src/system/PackStream.cpp | 17 +++ src/system/PackStream.h | 10 ++ src/tests/Layers_Test.cpp | 159 +++++++++++++++++----- 24 files changed, 444 insertions(+), 207 deletions(-) create mode 100644 src/definition/LayersDiff.cpp create mode 100644 src/definition/LayersDiff.h diff --git a/src/definition/CloudLayerDefinition.cpp b/src/definition/CloudLayerDefinition.cpp index 09f0338..508dd28 100644 --- a/src/definition/CloudLayerDefinition.cpp +++ b/src/definition/CloudLayerDefinition.cpp @@ -6,7 +6,8 @@ #include "PackStream.h" #include "FloatNode.h" -CloudLayerDefinition::CloudLayerDefinition(DefinitionNode *parent) : DefinitionNode(parent, "layer", "cloudlayer") { +CloudLayerDefinition::CloudLayerDefinition(DefinitionNode *parent, const std::string &name) + : DefinitionNode(parent, name, "cloudlayer") { type = CIRRUS; altitude = 0.5; scaling = 0.5; @@ -20,13 +21,13 @@ CloudLayerDefinition::~CloudLayerDefinition() { } CloudLayerDefinition *CloudLayerDefinition::newCopy(const CloudLayerDefinition &other, DefinitionNode *parent) { - CloudLayerDefinition *layer = new CloudLayerDefinition(parent); + CloudLayerDefinition *layer = new CloudLayerDefinition(parent, other.getName()); other.copy(layer); return layer; } CloudLayerDefinition *CloudLayerDefinition::newCopy(DefinitionNode *parent) const { - CloudLayerDefinition *layer = new CloudLayerDefinition(parent); + CloudLayerDefinition *layer = new CloudLayerDefinition(parent, getName()); copy(layer); return layer; } diff --git a/src/definition/CloudLayerDefinition.h b/src/definition/CloudLayerDefinition.h index 2afe919..d9c0918 100644 --- a/src/definition/CloudLayerDefinition.h +++ b/src/definition/CloudLayerDefinition.h @@ -12,7 +12,7 @@ namespace definition { class DEFINITIONSHARED_EXPORT CloudLayerDefinition : public DefinitionNode { public: - CloudLayerDefinition(DefinitionNode *parent); + CloudLayerDefinition(DefinitionNode *parent, const std::string &name); virtual ~CloudLayerDefinition(); inline const NoiseState &getNoiseState() const { diff --git a/src/definition/CloudsDefinition.cpp b/src/definition/CloudsDefinition.cpp index 058d777..a73595a 100644 --- a/src/definition/CloudsDefinition.cpp +++ b/src/definition/CloudsDefinition.cpp @@ -2,8 +2,8 @@ #include "CloudLayerDefinition.h" -static DefinitionNode *_layerConstructor(Layers *parent) { - return new CloudLayerDefinition(parent); +static DefinitionNode *_layerConstructor(Layers *parent, const std::string &name) { + return new CloudLayerDefinition(parent, name); } CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) { @@ -13,9 +13,8 @@ void CloudsDefinition::applyPreset(CloudsPreset preset) { clear(); if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) { - CloudLayerDefinition *layer = new CloudLayerDefinition(this); - layer->type = CloudLayerDefinition::STRATOCUMULUS; - layer->setName("Strato-cumulus"); + CloudLayerDefinition layer(NULL, "Strato-cumulus"); + layer.type = CloudLayerDefinition::STRATOCUMULUS; addLayer(layer); } } diff --git a/src/definition/DefinitionDiff.cpp b/src/definition/DefinitionDiff.cpp index 7a787bd..df06a3b 100644 --- a/src/definition/DefinitionDiff.cpp +++ b/src/definition/DefinitionDiff.cpp @@ -4,3 +4,6 @@ DefinitionDiff::DefinitionDiff(const DefinitionNode *node) : type_name(node->getTypeName()), path(node->getPath()) { } + +DefinitionDiff::~DefinitionDiff() { +} diff --git a/src/definition/DefinitionDiff.h b/src/definition/DefinitionDiff.h index 01b20bb..6f90bc2 100644 --- a/src/definition/DefinitionDiff.h +++ b/src/definition/DefinitionDiff.h @@ -14,6 +14,7 @@ namespace definition { class DEFINITIONSHARED_EXPORT DefinitionDiff { public: DefinitionDiff(const DefinitionNode *node); + virtual ~DefinitionDiff(); inline const std::string &getTypeName() const { return type_name; diff --git a/src/definition/DefinitionNode.cpp b/src/definition/DefinitionNode.cpp index af999b4..079e832 100644 --- a/src/definition/DefinitionNode.cpp +++ b/src/definition/DefinitionNode.cpp @@ -248,5 +248,7 @@ void DefinitionNode::addDiff(const DefinitionDiff *diff) { if (root && root->diffs) { root->diffs->addDiff(this, diff); + } else { + delete diff; } } diff --git a/src/definition/DiffManager.cpp b/src/definition/DiffManager.cpp index e841262..5e93d2a 100644 --- a/src/definition/DiffManager.cpp +++ b/src/definition/DiffManager.cpp @@ -4,6 +4,7 @@ #include "DefinitionNode.h" #include "DefinitionDiff.h" #include "DefinitionWatcher.h" +#include "Logs.h" DiffManager::DiffManager(DefinitionNode *tree) : tree(tree) { undone = 0; @@ -46,16 +47,21 @@ void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff) { void DiffManager::undo() { if (undone < (int)diffs.size()) { - undone++; - const DefinitionDiff *diff = diffs[diffs.size() - undone]; + const DefinitionDiff *diff = diffs[diffs.size() - undone - 1]; // Obtain the node by path and reverse apply diff on it DefinitionNode *node = tree->findByPath(diff->getPath()); - node->applyDiff(diff, true); + if (node) { + undone++; - for (auto watcher : watchers[node]) { - // FIXME Reverse diff - watcher->nodeChanged(node, diff); + node->applyDiff(diff, true); + + for (auto watcher : watchers[node]) { + // FIXME Reverse diff + watcher->nodeChanged(node, diff); + } + } else { + Logs::error() << "Can't find node to undo diff : " << diff->getPath() << std::endl; } } } @@ -63,14 +69,19 @@ void DiffManager::undo() { void DiffManager::redo() { if (undone > 0) { const DefinitionDiff *diff = diffs[diffs.size() - undone]; - undone--; // Obtain the node by path and re-apply diff on it DefinitionNode *node = tree->findByPath(diff->getPath()); - node->applyDiff(diff); + if (node) { + undone--; - for (auto watcher : watchers[node]) { - watcher->nodeChanged(node, diff); + node->applyDiff(diff); + + for (auto watcher : watchers[node]) { + watcher->nodeChanged(node, diff); + } + } else { + Logs::error() << "Can't find node to redo diff : " << diff->getPath() << std::endl; } } } diff --git a/src/definition/DiffManager.h b/src/definition/DiffManager.h index ba92514..8bc4a43 100644 --- a/src/definition/DiffManager.h +++ b/src/definition/DiffManager.h @@ -19,6 +19,13 @@ class DEFINITIONSHARED_EXPORT DiffManager { DiffManager(DefinitionNode *tree); ~DiffManager(); + /** + * Get the total number of diff stored. + */ + inline int getDiffCount(int include_undone = true) { + return include_undone ? diffs.size() : diffs.size() - undone; + } + /** * Add a watcher for a specific node. * diff --git a/src/definition/Layers.cpp b/src/definition/Layers.cpp index d08a258..3ace25a 100644 --- a/src/definition/Layers.cpp +++ b/src/definition/Layers.cpp @@ -2,15 +2,15 @@ #include "PackStream.h" #include "Logs.h" +#include "LayersDiff.h" Layers::Layers(DefinitionNode *parent, const std::string &name, LayerConstructor layer_constructor) : DefinitionNode(parent, name, "layers" + name), layer_constructor(layer_constructor) { max_layer_count = 100; - null_layer = layer_constructor(this); + null_layer = layer_constructor(this, "#NULL#"); } Layers::~Layers() { - clear(); delete null_layer; } @@ -28,16 +28,12 @@ void Layers::load(PackStream *stream) { int layer_count; stream->read(&layer_count); - if (layer_count > max_layer_count) { - layer_count = max_layer_count; - } clear(); for (int i = 0; i < layer_count; i++) { - int position = addLayer(); - if (position >= 0) { - layers[position]->setName(stream->readString()); - layers[position]->load(stream); - } + DefinitionNode *layer = layer_constructor(this, stream->readString()); + layer->load(stream); + addLayer(*layer); + delete layer; } } @@ -53,24 +49,18 @@ void Layers::copy(DefinitionNode *destination_) const { null_layer->copy(destination->null_layer); for (auto layer : layers) { - int position = destination->addLayer(); - DefinitionNode *new_layer = destination->getLayer(position); - layer->copy(new_layer); + destination->addLayer(*layer); } } -Layers *Layers::newCopy() const { - Layers *result = new Layers(NULL, getName(), layer_constructor); - copy(result); - return result; -} - void Layers::setMaxLayerCount(int max_layer_count) { this->max_layer_count = max_layer_count; - // TODO Delete overlimit layers ? + for (int i = getLayerCount(); i > max_layer_count; i--) { + removeLayer(i - 1); + } } -int Layers::count() const { +int Layers::getLayerCount() const { return layers.size(); } @@ -84,82 +74,79 @@ DefinitionNode *Layers::getLayer(int position) const { } } -int Layers::findLayer(DefinitionNode *layer) const { - int i = 0; - for (auto it : layers) { - if (it == layer) { - return i; +bool Layers::applyDiff(const DefinitionDiff *diff, bool backward) { + auto layer_diff = (LayersDiff *)diff; + LayersDiff::LayersDiffOp op = layer_diff->getOp(); + int layer_count = getLayerCount(); + + if ((not backward and op == LayersDiff::LAYER_ADDED) or (backward and op == LayersDiff::LAYER_REMOVED)) { + if (layer_count >= max_layer_count) { + Logs::warning() << "Add layer ignored because limit of " << max_layer_count << " reached" << std::endl; + return false; + } else { + int position = layer_diff->getLayer1(); + if (position < 0 or position > layer_count) { + Logs::error() << "Add layer ignored because requested position was incorrect" << std::endl; + return false; + } else { + DefinitionNode *layer = layer_constructor(this, "temp"); + layer_diff->restoreSavedLayer(layer); + if (position == layer_count) { + layers.push_back(layer); + } else { + layers.insert(layers.begin() + position, layer); + } + addChild(layer); + return true; + } + } + } else if ((not backward and op == LayersDiff::LAYER_REMOVED) or (backward and op == LayersDiff::LAYER_ADDED)) { + int position = layer_diff->getLayer1(); + if (position < 0 or position >= layer_count) { + Logs::warning() << "Removing unknown layer " << position << " on " << layer_count << " from '" << getName() + << "'" << std::endl; + return false; + } else { + DefinitionNode *removed = layers[position]; + removeChild(removed); + layers.erase(layers.begin() + position); + delete removed; + return true; } - i++; } - Logs::warning() << "Layer " << layer << " (" << layer->getName() << " not found, on a total of " - << (int)layers.size() << std::endl; - return -1; + return false; } -int Layers::addLayer(DefinitionNode *layer) { - if ((int)layers.size() < max_layer_count) { - layers.push_back(layer); - addChild(layer); - return layers.size() - 1; - } else { - Logs::warning() << "Add layer ignored because limit of " << max_layer_count << " reached" << std::endl; - delete layer; - return -1; +void Layers::generateInitDiffs(std::vector *diffs) const { + int i = 0; + for (auto layer: layers) { + auto diff = new LayersDiff(this, LayersDiff::LAYER_ADDED, i++); + diff->saveLayer(*layer); + diffs->push_back(diff); } } -int Layers::addLayer() { - return addLayer(layer_constructor(this)); +void Layers::addLayer(const DefinitionNode &tocopy) { + auto diff = new LayersDiff(this, LayersDiff::LAYER_ADDED, getLayerCount()); + diff->saveLayer(tocopy); + addDiff(diff); +} + +void Layers::addLayer(const std::string &name) { + auto layer = layer_constructor(this, name); + addLayer(*layer); + delete layer; } void Layers::removeLayer(int position) { - if (position >= 0 and position < (int)layers.size()) { - DefinitionNode *removed = layers[position]; - removeChild(removed); - layers.erase(layers.begin() + position); - delete removed; - } else { - Logs::warning() << "Removing unknown layer " << position << " on " << (int)layers.size() << " from '" - << getName() << "'" << std::endl; - } -} - -void Layers::removeLayer(DefinitionNode *layer) { - removeLayer(findLayer(layer)); -} - -void Layers::moveLayer(int old_position, int new_position) { - if (old_position >= 0 and old_position < (int)layers.size() and new_position >= 0 and - new_position < (int)layers.size()) { - DefinitionNode *layer = layers[old_position]; - layers.erase(layers.begin() + old_position); - layers.insert(layers.begin() + new_position, layer); - } -} - -void Layers::moveLayer(DefinitionNode *layer, int new_position) { - moveLayer(findLayer(layer), new_position); + auto diff = new LayersDiff(this, LayersDiff::LAYER_REMOVED, position); + diff->saveLayer(*getLayer(position)); + addDiff(diff); } void Layers::clear() { - while (layers.size() > 0) { - removeLayer(0); - } -} - -DefinitionNode *Layers::findChildByName(const std::string name) { - DefinitionNode *result = DefinitionNode::findChildByName(name); - if (result) { - return result; - } else { - int position = addLayer(); - if (position >= 0) { - result = getLayer(position); - result->setName(name); - return result; - } else { - return NULL; - } + int n = getLayerCount(); + for (int i = n - 1; i >= 0; i--) { + removeLayer(i); } } diff --git a/src/definition/Layers.h b/src/definition/Layers.h index 4b454a4..fdba3af 100644 --- a/src/definition/Layers.h +++ b/src/definition/Layers.h @@ -8,7 +8,7 @@ namespace paysages { namespace definition { -typedef DefinitionNode *(*LayerConstructor)(Layers *parent); +typedef DefinitionNode *(*LayerConstructor)(Layers *parent, const std::string &name); /** * @brief Layers of definitions, ideally all of the same type. @@ -21,31 +21,49 @@ class DEFINITIONSHARED_EXPORT Layers : public DefinitionNode { virtual void save(PackStream *stream) const override; virtual void load(PackStream *stream) override; virtual void copy(DefinitionNode *destination) const override; - Layers *newCopy() const; - void setMaxLayerCount(int max_layer_count); - - int count() const; - DefinitionNode *getLayer(int position) const; - int findLayer(DefinitionNode *layer) const; + virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override; + virtual void generateInitDiffs(std::vector *diffs) const override; /** - * @brief Add a new layer - * - * This method takes ownership of the layer definition. In any case, it will be deleted by - * this object (even if the layer could not be added). - * @return The position of the new layer, -1 if it couldn't be added. + * Set the maximal layer count allowed. */ - int addLayer(DefinitionNode *layer); - int addLayer(); - void removeLayer(int position); - void removeLayer(DefinitionNode *layer); - void moveLayer(int old_position, int new_position); - void moveLayer(DefinitionNode *layer, int new_position); - void clear(); + void setMaxLayerCount(int max_layer_count); - protected: - virtual DefinitionNode *findChildByName(const std::string name) override; + /** + * Get the current layer count. + */ + int getLayerCount() const; + + /** + * Retrieve a layer by its position. + */ + DefinitionNode *getLayer(int position) const; + + /** + * Retrieve a layer by its name. + */ + DefinitionNode *getLayer(const std::string &name) const; + + /** + * Add a new empty layer. + */ + void addLayer(const std::string &name); + + /** + * Add a new layer, copying another node into it. + */ + void addLayer(const DefinitionNode &tocopy); + + /** + * Remove a layer by its position. + */ + void removeLayer(int position); + + /** + * Clear this node of all layers. + */ + void clear(); public: LayerConstructor layer_constructor; diff --git a/src/definition/LayersDiff.cpp b/src/definition/LayersDiff.cpp new file mode 100644 index 0000000..b22be29 --- /dev/null +++ b/src/definition/LayersDiff.cpp @@ -0,0 +1,32 @@ +#include "LayersDiff.h" + +#include "PackStream.h" +#include "Layers.h" +#include "Logs.h" + +LayersDiff::LayersDiff(const Layers *layers, LayersDiffOp op, int layer1) + : DefinitionDiff(layers), op(op), layer1(layer1), saved(NULL) { +} + +LayersDiff::~LayersDiff() { + if (saved) { + delete saved; + } +} + +void LayersDiff::saveLayer(const DefinitionNode &src) { + if (saved) { + delete saved; + } + saved = new PackStream(); + saved->write(src.getName()); + src.save(saved); +} + +void LayersDiff::restoreSavedLayer(DefinitionNode *dest) const { + if (saved) { + PackStream reader(saved); + dest->setName(reader.readString()); + dest->load(&reader); + } +} diff --git a/src/definition/LayersDiff.h b/src/definition/LayersDiff.h new file mode 100644 index 0000000..ae3de1f --- /dev/null +++ b/src/definition/LayersDiff.h @@ -0,0 +1,47 @@ +#ifndef LAYERSDIFF_H +#define LAYERSDIFF_H + +#include "definition_global.h" + +#include "DefinitionDiff.h" + +namespace paysages { +namespace definition { + +class DEFINITIONSHARED_EXPORT LayersDiff : public DefinitionDiff { + public: + typedef enum { LAYER_ADDED, LAYER_REMOVED } LayersDiffOp; + + public: + LayersDiff(const Layers *layers, LayersDiffOp op, int layer1); + virtual ~LayersDiff(); + + inline LayersDiffOp getOp() const { + return op; + } + inline int getLayer1() const { + return layer1; + } + + /** + * Save a layer state into the diff. + */ + void saveLayer(const DefinitionNode &src); + + /** + * Restore the saved layer into a node. + */ + void restoreSavedLayer(DefinitionNode *dest) const; + + private: + // Operation to apply + LayersDiffOp op; + // Position of first layer changed + int layer1; + // Serialized layer data + PackStream *saved; +}; +} +} + +#endif // LAYERSDIFF_H diff --git a/src/definition/TextureLayerDefinition.cpp b/src/definition/TextureLayerDefinition.cpp index 61a5592..6a40cb7 100644 --- a/src/definition/TextureLayerDefinition.cpp +++ b/src/definition/TextureLayerDefinition.cpp @@ -8,8 +8,8 @@ #include "TerrainDefinition.h" #include "Color.h" -TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent) - : DefinitionNode(parent, "texture", "texturelayer") { +TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent, const std::string &name) + : DefinitionNode(parent, name, "texturelayer") { terrain_zone = new Zone; _displacement_noise = new NoiseGenerator; _detail_noise = new NoiseGenerator; diff --git a/src/definition/TextureLayerDefinition.h b/src/definition/TextureLayerDefinition.h index 5594f5f..fc38ed2 100644 --- a/src/definition/TextureLayerDefinition.h +++ b/src/definition/TextureLayerDefinition.h @@ -20,7 +20,7 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode { } TextureLayerPreset; public: - TextureLayerDefinition(DefinitionNode *parent); + TextureLayerDefinition(DefinitionNode *parent, const std::string &name); virtual ~TextureLayerDefinition(); virtual void save(PackStream *stream) const override; diff --git a/src/definition/TexturesDefinition.cpp b/src/definition/TexturesDefinition.cpp index 5197c2a..92d1e77 100644 --- a/src/definition/TexturesDefinition.cpp +++ b/src/definition/TexturesDefinition.cpp @@ -2,53 +2,53 @@ #include "TextureLayerDefinition.h" -static DefinitionNode *_layer_constructor(Layers *parent) { - return new TextureLayerDefinition(parent); +static DefinitionNode *_layer_constructor(Layers *parent, const std::string &name) { + return new TextureLayerDefinition(parent, name); } TexturesDefinition::TexturesDefinition(DefinitionNode *parent) : Layers(parent, "textures", _layer_constructor) { } void TexturesDefinition::applyPreset(TexturesPreset preset) { - TextureLayerDefinition *layer; + TextureLayerDefinition layer(NULL, "temp"); clear(); - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD); - layer->setName("Mud"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD); + layer.setName("Mud"); + addLayer(layer); if (preset == TEXTURES_PRESET_FULL) { - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); - layer->setName("Ground"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); + layer.setName("Ground"); + addLayer(layer); - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); - layer->setName("Grass"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); + layer.setName("Grass"); + addLayer(layer); - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND); - layer->setName("Sand"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND); + layer.setName("Sand"); + addLayer(layer); - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); - layer->setName("Snow"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); + layer.setName("Snow"); + addLayer(layer); } else if (preset == TEXTURES_PRESET_IRELAND) { - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); - layer->setName("Ground"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); + layer.setName("Ground"); + addLayer(layer); - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); - layer->setName("Grass"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); + layer.setName("Grass"); + addLayer(layer); } else if (preset == TEXTURES_PRESET_ALPS) { - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); - layer->setName("Ground"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); + layer.setName("Ground"); + addLayer(layer); - layer = getTextureLayer(addLayer()); - layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); - layer->setName("Snow"); + layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); + layer.setName("Snow"); + addLayer(layer); } else if (preset == TEXTURES_PRESET_CANYON) { /* TODO */ } @@ -56,7 +56,7 @@ void TexturesDefinition::applyPreset(TexturesPreset preset) { double TexturesDefinition::getMaximalDisplacement() { double result = 0.0; - int n = count(); + int n = getLayerCount(); for (int i = 0; i < n; i++) { result += getTextureLayer(i)->displacement_height; } diff --git a/src/definition/TimeManager.cpp b/src/definition/TimeManager.cpp index c206636..2455877 100644 --- a/src/definition/TimeManager.cpp +++ b/src/definition/TimeManager.cpp @@ -17,7 +17,7 @@ void TimeManager::moveForward(Scenery *scenery, double amount) { scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->propDayTime()->getValue() + amount); // Move the clouds - int n = scenery->getClouds()->count(); + int n = scenery->getClouds()->getLayerCount(); for (int i = 0; i < n; i++) { CloudLayerDefinition *cloud = scenery->getClouds()->getCloudLayer(i); cloud->propXOffset()->addValue(-wind_x * amount * 100.0); diff --git a/src/definition/definition_global.h b/src/definition/definition_global.h index c3b5d9e..ca66a8f 100644 --- a/src/definition/definition_global.h +++ b/src/definition/definition_global.h @@ -26,6 +26,7 @@ class SurfaceMaterial; class Zone; class WaterDefinition; class Layers; +class LayersDiff; class CloudsDefinition; class CloudLayerDefinition; class AtmosphereDefinition; diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index beb8a06..f7ffe58 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -52,14 +52,15 @@ static void testGroundShadowQuality() { scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET); scenery.getAtmosphere()->setDayTime(16, 45); scenery.getTextures()->clear(); - TextureLayerDefinition *texture = scenery.getTextures()->getTextureLayer(scenery.getTextures()->addLayer()); - texture->displacement_height = 0.3; - texture->displacement_scaling = 2.0; - texture->displacement_offset = 0.0; - texture->material->setColor(0.6, 0.55, 0.57, 1.0); - texture->material->reflection = 0.006; - texture->material->shininess = 6.0; - texture->validate(); + TextureLayerDefinition texture(NULL, "test"); + texture.displacement_height = 0.3; + texture.displacement_scaling = 2.0; + texture.displacement_offset = 0.0; + texture.material->setColor(0.6, 0.55, 0.57, 1.0); + texture.material->reflection = 0.006; + texture.material->shininess = 6.0; + texture.validate(); + scenery.getTextures()->addLayer(texture); scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0)); scenery.getCamera()->setTarget(VECTOR_ZERO); scenery.validate(); diff --git a/src/render/software/CloudsRenderer.cpp b/src/render/software/CloudsRenderer.cpp index 29c9ecf..5f36c6f 100644 --- a/src/render/software/CloudsRenderer.cpp +++ b/src/render/software/CloudsRenderer.cpp @@ -20,7 +20,7 @@ CloudsRenderer::CloudsRenderer(SoftwareRenderer *parent) : parent(parent) { enabled = true; fake_renderer = new BaseCloudLayerRenderer(parent); - CloudLayerDefinition *fake_layer = new CloudLayerDefinition(NULL); + CloudLayerDefinition *fake_layer = new CloudLayerDefinition(NULL, "#fake#"); fake_model = new BaseCloudsModel(fake_layer); } @@ -60,7 +60,7 @@ void CloudsRenderer::update() { layer_models.clear(); CloudsDefinition *clouds = parent->getScenery()->getClouds(); - int n = clouds->count(); + int n = clouds->getLayerCount(); for (int i = 0; i < n; i++) { layer_renderers.push_back(new CloudBasicLayerRenderer(parent)); @@ -129,7 +129,7 @@ void CloudsRenderer::setLayerModel(unsigned int layer, BaseCloudsModel *model, b Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, const Color &base) { CloudsDefinition *definition = parent->getScenery()->getClouds(); - int n = definition->count(); + int n = definition->getLayerCount(); if (not enabled or n < 1) { return base; } @@ -152,7 +152,7 @@ Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, cons bool CloudsRenderer::applyLightFilter(LightComponent &light, const Vector3 &at) { CloudsDefinition *definition = parent->getScenery()->getClouds(); - int n = definition->count(); + int n = definition->getLayerCount(); if (not enabled or n < 1) { return true; } @@ -172,7 +172,7 @@ double CloudsRenderer::getHighestAltitude() { CloudsDefinition *definition = parent->getScenery()->getClouds(); double highest = 0.0; - int n = definition->count(); + int n = definition->getLayerCount(); double low, high; for (int i = 0; i < n; i++) { BaseCloudsModel *layer_model = getLayerModel(i); diff --git a/src/render/software/TexturesRenderer.cpp b/src/render/software/TexturesRenderer.cpp index 015f732..22ce4f9 100644 --- a/src/render/software/TexturesRenderer.cpp +++ b/src/render/software/TexturesRenderer.cpp @@ -46,7 +46,7 @@ double TexturesRenderer::getTriplanarNoise(NoiseGenerator *noise, const Vector3 double TexturesRenderer::getMaximalDisplacement(TexturesDefinition *textures) { int i, n; double disp = 0.0; - n = textures->count(); + n = textures->getLayerCount(); for (i = 0; i < n; i++) { TextureLayerDefinition *layer = textures->getTextureLayer(i); @@ -129,7 +129,7 @@ Vector3 TexturesRenderer::displaceTerrain(const TerrainRenderer::TerrainResult & double offset = 0.0; int i, n; - n = textures->count(); + n = textures->getLayerCount(); for (i = 0; i < n; i++) { TextureLayerDefinition *layer = textures->getTextureLayer(i); @@ -161,7 +161,7 @@ TexturesRenderer::TexturesResult TexturesRenderer::applyToTerrain(double x, doub // TODO Displaced textures had their presence already computed before, store that result and use it // Find presence of each layer - int n = textures->count(); + int n = textures->getLayerCount(); int start = 0; for (int i = 0; i < n; i++) { TexturesLayerResult &layer = result.layers[i]; diff --git a/src/system/FileSystem.cpp b/src/system/FileSystem.cpp index 8d1d961..d4b962b 100644 --- a/src/system/FileSystem.cpp +++ b/src/system/FileSystem.cpp @@ -15,5 +15,8 @@ bool FileSystem::isFile(const std::string &filepath) { bool FileSystem::removeFile(const std::string &filepath) { if (FileSystem::isFile(filepath)) { remove(filepath.c_str()); + return true; + } else { + return false; } } diff --git a/src/system/PackStream.cpp b/src/system/PackStream.cpp index 1716866..acc8aa8 100644 --- a/src/system/PackStream.cpp +++ b/src/system/PackStream.cpp @@ -33,6 +33,13 @@ PackStream::PackStream(const PackStream *other) { stream->setVersion(QDataStream::Qt_5_2); } +PackStream::PackStream(const std::string &buffer_content) { + file = NULL; + buffer = new QByteArray(buffer_content.c_str(), buffer_content.size()); + stream = new QDataStream(buffer, QIODevice::ReadOnly); + stream->setVersion(QDataStream::Qt_5_2); +} + bool PackStream::bindToFile(const std::string &filepath, bool write) { if (not file) { file = new QFile(QString::fromStdString(filepath)); @@ -90,6 +97,16 @@ void PackStream::writeFromBuffer(const PackStream &other, bool prepend_size) { } } +std::string PackStream::getBuffer() { + if (file) { + Logs::error() << "Try to get buffer on a stream bound to a file: " << file->fileName().toStdString() + << std::endl; + return ""; + } else { + return buffer->toStdString(); + } +} + void PackStream::read(int *value) { if (value and not stream->atEnd()) { int output; diff --git a/src/system/PackStream.h b/src/system/PackStream.h index 475289c..d72da78 100644 --- a/src/system/PackStream.h +++ b/src/system/PackStream.h @@ -25,6 +25,11 @@ class SYSTEMSHARED_EXPORT PackStream { */ PackStream(const PackStream *other); + /** + * Open a reading stream on a buffer content. + */ + PackStream(const std::string &buffer_content); + bool bindToFile(const std::string &filepath, bool write = false); void write(const int *value); @@ -41,6 +46,11 @@ class SYSTEMSHARED_EXPORT PackStream { */ void writeFromBuffer(const PackStream &other, bool prepend_size = false); + /** + * Get the contents of the memory buffer, if this stream is not bound to a file. + */ + std::string getBuffer(); + void read(int *value); void read(double *value); void read(char *value, int max_length); diff --git a/src/tests/Layers_Test.cpp b/src/tests/Layers_Test.cpp index b9d2961..25d1419 100644 --- a/src/tests/Layers_Test.cpp +++ b/src/tests/Layers_Test.cpp @@ -2,19 +2,21 @@ #include "Layers.h" #include "PackStream.h" +#include "DiffManager.h" +#include "IntNode.h" -DefinitionNode *_construc1(Layers *) { - return new DefinitionNode(NULL, "test"); +static DefinitionNode *_construc1(Layers *, const std::string &name) { + return new DefinitionNode(NULL, name); } -DefinitionNode *_construc2(Layers *parent) { - DefinitionNode *result = new DefinitionNode(parent, "test"); +static DefinitionNode *_construc2(Layers *parent, const std::string &name) { + DefinitionNode *result = new DefinitionNode(parent, name); return result; } TEST(Layers, Constructor) { Layers layers1(NULL, "test", _construc1); - EXPECT_EQ(0, layers1.count()); + EXPECT_EQ(0, layers1.getLayerCount()); } TEST(Layers, NullLayer) { @@ -27,22 +29,22 @@ TEST(Layers, NullLayer) { EXPECT_EQ(NULL, layer->getParent()); EXPECT_EQ(layer, layer->getRoot()); - EXPECT_EQ("test", layer->getName()); + EXPECT_EQ("#NULL#", layer->getName()); } - EXPECT_EQ(0, layers1.count()); + EXPECT_EQ(0, layers1.getLayerCount()); } TEST(Layers, copy) { Layers layers1(NULL, "test", _construc2); - layers1.addLayer(); - EXPECT_EQ(1, layers1.count()); + layers1.addLayer("test"); + EXPECT_EQ(1, layers1.getLayerCount()); // Copy with the same constructor Layers layers2(NULL, "test", _construc2); - EXPECT_EQ(0, layers2.count()); + EXPECT_EQ(0, layers2.getLayerCount()); layers1.copy(&layers2); - EXPECT_EQ(1, layers2.count()); + EXPECT_EQ(1, layers2.getLayerCount()); EXPECT_EQ("test", layers1.getLayer(0)->getName()); EXPECT_EQ(&layers1, layers1.getLayer(0)->getParent()); EXPECT_EQ("test", layers2.getLayer(0)->getName()); @@ -54,32 +56,35 @@ TEST(Layers, maxLayerCount) { Layers layers1(NULL, "test", _construc1); layers1.setMaxLayerCount(2); - EXPECT_EQ(0, layers1.count()); - layers1.addLayer(); - EXPECT_EQ(1, layers1.count()); - layers1.addLayer(); - EXPECT_EQ(2, layers1.count()); - layers1.addLayer(); - EXPECT_EQ(2, layers1.count()); - layers1.addLayer(); - EXPECT_EQ(2, layers1.count()); + EXPECT_EQ(0, layers1.getLayerCount()); + layers1.addLayer("t1"); + EXPECT_EQ(1, layers1.getLayerCount()); + layers1.addLayer("t2"); + EXPECT_EQ(2, layers1.getLayerCount()); + layers1.addLayer("t3"); + EXPECT_EQ(2, layers1.getLayerCount()); + layers1.addLayer("t4"); + EXPECT_EQ(2, layers1.getLayerCount()); layers1.removeLayer(0); - EXPECT_EQ(1, layers1.count()); - layers1.addLayer(); - EXPECT_EQ(2, layers1.count()); - layers1.addLayer(); - EXPECT_EQ(2, layers1.count()); + EXPECT_EQ(1, layers1.getLayerCount()); + layers1.addLayer("t5"); + EXPECT_EQ(2, layers1.getLayerCount()); + layers1.addLayer("t6"); + EXPECT_EQ(2, layers1.getLayerCount()); + + layers1.setMaxLayerCount(1); + EXPECT_EQ(1, layers1.getLayerCount()); + layers1.setMaxLayerCount(0); + EXPECT_EQ(0, layers1.getLayerCount()); } TEST(Layers, saveLoad) { PackStream *stream; Layers layers1(NULL, "test", _construc1); - layers1.addLayer(); - layers1.addLayer(); - ASSERT_EQ(2, layers1.count()); - layers1.getLayer(0)->setName("first"); - layers1.getLayer(1)->setName("second"); + layers1.addLayer("first"); + layers1.addLayer("second"); + ASSERT_EQ(2, layers1.getLayerCount()); stream = new PackStream(); stream->bindToFile("/tmp/test_paysages_pack", true); @@ -93,7 +98,99 @@ TEST(Layers, saveLoad) { layers2.load(stream); delete stream; - ASSERT_EQ(2, layers2.count()); + ASSERT_EQ(2, layers2.getLayerCount()); EXPECT_EQ("first", layers2.getLayer(0)->getName()); EXPECT_EQ("second", layers2.getLayer(1)->getName()); } + +static void checkLayerChild(const Layers &layers, int layer, const std::string &name, int value) { + ASSERT_EQ(1, layers.getLayerCount()); + ASSERT_TRUE(layers.getLayer(layer)->findByPath(name)); + ASSERT_EQ("int", layers.getLayer(layer)->findByPath(name)->getTypeName()); + EXPECT_EQ(value, ((IntNode *)layers.getLayer(layer)->findByPath(name))->getValue()); +} + +class TestLayer : public DefinitionNode { + public: + TestLayer(Layers *parent, const std::string &name) : DefinitionNode(parent, name) { + val = new IntNode(this, "val", 5); + } + IntNode *val; +}; + +static DefinitionNode *_construc3(Layers *parent, const std::string &name) { + return new TestLayer(parent, name); +} + +TEST(Layers, undoRedo) { + Layers layers(NULL, "layers", _construc3); + + EXPECT_EQ(0, layers.getLayerCount()); + EXPECT_EQ(0, layers.getDiffManager()->getDiffCount()); + + layers.addLayer("testlayer"); + + ASSERT_EQ(1, layers.getLayerCount()); + + TestLayer *layer = (TestLayer *)layers.getLayer(0); + + EXPECT_EQ(1, layers.getDiffManager()->getDiffCount()); + checkLayerChild(layers, 0, "val", 5); + + layer->val->setValue(8); + + EXPECT_EQ(2, layers.getDiffManager()->getDiffCount()); + checkLayerChild(layers, 0, "val", 8); + + layers.removeLayer(0); + + EXPECT_EQ(3, layers.getDiffManager()->getDiffCount()); + EXPECT_EQ(0, layers.getLayerCount()); + + // Start undoing + layers.getDiffManager()->undo(); + checkLayerChild(layers, 0, "val", 8); + layers.getDiffManager()->undo(); + checkLayerChild(layers, 0, "val", 5); + layers.getDiffManager()->undo(); + EXPECT_EQ(0, layers.getLayerCount()); + + EXPECT_EQ(3, layers.getDiffManager()->getDiffCount()); + + // Start redoing + layers.getDiffManager()->redo(); + checkLayerChild(layers, 0, "val", 5); + layers.getDiffManager()->redo(); + checkLayerChild(layers, 0, "val", 8); + layers.getDiffManager()->redo(); + EXPECT_EQ(0, layers.getLayerCount()); + + EXPECT_EQ(3, layers.getDiffManager()->getDiffCount()); + + // TODO Test swapping +} + +TEST(Layers, generateInitDiffs) { + Layers layers(NULL, "layers", _construc1); + + std::vector diffs; + layers.generateInitDiffs(&diffs); + EXPECT_EQ(0, (int)diffs.size()); + + layers.addLayer("l1"); + layers.addLayer("l2"); + layers.addLayer("l3"); + + diffs.clear(); + layers.generateInitDiffs(&diffs); + EXPECT_EQ(3, (int)diffs.size()); + + Layers layers1(NULL, "layers", _construc1); + for (auto diff: diffs) { + layers1.applyDiff(diff); + } + ASSERT_EQ(3, layers1.getLayerCount()); + EXPECT_EQ("l1", layers1.getLayer(0)->getName()); + EXPECT_EQ("l2", layers1.getLayer(1)->getName()); + EXPECT_EQ("l3", layers1.getLayer(2)->getName()); +}