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 "PackStream.h"
#include "FloatNode.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; type = CIRRUS;
altitude = 0.5; altitude = 0.5;
scaling = 0.5; scaling = 0.5;
@ -20,13 +21,13 @@ CloudLayerDefinition::~CloudLayerDefinition() {
} }
CloudLayerDefinition *CloudLayerDefinition::newCopy(const CloudLayerDefinition &other, DefinitionNode *parent) { CloudLayerDefinition *CloudLayerDefinition::newCopy(const CloudLayerDefinition &other, DefinitionNode *parent) {
CloudLayerDefinition *layer = new CloudLayerDefinition(parent); CloudLayerDefinition *layer = new CloudLayerDefinition(parent, other.getName());
other.copy(layer); other.copy(layer);
return layer; return layer;
} }
CloudLayerDefinition *CloudLayerDefinition::newCopy(DefinitionNode *parent) const { CloudLayerDefinition *CloudLayerDefinition::newCopy(DefinitionNode *parent) const {
CloudLayerDefinition *layer = new CloudLayerDefinition(parent); CloudLayerDefinition *layer = new CloudLayerDefinition(parent, getName());
copy(layer); copy(layer);
return layer; return layer;
} }

View file

@ -12,7 +12,7 @@ namespace definition {
class DEFINITIONSHARED_EXPORT CloudLayerDefinition : public DefinitionNode { class DEFINITIONSHARED_EXPORT CloudLayerDefinition : public DefinitionNode {
public: public:
CloudLayerDefinition(DefinitionNode *parent); CloudLayerDefinition(DefinitionNode *parent, const std::string &name);
virtual ~CloudLayerDefinition(); virtual ~CloudLayerDefinition();
inline const NoiseState &getNoiseState() const { inline const NoiseState &getNoiseState() const {

View file

@ -2,8 +2,8 @@
#include "CloudLayerDefinition.h" #include "CloudLayerDefinition.h"
static DefinitionNode *_layerConstructor(Layers *parent) { static DefinitionNode *_layerConstructor(Layers *parent, const std::string &name) {
return new CloudLayerDefinition(parent); return new CloudLayerDefinition(parent, name);
} }
CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) { CloudsDefinition::CloudsDefinition(DefinitionNode *parent) : Layers(parent, "clouds", _layerConstructor) {
@ -13,9 +13,8 @@ void CloudsDefinition::applyPreset(CloudsPreset preset) {
clear(); clear();
if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) { if (preset == CLOUDS_PRESET_PARTLY_CLOUDY) {
CloudLayerDefinition *layer = new CloudLayerDefinition(this); CloudLayerDefinition layer(NULL, "Strato-cumulus");
layer->type = CloudLayerDefinition::STRATOCUMULUS; layer.type = CloudLayerDefinition::STRATOCUMULUS;
layer->setName("Strato-cumulus");
addLayer(layer); addLayer(layer);
} }
} }

View file

@ -4,3 +4,6 @@
DefinitionDiff::DefinitionDiff(const DefinitionNode *node) : type_name(node->getTypeName()), path(node->getPath()) { 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 { class DEFINITIONSHARED_EXPORT DefinitionDiff {
public: public:
DefinitionDiff(const DefinitionNode *node); DefinitionDiff(const DefinitionNode *node);
virtual ~DefinitionDiff();
inline const std::string &getTypeName() const { inline const std::string &getTypeName() const {
return type_name; return type_name;

View file

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

View file

@ -4,6 +4,7 @@
#include "DefinitionNode.h" #include "DefinitionNode.h"
#include "DefinitionDiff.h" #include "DefinitionDiff.h"
#include "DefinitionWatcher.h" #include "DefinitionWatcher.h"
#include "Logs.h"
DiffManager::DiffManager(DefinitionNode *tree) : tree(tree) { DiffManager::DiffManager(DefinitionNode *tree) : tree(tree) {
undone = 0; undone = 0;
@ -46,31 +47,41 @@ void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff) {
void DiffManager::undo() { void DiffManager::undo() {
if (undone < (int)diffs.size()) { if (undone < (int)diffs.size()) {
undone++; const DefinitionDiff *diff = diffs[diffs.size() - undone - 1];
const DefinitionDiff *diff = diffs[diffs.size() - undone];
// Obtain the node by path and reverse apply diff on it // Obtain the node by path and reverse apply diff on it
DefinitionNode *node = tree->findByPath(diff->getPath()); DefinitionNode *node = tree->findByPath(diff->getPath());
if (node) {
undone++;
node->applyDiff(diff, true); node->applyDiff(diff, true);
for (auto watcher : watchers[node]) { for (auto watcher : watchers[node]) {
// FIXME Reverse diff // FIXME Reverse diff
watcher->nodeChanged(node, diff); watcher->nodeChanged(node, diff);
} }
} else {
Logs::error() << "Can't find node to undo diff : " << diff->getPath() << std::endl;
}
} }
} }
void DiffManager::redo() { void DiffManager::redo() {
if (undone > 0) { if (undone > 0) {
const DefinitionDiff *diff = diffs[diffs.size() - undone]; const DefinitionDiff *diff = diffs[diffs.size() - undone];
undone--;
// Obtain the node by path and re-apply diff on it // Obtain the node by path and re-apply diff on it
DefinitionNode *node = tree->findByPath(diff->getPath()); DefinitionNode *node = tree->findByPath(diff->getPath());
if (node) {
undone--;
node->applyDiff(diff); node->applyDiff(diff);
for (auto watcher : watchers[node]) { for (auto watcher : watchers[node]) {
watcher->nodeChanged(node, diff); 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(DefinitionNode *tree);
~DiffManager(); ~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. * Add a watcher for a specific node.
* *

View file

@ -2,15 +2,15 @@
#include "PackStream.h" #include "PackStream.h"
#include "Logs.h" #include "Logs.h"
#include "LayersDiff.h"
Layers::Layers(DefinitionNode *parent, const std::string &name, LayerConstructor layer_constructor) Layers::Layers(DefinitionNode *parent, const std::string &name, LayerConstructor layer_constructor)
: DefinitionNode(parent, name, "layers" + name), layer_constructor(layer_constructor) { : DefinitionNode(parent, name, "layers" + name), layer_constructor(layer_constructor) {
max_layer_count = 100; max_layer_count = 100;
null_layer = layer_constructor(this); null_layer = layer_constructor(this, "#NULL#");
} }
Layers::~Layers() { Layers::~Layers() {
clear();
delete null_layer; delete null_layer;
} }
@ -28,16 +28,12 @@ void Layers::load(PackStream *stream) {
int layer_count; int layer_count;
stream->read(&layer_count); stream->read(&layer_count);
if (layer_count > max_layer_count) {
layer_count = max_layer_count;
}
clear(); clear();
for (int i = 0; i < layer_count; i++) { for (int i = 0; i < layer_count; i++) {
int position = addLayer(); DefinitionNode *layer = layer_constructor(this, stream->readString());
if (position >= 0) { layer->load(stream);
layers[position]->setName(stream->readString()); addLayer(*layer);
layers[position]->load(stream); delete layer;
}
} }
} }
@ -53,24 +49,18 @@ void Layers::copy(DefinitionNode *destination_) const {
null_layer->copy(destination->null_layer); null_layer->copy(destination->null_layer);
for (auto layer : layers) { for (auto layer : layers) {
int position = destination->addLayer(); destination->addLayer(*layer);
DefinitionNode *new_layer = destination->getLayer(position);
layer->copy(new_layer);
} }
} }
Layers *Layers::newCopy() const {
Layers *result = new Layers(NULL, getName(), layer_constructor);
copy(result);
return result;
}
void Layers::setMaxLayerCount(int max_layer_count) { void Layers::setMaxLayerCount(int max_layer_count) {
this->max_layer_count = 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(); return layers.size();
} }
@ -84,82 +74,79 @@ DefinitionNode *Layers::getLayer(int position) const {
} }
} }
int Layers::findLayer(DefinitionNode *layer) const { bool Layers::applyDiff(const DefinitionDiff *diff, bool backward) {
int i = 0; auto layer_diff = (LayersDiff *)diff;
for (auto it : layers) { LayersDiff::LayersDiffOp op = layer_diff->getOp();
if (it == layer) { int layer_count = getLayerCount();
return i;
}
i++;
}
Logs::warning() << "Layer " << layer << " (" << layer->getName() << " not found, on a total of "
<< (int)layers.size() << std::endl;
return -1;
}
int Layers::addLayer(DefinitionNode *layer) { if ((not backward and op == LayersDiff::LAYER_ADDED) or (backward and op == LayersDiff::LAYER_REMOVED)) {
if ((int)layers.size() < max_layer_count) { if (layer_count >= 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; Logs::warning() << "Add layer ignored because limit of " << max_layer_count << " reached" << std::endl;
delete layer; return false;
return -1; } 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)); }
} } else if ((not backward and op == LayersDiff::LAYER_REMOVED) or (backward and op == LayersDiff::LAYER_ADDED)) {
int position = layer_diff->getLayer1();
void Layers::removeLayer(int position) { if (position < 0 or position >= layer_count) {
if (position >= 0 and position < (int)layers.size()) { Logs::warning() << "Removing unknown layer " << position << " on " << layer_count << " from '" << getName()
<< "'" << std::endl;
return false;
} else {
DefinitionNode *removed = layers[position]; DefinitionNode *removed = layers[position];
removeChild(removed); removeChild(removed);
layers.erase(layers.begin() + position); layers.erase(layers.begin() + position);
delete removed; delete removed;
} else { return true;
Logs::warning() << "Removing unknown layer " << position << " on " << (int)layers.size() << " from '" }
<< getName() << "'" << std::endl; }
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) { void Layers::addLayer(const DefinitionNode &tocopy) {
removeLayer(findLayer(layer)); auto diff = new LayersDiff(this, LayersDiff::LAYER_ADDED, getLayerCount());
diff->saveLayer(tocopy);
addDiff(diff);
} }
void Layers::moveLayer(int old_position, int new_position) { void Layers::addLayer(const std::string &name) {
if (old_position >= 0 and old_position < (int)layers.size() and new_position >= 0 and auto layer = layer_constructor(this, name);
new_position < (int)layers.size()) { addLayer(*layer);
DefinitionNode *layer = layers[old_position]; delete layer;
layers.erase(layers.begin() + old_position);
layers.insert(layers.begin() + new_position, layer);
}
} }
void Layers::moveLayer(DefinitionNode *layer, int new_position) { void Layers::removeLayer(int position) {
moveLayer(findLayer(layer), new_position); auto diff = new LayersDiff(this, LayersDiff::LAYER_REMOVED, position);
diff->saveLayer(*getLayer(position));
addDiff(diff);
} }
void Layers::clear() { void Layers::clear() {
while (layers.size() > 0) { int n = getLayerCount();
removeLayer(0); for (int i = n - 1; i >= 0; i--) {
} removeLayer(i);
}
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;
}
} }
} }

View file

@ -8,7 +8,7 @@
namespace paysages { namespace paysages {
namespace definition { 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. * @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 save(PackStream *stream) const override;
virtual void load(PackStream *stream) override; virtual void load(PackStream *stream) override;
virtual void copy(DefinitionNode *destination) const override; virtual void copy(DefinitionNode *destination) const override;
Layers *newCopy() const;
void setMaxLayerCount(int max_layer_count); virtual bool applyDiff(const DefinitionDiff *diff, bool backward = false) override;
virtual void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const override;
int count() const;
DefinitionNode *getLayer(int position) const;
int findLayer(DefinitionNode *layer) const;
/** /**
* @brief Add a new layer * Set the maximal layer count allowed.
*
* 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.
*/ */
int addLayer(DefinitionNode *layer); void setMaxLayerCount(int max_layer_count);
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();
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: public:
LayerConstructor layer_constructor; 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 "TerrainDefinition.h"
#include "Color.h" #include "Color.h"
TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent) TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent, const std::string &name)
: DefinitionNode(parent, "texture", "texturelayer") { : DefinitionNode(parent, name, "texturelayer") {
terrain_zone = new Zone; terrain_zone = new Zone;
_displacement_noise = new NoiseGenerator; _displacement_noise = new NoiseGenerator;
_detail_noise = new NoiseGenerator; _detail_noise = new NoiseGenerator;

View file

@ -20,7 +20,7 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode {
} TextureLayerPreset; } TextureLayerPreset;
public: public:
TextureLayerDefinition(DefinitionNode *parent); TextureLayerDefinition(DefinitionNode *parent, const std::string &name);
virtual ~TextureLayerDefinition(); virtual ~TextureLayerDefinition();
virtual void save(PackStream *stream) const override; virtual void save(PackStream *stream) const override;

View file

@ -2,53 +2,53 @@
#include "TextureLayerDefinition.h" #include "TextureLayerDefinition.h"
static DefinitionNode *_layer_constructor(Layers *parent) { static DefinitionNode *_layer_constructor(Layers *parent, const std::string &name) {
return new TextureLayerDefinition(parent); return new TextureLayerDefinition(parent, name);
} }
TexturesDefinition::TexturesDefinition(DefinitionNode *parent) : Layers(parent, "textures", _layer_constructor) { TexturesDefinition::TexturesDefinition(DefinitionNode *parent) : Layers(parent, "textures", _layer_constructor) {
} }
void TexturesDefinition::applyPreset(TexturesPreset preset) { void TexturesDefinition::applyPreset(TexturesPreset preset) {
TextureLayerDefinition *layer; TextureLayerDefinition layer(NULL, "temp");
clear(); clear();
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_MUD); layer.setName("Mud");
layer->setName("Mud"); addLayer(layer);
if (preset == TEXTURES_PRESET_FULL) { if (preset == TEXTURES_PRESET_FULL) {
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); layer.setName("Ground");
layer->setName("Ground"); addLayer(layer);
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); layer.setName("Grass");
layer->setName("Grass"); addLayer(layer);
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SAND); layer.setName("Sand");
layer->setName("Sand"); addLayer(layer);
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); layer.setName("Snow");
layer->setName("Snow"); addLayer(layer);
} else if (preset == TEXTURES_PRESET_IRELAND) { } else if (preset == TEXTURES_PRESET_IRELAND) {
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); layer.setName("Ground");
layer->setName("Ground"); addLayer(layer);
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_GRASS); layer.setName("Grass");
layer->setName("Grass"); addLayer(layer);
} else if (preset == TEXTURES_PRESET_ALPS) { } else if (preset == TEXTURES_PRESET_ALPS) {
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK); layer.setName("Ground");
layer->setName("Ground"); addLayer(layer);
layer = getTextureLayer(addLayer()); layer.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW);
layer->applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_SNOW); layer.setName("Snow");
layer->setName("Snow"); addLayer(layer);
} else if (preset == TEXTURES_PRESET_CANYON) { } else if (preset == TEXTURES_PRESET_CANYON) {
/* TODO */ /* TODO */
} }
@ -56,7 +56,7 @@ void TexturesDefinition::applyPreset(TexturesPreset preset) {
double TexturesDefinition::getMaximalDisplacement() { double TexturesDefinition::getMaximalDisplacement() {
double result = 0.0; double result = 0.0;
int n = count(); int n = getLayerCount();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
result += getTextureLayer(i)->displacement_height; 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); scenery->getAtmosphere()->setDayTime(scenery->getAtmosphere()->propDayTime()->getValue() + amount);
// Move the clouds // Move the clouds
int n = scenery->getClouds()->count(); int n = scenery->getClouds()->getLayerCount();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
CloudLayerDefinition *cloud = scenery->getClouds()->getCloudLayer(i); CloudLayerDefinition *cloud = scenery->getClouds()->getCloudLayer(i);
cloud->propXOffset()->addValue(-wind_x * amount * 100.0); cloud->propXOffset()->addValue(-wind_x * amount * 100.0);

View file

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

View file

@ -52,14 +52,15 @@ static void testGroundShadowQuality() {
scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET); scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET);
scenery.getAtmosphere()->setDayTime(16, 45); scenery.getAtmosphere()->setDayTime(16, 45);
scenery.getTextures()->clear(); scenery.getTextures()->clear();
TextureLayerDefinition *texture = scenery.getTextures()->getTextureLayer(scenery.getTextures()->addLayer()); TextureLayerDefinition texture(NULL, "test");
texture->displacement_height = 0.3; texture.displacement_height = 0.3;
texture->displacement_scaling = 2.0; texture.displacement_scaling = 2.0;
texture->displacement_offset = 0.0; texture.displacement_offset = 0.0;
texture->material->setColor(0.6, 0.55, 0.57, 1.0); texture.material->setColor(0.6, 0.55, 0.57, 1.0);
texture->material->reflection = 0.006; texture.material->reflection = 0.006;
texture->material->shininess = 6.0; texture.material->shininess = 6.0;
texture->validate(); texture.validate();
scenery.getTextures()->addLayer(texture);
scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0)); scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0));
scenery.getCamera()->setTarget(VECTOR_ZERO); scenery.getCamera()->setTarget(VECTOR_ZERO);
scenery.validate(); scenery.validate();

View file

@ -20,7 +20,7 @@ CloudsRenderer::CloudsRenderer(SoftwareRenderer *parent) : parent(parent) {
enabled = true; enabled = true;
fake_renderer = new BaseCloudLayerRenderer(parent); fake_renderer = new BaseCloudLayerRenderer(parent);
CloudLayerDefinition *fake_layer = new CloudLayerDefinition(NULL); CloudLayerDefinition *fake_layer = new CloudLayerDefinition(NULL, "#fake#");
fake_model = new BaseCloudsModel(fake_layer); fake_model = new BaseCloudsModel(fake_layer);
} }
@ -60,7 +60,7 @@ void CloudsRenderer::update() {
layer_models.clear(); layer_models.clear();
CloudsDefinition *clouds = parent->getScenery()->getClouds(); CloudsDefinition *clouds = parent->getScenery()->getClouds();
int n = clouds->count(); int n = clouds->getLayerCount();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
layer_renderers.push_back(new CloudBasicLayerRenderer(parent)); 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) { Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, const Color &base) {
CloudsDefinition *definition = parent->getScenery()->getClouds(); CloudsDefinition *definition = parent->getScenery()->getClouds();
int n = definition->count(); int n = definition->getLayerCount();
if (not enabled or n < 1) { if (not enabled or n < 1) {
return base; return base;
} }
@ -152,7 +152,7 @@ Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, cons
bool CloudsRenderer::applyLightFilter(LightComponent &light, const Vector3 &at) { bool CloudsRenderer::applyLightFilter(LightComponent &light, const Vector3 &at) {
CloudsDefinition *definition = parent->getScenery()->getClouds(); CloudsDefinition *definition = parent->getScenery()->getClouds();
int n = definition->count(); int n = definition->getLayerCount();
if (not enabled or n < 1) { if (not enabled or n < 1) {
return true; return true;
} }
@ -172,7 +172,7 @@ double CloudsRenderer::getHighestAltitude() {
CloudsDefinition *definition = parent->getScenery()->getClouds(); CloudsDefinition *definition = parent->getScenery()->getClouds();
double highest = 0.0; double highest = 0.0;
int n = definition->count(); int n = definition->getLayerCount();
double low, high; double low, high;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
BaseCloudsModel *layer_model = getLayerModel(i); BaseCloudsModel *layer_model = getLayerModel(i);

View file

@ -46,7 +46,7 @@ double TexturesRenderer::getTriplanarNoise(NoiseGenerator *noise, const Vector3
double TexturesRenderer::getMaximalDisplacement(TexturesDefinition *textures) { double TexturesRenderer::getMaximalDisplacement(TexturesDefinition *textures) {
int i, n; int i, n;
double disp = 0.0; double disp = 0.0;
n = textures->count(); n = textures->getLayerCount();
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
TextureLayerDefinition *layer = textures->getTextureLayer(i); TextureLayerDefinition *layer = textures->getTextureLayer(i);
@ -129,7 +129,7 @@ Vector3 TexturesRenderer::displaceTerrain(const TerrainRenderer::TerrainResult &
double offset = 0.0; double offset = 0.0;
int i, n; int i, n;
n = textures->count(); n = textures->getLayerCount();
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
TextureLayerDefinition *layer = textures->getTextureLayer(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 // TODO Displaced textures had their presence already computed before, store that result and use it
// Find presence of each layer // Find presence of each layer
int n = textures->count(); int n = textures->getLayerCount();
int start = 0; int start = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
TexturesLayerResult &layer = result.layers[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) { bool FileSystem::removeFile(const std::string &filepath) {
if (FileSystem::isFile(filepath)) { if (FileSystem::isFile(filepath)) {
remove(filepath.c_str()); 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); 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) { bool PackStream::bindToFile(const std::string &filepath, bool write) {
if (not file) { if (not file) {
file = new QFile(QString::fromStdString(filepath)); 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) { void PackStream::read(int *value) {
if (value and not stream->atEnd()) { if (value and not stream->atEnd()) {
int output; int output;

View file

@ -25,6 +25,11 @@ class SYSTEMSHARED_EXPORT PackStream {
*/ */
PackStream(const PackStream *other); 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); bool bindToFile(const std::string &filepath, bool write = false);
void write(const int *value); void write(const int *value);
@ -41,6 +46,11 @@ class SYSTEMSHARED_EXPORT PackStream {
*/ */
void writeFromBuffer(const PackStream &other, bool prepend_size = false); 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(int *value);
void read(double *value); void read(double *value);
void read(char *value, int max_length); void read(char *value, int max_length);

View file

@ -2,19 +2,21 @@
#include "Layers.h" #include "Layers.h"
#include "PackStream.h" #include "PackStream.h"
#include "DiffManager.h"
#include "IntNode.h"
DefinitionNode *_construc1(Layers *) { static DefinitionNode *_construc1(Layers *, const std::string &name) {
return new DefinitionNode(NULL, "test"); return new DefinitionNode(NULL, name);
} }
DefinitionNode *_construc2(Layers *parent) { static DefinitionNode *_construc2(Layers *parent, const std::string &name) {
DefinitionNode *result = new DefinitionNode(parent, "test"); DefinitionNode *result = new DefinitionNode(parent, name);
return result; return result;
} }
TEST(Layers, Constructor) { TEST(Layers, Constructor) {
Layers layers1(NULL, "test", _construc1); Layers layers1(NULL, "test", _construc1);
EXPECT_EQ(0, layers1.count()); EXPECT_EQ(0, layers1.getLayerCount());
} }
TEST(Layers, NullLayer) { TEST(Layers, NullLayer) {
@ -27,22 +29,22 @@ TEST(Layers, NullLayer) {
EXPECT_EQ(NULL, layer->getParent()); EXPECT_EQ(NULL, layer->getParent());
EXPECT_EQ(layer, layer->getRoot()); 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) { TEST(Layers, copy) {
Layers layers1(NULL, "test", _construc2); Layers layers1(NULL, "test", _construc2);
layers1.addLayer(); layers1.addLayer("test");
EXPECT_EQ(1, layers1.count()); EXPECT_EQ(1, layers1.getLayerCount());
// Copy with the same constructor // Copy with the same constructor
Layers layers2(NULL, "test", _construc2); Layers layers2(NULL, "test", _construc2);
EXPECT_EQ(0, layers2.count()); EXPECT_EQ(0, layers2.getLayerCount());
layers1.copy(&layers2); layers1.copy(&layers2);
EXPECT_EQ(1, layers2.count()); EXPECT_EQ(1, layers2.getLayerCount());
EXPECT_EQ("test", layers1.getLayer(0)->getName()); EXPECT_EQ("test", layers1.getLayer(0)->getName());
EXPECT_EQ(&layers1, layers1.getLayer(0)->getParent()); EXPECT_EQ(&layers1, layers1.getLayer(0)->getParent());
EXPECT_EQ("test", layers2.getLayer(0)->getName()); EXPECT_EQ("test", layers2.getLayer(0)->getName());
@ -54,32 +56,35 @@ TEST(Layers, maxLayerCount) {
Layers layers1(NULL, "test", _construc1); Layers layers1(NULL, "test", _construc1);
layers1.setMaxLayerCount(2); layers1.setMaxLayerCount(2);
EXPECT_EQ(0, layers1.count()); EXPECT_EQ(0, layers1.getLayerCount());
layers1.addLayer(); layers1.addLayer("t1");
EXPECT_EQ(1, layers1.count()); EXPECT_EQ(1, layers1.getLayerCount());
layers1.addLayer(); layers1.addLayer("t2");
EXPECT_EQ(2, layers1.count()); EXPECT_EQ(2, layers1.getLayerCount());
layers1.addLayer(); layers1.addLayer("t3");
EXPECT_EQ(2, layers1.count()); EXPECT_EQ(2, layers1.getLayerCount());
layers1.addLayer(); layers1.addLayer("t4");
EXPECT_EQ(2, layers1.count()); EXPECT_EQ(2, layers1.getLayerCount());
layers1.removeLayer(0); layers1.removeLayer(0);
EXPECT_EQ(1, layers1.count()); EXPECT_EQ(1, layers1.getLayerCount());
layers1.addLayer(); layers1.addLayer("t5");
EXPECT_EQ(2, layers1.count()); EXPECT_EQ(2, layers1.getLayerCount());
layers1.addLayer(); layers1.addLayer("t6");
EXPECT_EQ(2, layers1.count()); EXPECT_EQ(2, layers1.getLayerCount());
layers1.setMaxLayerCount(1);
EXPECT_EQ(1, layers1.getLayerCount());
layers1.setMaxLayerCount(0);
EXPECT_EQ(0, layers1.getLayerCount());
} }
TEST(Layers, saveLoad) { TEST(Layers, saveLoad) {
PackStream *stream; PackStream *stream;
Layers layers1(NULL, "test", _construc1); Layers layers1(NULL, "test", _construc1);
layers1.addLayer(); layers1.addLayer("first");
layers1.addLayer(); layers1.addLayer("second");
ASSERT_EQ(2, layers1.count()); ASSERT_EQ(2, layers1.getLayerCount());
layers1.getLayer(0)->setName("first");
layers1.getLayer(1)->setName("second");
stream = new PackStream(); stream = new PackStream();
stream->bindToFile("/tmp/test_paysages_pack", true); stream->bindToFile("/tmp/test_paysages_pack", true);
@ -93,7 +98,99 @@ TEST(Layers, saveLoad) {
layers2.load(stream); layers2.load(stream);
delete stream; delete stream;
ASSERT_EQ(2, layers2.count()); ASSERT_EQ(2, layers2.getLayerCount());
EXPECT_EQ("first", layers2.getLayer(0)->getName()); EXPECT_EQ("first", layers2.getLayer(0)->getName());
EXPECT_EQ("second", layers2.getLayer(1)->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());
}