Added IntNode, IntPropertyBind, PanelPictureChoice and /water/model property

This commit is contained in:
Michaël Lemaire 2015-09-08 23:52:34 +02:00
parent 982af74c2d
commit 647e185e52
25 changed files with 534 additions and 57 deletions

View file

@ -0,0 +1,7 @@
#include "IntDiff.h"
IntDiff::IntDiff(const DefinitionNode *node, int oldvalue, int newvalue):
DefinitionDiff(node), oldvalue(oldvalue), newvalue(newvalue)
{
}

30
src/definition/IntDiff.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef INTDIFF_H
#define INTDIFF_H
#include "definition_global.h"
#include "DefinitionDiff.h"
namespace paysages {
namespace definition {
/**
* Diff for an IntNode.
*/
class DEFINITIONSHARED_EXPORT IntDiff: public DefinitionDiff
{
public:
IntDiff(const DefinitionNode *node, int oldvalue, int newvalue);
inline int getOldValue() const {return oldvalue;}
inline int getNewValue() const {return newvalue;}
private:
int oldvalue;
int newvalue;
};
}
}
#endif // INTDIFF_H

View file

@ -0,0 +1,83 @@
#include "IntNode.h"
#include "PackStream.h"
#include "IntDiff.h"
#include "Logs.h"
#include <sstream>
#include <cassert>
IntNode::IntNode(DefinitionNode* parent, const std::string &name, int value):
DefinitionNode(parent, name, "int"), value(value)
{
}
std::string IntNode::toString(int indent) const
{
std::ostringstream stream;
stream << DefinitionNode::toString(indent) << " " << value;
return stream.str();
}
void IntNode::save(PackStream *stream) const
{
stream->write(&value);
}
void IntNode::load(PackStream *stream)
{
stream->read(&value);
}
void IntNode::copy(DefinitionNode *destination) const
{
if (destination->getTypeName() == getTypeName())
{
((IntNode *)destination)->value = value;
}
else
{
Logs::error() << "Can't copy from " << getTypeName() << " to " << destination->getTypeName() << std::endl;
}
}
void IntNode::setValue(int new_value)
{
addDiff(produceDiff(new_value));
}
const IntDiff *IntNode::produceDiff(int new_value) const
{
return new IntDiff(this, value, new_value);
}
void IntNode::generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const
{
diffs->push_back(produceDiff(value));
}
bool IntNode::applyDiff(const DefinitionDiff *diff, bool backward)
{
if (!DefinitionNode::applyDiff(diff, backward))
{
return false;
}
assert(diff->getTypeName() == "int");
const IntDiff *int_diff = (const IntDiff *)diff;
double previous = backward ? int_diff->getNewValue() : int_diff->getOldValue();
double next = backward ? int_diff->getOldValue() : int_diff->getNewValue();
if (value == previous)
{
value = next;
return true;
}
else
{
Logs::error() << "Can't apply int diff " << previous << " => " << next << " to " << getName() << std::endl;
return false;
}
}

43
src/definition/IntNode.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef INTNODE_H
#define INTNODE_H
#include "definition_global.h"
#include "DefinitionNode.h"
namespace paysages {
namespace definition {
/**
* Node with a single integer value, for the definition tree.
*/
class DEFINITIONSHARED_EXPORT IntNode: public DefinitionNode
{
public:
IntNode(DefinitionNode* parent, const std::string &name, int value = 0);
inline int getValue() const {return value;}
virtual std::string toString(int indent) const override;
virtual void save(PackStream* stream) const override;
virtual void load(PackStream* stream) override;
virtual void copy(DefinitionNode* destination) const override;
/**
* Change the int value stored.
*
* The DiffManager is used as intermediary, so that the change may not happen immediately.
*/
void setValue(int new_value);
const IntDiff *produceDiff(int new_value) const;
void generateInitDiffs(std::vector<const DefinitionDiff *> *diffs) const;
virtual bool applyDiff(const DefinitionDiff *diff, bool backward=false) override;
private:
int value;
};
}
}
#endif // INTNODE_H

View file

