Refactored layers system to work better as DefinitionNode

It now features undo/redo of layer creation and removal
This commit is contained in:
Michaël Lemaire 2015-11-20 01:07:31 +01:00
parent 5f0b3734cf
commit 2b65f1d26a
24 changed files with 444 additions and 207 deletions

View file

@ -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;
}

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -4,3 +4,6 @@
DefinitionDiff::DefinitionDiff(const DefinitionNode *node) : type_name(node->getTypeName()), path(node->getPath()) {
}
DefinitionDiff::~DefinitionDiff() {
}

View file

@ -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;

View file

@ -248,5 +248,7 @@ void DefinitionNode::addDiff(const DefinitionDiff *diff) {
if (root && root->diffs) {
root->diffs->addDiff(this, diff);
} else {
delete diff;
}
}

View file

@ -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,31 +47,41 @@ 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());
if (node) {
undone++;
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;
}
}
}
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());
if (node) {
undone--;
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;
}
}
}

View file

@ -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.
*

View file

@ -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;
}
i++;
}
Logs::warning() << "Layer " << layer << " (" << layer->getName() << " not found, on a total of "
<< (int)layers.size() << std::endl;
return -1;
}
bool Layers::applyDiff(const DefinitionDiff *diff, bool backward) {
auto layer_diff = (LayersDiff *)diff;
LayersDiff::LayersDiffOp op = layer_diff->getOp();
int layer_count = getLayerCount();
int Layers::addLayer(DefinitionNode *layer) {
if ((int)layers.size() < max_layer_count) {
layers.push_back(layer);
addChild(layer);
return layers.size() - 1;
} else {
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;
delete layer;
return -1;
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;
}
}
int Layers::addLayer() {
return addLayer(layer_constructor(this));
}
void Layers::removeLayer(int position) {
if (position >= 0 and position < (int)layers.size()) {
} 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;
} else {
Logs::warning() << "Removing unknown layer " << position << " on " << (int)layers.size() << " from '"
<< getName() << "'" << std::endl;
return true;
}
}
return false;
}
void Layers::generateInitDiffs(std::vector<const DefinitionDiff *> *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);
}
}
void Layers::removeLayer(DefinitionNode *layer) {
removeLayer(findLayer(layer));
void Layers::addLayer(const DefinitionNode &tocopy) {
auto diff = new LayersDiff(this, LayersDiff::LAYER_ADDED, getLayerCount());
diff->saveLayer(tocopy);
addDiff(diff);
}
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::addLayer(const std::string &name) {
auto layer = layer_constructor(this, name);
addLayer(*layer);
delete layer;
}
void Layers::moveLayer(DefinitionNode *layer, int new_position) {
moveLayer(findLayer(layer), new_position);
void Layers::removeLayer(int 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);
}
}

View file

@ -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<const DefinitionDiff *> *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;

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -26,6 +26,7 @@ class SurfaceMaterial;
class Zone;
class WaterDefinition;
class Layers;
class LayersDiff;
class CloudsDefinition;
class CloudLayerDefinition;
class AtmosphereDefinition;

View file

@ -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();

View file

@ -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);

View file

@ -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];

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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<const DefinitionDiff *> 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());
}