@ -4,11 +4,13 @@
#include "NoiseState.h"
#include "Color.h"
#include "SurfaceMaterial.h"
#include "IntNode.h"
#include "FloatNode.h"
WaterDefinition::WaterDefinition(DefinitionNode* parent):
DefinitionNode(parent, "water", "water")
{
model = new IntNode(this, "model", -1);
reflection = new FloatNode(this, "reflection");
material = new SurfaceMaterial;
@ -24,6 +26,8 @@ WaterDefinition::WaterDefinition(DefinitionNode* parent):
detail_height = 0.0;
turbulence = 0.0;
foam_coverage = 0.0;
model->addWatcher(this, true);
}
WaterDefinition::~WaterDefinition()
@ -101,47 +105,6 @@ void WaterDefinition::validate()
{
DefinitionNode::validate();
material->validate();
foam_material->validate();
}
void WaterDefinition::applyPreset(WaterPreset preset)
{
noise_state->randomizeOffsets();
if (preset == WATER_PRESET_LAKE)
{
transparency = 0.5;
reflection->setValue(0.2);
transparency_depth = 4.0;
material->setColor(0.08, 0.15, 0.2, 1.0);
depth_color->r = 0.0;
depth_color->g = 0.1;
depth_color->b = 0.1;
lighting_depth = 6.0;
scaling = 1.0;
waves_height = 0.8;
detail_height = 0.05;
turbulence = 0.1;
foam_coverage = 0.15;
}
else if (preset == WATER_PRESET_SEA)
{
transparency = 0.3;
reflection->setValue(0.07);
transparency_depth = 3.0;
material->setColor(0.05, 0.18, 0.2, 1.0);
depth_color->r = 0.0;
depth_color->g = 0.18;
depth_color->b = 0.15;
lighting_depth = 4.0;
scaling = 1.5;
waves_height = 1.0;
detail_height = 0.06;
turbulence = 0.3;
foam_coverage = 0.4;
}
depth_color->a = 1.0;
material->base->a = 1.0;
material->reflection = 1.0;
@ -152,5 +115,61 @@ void WaterDefinition::applyPreset(WaterPreset preset)
foam_material->shininess = 1.5;
foam_material->hardness = 0.2;
validate();
material->validate();
foam_material->validate();
}
void WaterDefinition::nodeChanged(const DefinitionNode *node, const DefinitionDiff *)
{
if (node == model)
{
noise_state->randomizeOffsets();
switch (model->getValue())
{
case 1:
transparency = 0.3;
reflection->setValue(0.07);
transparency_depth = 3.0;
material->setColor(0.05, 0.18, 0.2, 1.0);
depth_color->r = 0.0;
depth_color->g = 0.18;
depth_color->b = 0.15;
lighting_depth = 4.0;
scaling = 1.5;
waves_height = 1.0;
detail_height = 0.06;
turbulence = 0.3;
foam_coverage = 0.4;
break;
case 0:
default:
transparency = 0.5;
reflection->setValue(0.2);
transparency_depth = 4.0;
material->setColor(0.08, 0.15, 0.2, 1.0);
depth_color->r = 0.0;
depth_color->g = 0.1;
depth_color->b = 0.1;
lighting_depth = 6.0;
scaling = 1.0;
waves_height = 0.8;
detail_height = 0.05;
turbulence = 0.1;
foam_coverage = 0.15;
break;
}
}
}
void WaterDefinition::applyPreset(WaterPreset preset)
{
if (preset == WATER_PRESET_LAKE)
{
model->setValue(0);
}
else if (preset == WATER_PRESET_SEA)
{
model->setValue(1);
}
}

View file

@ -4,11 +4,12 @@
#include "definition_global.h"
#include "DefinitionNode.h"
#include "DefinitionWatcher.h"
namespace paysages {
namespace definition {
class DEFINITIONSHARED_EXPORT WaterDefinition: public DefinitionNode
class DEFINITIONSHARED_EXPORT WaterDefinition: public DefinitionNode, public DefinitionWatcher
{
public:
WaterDefinition(DefinitionNode* parent);
@ -20,9 +21,11 @@ public:
virtual void copy(DefinitionNode* destination) const override;
virtual void validate() override;
inline IntNode *propModel() const {return model;}
inline FloatNode *propReflection() const {return reflection;}
public:
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff);
typedef enum
{
WATER_PRESET_LAKE,
@ -48,6 +51,7 @@ public:
NoiseState* noise_state;
private:
IntNode *model;
FloatNode *reflection;
};

View file

@ -35,7 +35,9 @@ SOURCES += \
DefinitionDiff.cpp \
FloatDiff.cpp \
DiffManager.cpp \
DefinitionWatcher.cpp
DefinitionWatcher.cpp \
IntNode.cpp \
IntDiff.cpp
HEADERS +=\
definition_global.h \
@ -60,7 +62,9 @@ HEADERS +=\
DefinitionDiff.h \
FloatDiff.h \
DiffManager.h \
DefinitionWatcher.h
DefinitionWatcher.h \
IntNode.h \
IntDiff.h
unix:!symbian {
maemo5 {

View file

@ -17,6 +17,8 @@ namespace definition {
class DefinitionDiff;
class FloatNode;
class FloatDiff;
class IntNode;
class IntDiff;
class DiffManager;
class DefinitionWatcher;
class Scenery;

View file

@ -4,7 +4,6 @@
#include "FloatNode.h"
#include "Logs.h"
#include <cassert>
#include <cmath>
FloatPropertyBind::FloatPropertyBind(MainModelerWindow *window, const QString &object_name, const QString &property_name, FloatNode *node):

View file

@ -0,0 +1,37 @@
#include "IntPropertyBind.h"
#include "MainModelerWindow.h"
#include "IntNode.h"
#include "Logs.h"
IntPropertyBind::IntPropertyBind(MainModelerWindow *window, const QString &object_name, const QString &property_name, IntNode *node):
QObject(window), node(node), property(property_name)
{
item = window->findQmlObject(object_name);
if (item)
{
node->addWatcher(this, true);
connect(item, SIGNAL(changed(int)), this, SLOT(propertyChanged(int)));
}
else
{
item = NULL;
Logs::error() << "Can't find object :" << object_name.toStdString() << std::endl;
}
}
void IntPropertyBind::nodeChanged(const DefinitionNode *, const DefinitionDiff *)
{
if (item)
{
item->setProperty(property.toLocal8Bit(), node->getValue());
}
}
void IntPropertyBind::propertyChanged(int value)
{
if (value != node->getValue())
{
node->setValue(value);
}
}

View file

@ -0,0 +1,36 @@
#ifndef INTPROPERTYBIND_H
#define INTPROPERTYBIND_H
#include "modeler_global.h"
#include <QObject>
#include "DefinitionWatcher.h"
namespace paysages {
namespace modeler {
/**
* Bind an int Qml property to an IntNode.
*
* The IntNode must exist through this object lifetime.
*/
class IntPropertyBind : public QObject, public DefinitionWatcher
{
Q_OBJECT
public:
IntPropertyBind(MainModelerWindow *window, const QString &object_name, const QString &property_name, IntNode *node);
virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override;
private slots:
void propertyChanged(int value);
private:
IntNode *node;
QString property;
QObject *item;
};
}
}
#endif // INTPROPERTYBIND_H

View file

@ -5,6 +5,7 @@
#include "TerrainDefinition.h"
#include "WaterDefinition.h"
#include "FloatPropertyBind.h"
#include "IntPropertyBind.h"
#include "OpenGLRenderer.h"
#include "OpenGLWater.h"
@ -17,14 +18,16 @@ WaterModeler::WaterModeler(MainModelerWindow *ui):
connect(toggle_water, SIGNAL(toggled(bool)), this, SLOT(enableRendering(bool)));
}
prop_water_height = new FloatPropertyBind(ui, "water_height", "value", ui->getScenery()->getTerrain()->propWaterHeight());
prop_water_reflexion = new FloatPropertyBind(ui, "water_reflection", "value", ui->getScenery()->getWater()->propReflection());
prop_model = new IntPropertyBind(ui, "water_model", "value", ui->getScenery()->getWater()->propModel());
prop_height = new FloatPropertyBind(ui, "water_height", "value", ui->getScenery()->getTerrain()->propWaterHeight());
prop_reflexion = new FloatPropertyBind(ui, "water_reflection", "value", ui->getScenery()->getWater()->propReflection());
}
WaterModeler::~WaterModeler()
{
delete prop_water_height;
delete prop_water_reflexion;
delete prop_model;
delete prop_height;
delete prop_reflexion;
}
void WaterModeler::enableRendering(bool enable)

View file

@ -20,8 +20,9 @@ public slots:
private:
MainModelerWindow *ui;
FloatPropertyBind *prop_water_height;
FloatPropertyBind *prop_water_reflexion;
IntPropertyBind *prop_model;
FloatPropertyBind *prop_height;
FloatPropertyBind *prop_reflexion;
};
}

View file

@ -19,6 +19,7 @@ namespace modeler {
class ModelerCameras;
class FloatPropertyBind;
class IntPropertyBind;
}
}

View file

@ -0,0 +1,48 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
// Panel with a selection of pictures to choose from
// Mainly used for presets or models
BasePanel {
id: panel
property alias items: container.children
property int value: -1
width: items[0].width + 10
signal changed(int value)
ExclusiveGroup {
id: exclusive_item
onCurrentChanged: {
if (current) {
panel.value = current.position;
} else {
panel.value = -1;
}
}
}
onValueChanged: {
if (!exclusive_item.current || exclusive_item.current.position !== panel.value) {
if (panel.value >= 0) {
exclusive_item.current = items[panel.value];
} else {
exclusive_item.current = null;
}
}
changed(value);
}
onItemsChanged: {
for (var i = 0; i < items.length; i++) {
items[i].exclusiveGroup = exclusive_item;
items[i].position = i;
}
}
Column {
id: container
anchors.centerIn: panel
}
}

View file

@ -0,0 +1,7 @@
import QtQuick 2.0
ToolbarButton {
property int position: -1
image_width: 128
image_height: 128
}

View file

@ -13,6 +13,8 @@ Item {
property string helptext
property string hovertext
property string shortcut
property alias image_width: image.width
property alias image_height: image.height
signal clicked
signal toggled(bool value)

View file

@ -7,6 +7,12 @@ BaseSection {
BaseToolbar {
id: toolbar
ToolbarButton {
id: tool_water_preset
picture: "images/icon_preset.png"
hovertext: qsTr("Choose a water model")
}
ToolbarButton {
id: tool_water_level
checked: true
@ -16,12 +22,28 @@ BaseSection {
ToolbarButton {
id: tool_water_reflection
checked: false
picture: "images/icon_water_reflection.png"
hovertext: qsTr("Reflection of the water surface")
}
}
PanelPictureChoice {
id: panel_water_preset
enabled: false
anchors.left: toolbar.right
objectName: "water_model"
items: [
PictureChoiceItem {
picture: "images/preset_water_lake.jpg"
hovertext: "Water model : Lake"
},
PictureChoiceItem {
picture: "images/preset_water_sea.jpg"
hovertext: "Water model : Sea"
}
]
}
PanelSimpleFloat {
id: panel_water_level
enabled: false
@ -39,6 +61,14 @@ BaseSection {
}
states: [
State {
name: "WaterPreset"
when: tool_water_preset.checked
PropertyChanges {
target: panel_water_preset
enabled: true
}
},
State {
name: "WaterHeight"
when: tool_water_level.checked

View file

@ -44,5 +44,10 @@
<file>AtmosphereSection.qml</file>
<file>PanelSimpleFloat.qml</file>
<file>images/icon_water_reflection.png</file>
<file>PanelPictureChoice.qml</file>
<file>PictureChoiceItem.qml</file>
<file>images/preset_water_lake.jpg</file>
<file>images/preset_water_sea.jpg</file>
<file>images/icon_preset.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -12,7 +12,8 @@ SOURCES += main.cpp \
RenderPreviewProvider.cpp \
RenderProcess.cpp \
ModelerCameras.cpp \
FloatPropertyBind.cpp
FloatPropertyBind.cpp \
IntPropertyBind.cpp
RESOURCES += \
qml/app.qrc
@ -34,7 +35,8 @@ HEADERS += \
RenderPreviewProvider.h \
RenderProcess.h \
ModelerCameras.h \
FloatPropertyBind.h
FloatPropertyBind.h \
IntPropertyBind.h
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../system/release/ -lpaysages_system
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../system/debug/ -lpaysages_system

113
src/tests/IntNode_Test.cpp Normal file
View file

@ -0,0 +1,113 @@
#include "BaseTestCase.h"
#include "IntNode.h"
#include "IntDiff.h"
#include "PackStream.h"
TEST(IntNode, toString)
{
IntNode test(NULL, "test", 2);
EXPECT_EQ("test 2", test.toString(0));
EXPECT_EQ(" test 2", test.toString(2));
}
TEST(IntNode, saveLoadAndSkip)
{
DefinitionNode root1(NULL, "root");
IntNode testa1(&root1, "testa", 1);
IntNode testb1(&root1, "testb", 4);
PackStream stream1;
root1.save(&stream1);
DefinitionNode root2(NULL, "root");
IntNode testb2(&root2, "testb");
PackStream stream2(&stream1);
root2.load(&stream2);
EXPECT_DOUBLE_EQ(4, testb2.getValue());
}
TEST(IntNode, copy)
{
IntNode base(NULL, "test", 2);
IntNode other(NULL, "test", 4);
DefinitionNode badother(NULL, "test");
base.copy(&other);
EXPECT_DOUBLE_EQ(2, base.getValue());
EXPECT_DOUBLE_EQ(2, other.getValue());
badother.copy(&base);
EXPECT_DOUBLE_EQ(2, base.getValue());
base.copy(&badother);
// can't check anything, just useful in valgrind
}
TEST(IntNode, produceDiff)
{
IntNode node(NULL, "test", 8);
const IntDiff *diff = node.produceDiff(-4);
EXPECT_EQ("int", diff->getTypeName());
EXPECT_DOUBLE_EQ(8, diff->getOldValue());
EXPECT_DOUBLE_EQ(-4, diff->getNewValue());
bool result = node.applyDiff(diff);
EXPECT_TRUE(result);
EXPECT_DOUBLE_EQ(-4, node.getValue());
delete diff;
}
TEST(IntNode, applyDiff)
{
IntNode node(NULL, "test", 1);
IntDiff diff(&node, 1, 2);
DefinitionNode onode(NULL, "test", "badtype");
DefinitionDiff odiff(&onode);
bool result;
EXPECT_DOUBLE_EQ(1, node.getValue());
// apply
result = node.applyDiff(&diff);
EXPECT_TRUE(result);
EXPECT_DOUBLE_EQ(2, node.getValue());
// can't apply twice
result = node.applyDiff(&diff);
EXPECT_FALSE(result);
EXPECT_DOUBLE_EQ(2, node.getValue());
// reverse
result = node.applyDiff(&diff, true);
EXPECT_TRUE(result);
EXPECT_DOUBLE_EQ(1, node.getValue());
// can't reverse twice
result = node.applyDiff(&diff, true);
EXPECT_FALSE(result);
EXPECT_DOUBLE_EQ(1, node.getValue());
// bad type
result = node.applyDiff(&odiff);
EXPECT_FALSE(result);
EXPECT_DOUBLE_EQ(1, node.getValue());
// apply again
result = node.applyDiff(&diff);
EXPECT_TRUE(result);
EXPECT_DOUBLE_EQ(2, node.getValue());
}

View file

@ -27,7 +27,8 @@ SOURCES += main.cpp \
FloatNode_Test.cpp \
DiffManager_Test.cpp \
ColorHSL_Test.cpp \
RenderProgress_Test.cpp
RenderProgress_Test.cpp \
IntNode_Test.cpp
HEADERS += \
BaseTestCase.h