Changed: #1301 Added load landscape from file. Added initial snapshot dialog.
This commit is contained in:
parent
9f25454f4f
commit
7351dcd33c
19 changed files with 793 additions and 72 deletions
|
@ -17,11 +17,13 @@ SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_HDR landscape_editor_plugin.h
|
|||
landscape_actions.h
|
||||
landscape_view.h
|
||||
project_settings_dialog.h
|
||||
snapshot_dialog.h
|
||||
)
|
||||
|
||||
SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS landscape_editor_window.ui
|
||||
list_zones_widget.ui
|
||||
project_settings_dialog.ui
|
||||
shapshot_dialog.ui
|
||||
)
|
||||
|
||||
SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_RCS landscape_editor.qrc)
|
||||
|
|
|
@ -36,35 +36,6 @@
|
|||
namespace LandscapeEditor
|
||||
{
|
||||
|
||||
// Data
|
||||
struct LigoData
|
||||
{
|
||||
uint32 PosX;
|
||||
uint32 PosY;
|
||||
qreal Scale;
|
||||
uint8 Rot;
|
||||
uint8 Flip;
|
||||
std::string ZoneName;
|
||||
std::string SharingMatNames[4];
|
||||
uint8 SharingCutEdges[4];
|
||||
bool operator!= (const LigoData& other) const
|
||||
{
|
||||
return (PosX != other.PosX) ||
|
||||
(PosY != other.PosY) ||
|
||||
(Rot != other.Rot) ||
|
||||
(Flip != other.Flip) ||
|
||||
(ZoneName != other.ZoneName) ||
|
||||
(SharingMatNames[0] != other.SharingMatNames[0]) ||
|
||||
(SharingMatNames[1] != other.SharingMatNames[1]) ||
|
||||
(SharingMatNames[2] != other.SharingMatNames[2]) ||
|
||||
(SharingMatNames[3] != other.SharingMatNames[3]) ||
|
||||
(SharingCutEdges[0] != other.SharingCutEdges[0]) ||
|
||||
(SharingCutEdges[1] != other.SharingCutEdges[1]) ||
|
||||
(SharingCutEdges[2] != other.SharingCutEdges[2]) ||
|
||||
(SharingCutEdges[3] != other.SharingCutEdges[3]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@class PixmapDatabase
|
||||
@brief PixmapDatabase contains the image database
|
||||
|
|
|
@ -62,34 +62,54 @@ void NewLandscapeCommand::redo()
|
|||
{
|
||||
}
|
||||
|
||||
LigoTileCommand::LigoTileCommand(const LigoData &data, ZoneBuilder *zoneBuilder, QGraphicsScene *scene, QUndoCommand *parent)
|
||||
AddLigoTileCommand::AddLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent)
|
||||
: QUndoCommand(parent),
|
||||
m_item(0),
|
||||
m_zoneBuilder(zoneBuilder),
|
||||
m_scene(scene)
|
||||
{
|
||||
m_ligoData = data;
|
||||
}
|
||||
|
||||
LigoTileCommand::~LigoTileCommand()
|
||||
AddLigoTileCommand::~AddLigoTileCommand()
|
||||
{
|
||||
}
|
||||
|
||||
void LigoTileCommand::undo()
|
||||
void AddLigoTileCommand::undo()
|
||||
{
|
||||
m_scene->removeItem(m_item);
|
||||
delete m_item;
|
||||
m_item = 0;
|
||||
}
|
||||
|
||||
void LigoTileCommand::redo()
|
||||
void AddLigoTileCommand::redo()
|
||||
{
|
||||
QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(m_ligoData.ZoneName.c_str()));
|
||||
m_item = new QGraphicsPixmapItem(*pixmap, 0, m_scene);
|
||||
m_item->setPos(m_ligoData.PosX, m_ligoData.PosY);
|
||||
m_item->setScale(m_ligoData.Scale);
|
||||
m_item->setTransformationMode(Qt::SmoothTransformation);
|
||||
m_item = m_scene->createZoneItem(m_ligoData);
|
||||
setText(QObject::tr("Add tile(%1, %2)").arg(m_ligoData.PosX).arg(m_ligoData.PosY));
|
||||
}
|
||||
|
||||
DelLigoTileCommand::DelLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent)
|
||||
: QUndoCommand(parent),
|
||||
m_item(0),
|
||||
m_scene(scene)
|
||||
{
|
||||
m_ligoData = data;
|
||||
}
|
||||
|
||||
DelLigoTileCommand::~DelLigoTileCommand()
|
||||
{
|
||||
}
|
||||
|
||||
void DelLigoTileCommand::undo()
|
||||
{
|
||||
m_item = m_scene->createZoneItem(m_ligoData);
|
||||
}
|
||||
|
||||
void DelLigoTileCommand::redo()
|
||||
{
|
||||
m_item = m_scene->itemAt(m_ligoData.PosX * m_scene->cellSize(), m_ligoData.PosY * m_scene->cellSize());
|
||||
delete m_item;
|
||||
m_item = 0;
|
||||
setText(QObject::tr("Del tile(%1, %2)").arg(m_ligoData.PosX).arg(m_ligoData.PosY));
|
||||
}
|
||||
|
||||
} /* namespace LandscapeEditor */
|
||||
|
|
|
@ -20,23 +20,24 @@
|
|||
|
||||
// Project includes
|
||||
#include "builder_zone.h"
|
||||
#include "landscape_scene.h"
|
||||
|
||||
// NeL includes
|
||||
|
||||
// Qt includes
|
||||
#include <QtGui/QUndoCommand>
|
||||
#include <QtGui/QGraphicsScene>
|
||||
#include <QtGui/QGraphicsPixmapItem>
|
||||
#include <QtGui/QGraphicsItem>
|
||||
|
||||
namespace LandscapeEditor
|
||||
{
|
||||
class ZoneBuilder;
|
||||
|
||||
class OpenLandscapeCommand: public QUndoCommand
|
||||
{
|
||||
public:
|
||||
OpenLandscapeCommand(const QString &fileName, QUndoCommand *parent = 0);
|
||||
~OpenLandscapeCommand();
|
||||
virtual ~OpenLandscapeCommand();
|
||||
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
private:
|
||||
|
@ -48,17 +49,18 @@ class NewLandscapeCommand: public QUndoCommand
|
|||
{
|
||||
public:
|
||||
NewLandscapeCommand(QUndoCommand *parent = 0);
|
||||
~NewLandscapeCommand();
|
||||
virtual ~NewLandscapeCommand();
|
||||
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
private:
|
||||
};
|
||||
|
||||
class LigoTileCommand: public QUndoCommand
|
||||
class AddLigoTileCommand: public QUndoCommand
|
||||
{
|
||||
public:
|
||||
LigoTileCommand(const LigoData &data, ZoneBuilder *zoneBuilder, QGraphicsScene *scene, QUndoCommand *parent = 0);
|
||||
~LigoTileCommand();
|
||||
AddLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent = 0);
|
||||
virtual ~AddLigoTileCommand();
|
||||
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
@ -66,9 +68,24 @@ public:
|
|||
private:
|
||||
|
||||
LigoData m_ligoData;
|
||||
QGraphicsPixmapItem *m_item;
|
||||
ZoneBuilder *m_zoneBuilder;
|
||||
QGraphicsScene *m_scene;
|
||||
QGraphicsItem *m_item;
|
||||
LandscapeScene *m_scene;
|
||||
};
|
||||
|
||||
class DelLigoTileCommand: public QUndoCommand
|
||||
{
|
||||
public:
|
||||
DelLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent = 0);
|
||||
virtual ~DelLigoTileCommand();
|
||||
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
private:
|
||||
|
||||
LigoData m_ligoData;
|
||||
QGraphicsItem *m_item;
|
||||
LandscapeScene *m_scene;
|
||||
};
|
||||
|
||||
} /* namespace LandscapeEditor */
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "builder_zone.h"
|
||||
#include "landscape_scene.h"
|
||||
#include "project_settings_dialog.h"
|
||||
#include "snapshot_dialog.h"
|
||||
|
||||
#include "../core/icore.h"
|
||||
#include "../core/imenu_manager.h"
|
||||
|
@ -51,6 +52,7 @@ LandscapeEditorWindow::LandscapeEditorWindow(QWidget *parent)
|
|||
|
||||
m_landscapeScene = new LandscapeScene(m_undoStack, m_ui.zoneListWidget, m_zoneBuilder, this);
|
||||
m_ui.graphicsView->setScene(m_landscapeScene);
|
||||
//m_ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer)));
|
||||
m_ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers)));
|
||||
|
||||
createMenus();
|
||||
|
@ -58,6 +60,7 @@ LandscapeEditorWindow::LandscapeEditorWindow(QWidget *parent)
|
|||
readSettings();
|
||||
|
||||
connect(m_ui.projectSettingsAction, SIGNAL(triggered()), this, SLOT(openProjectSettings()));
|
||||
connect(m_ui.snapshotAction, SIGNAL(triggered()), this, SLOT(openSnapshotDialog()));
|
||||
connect(m_ui.enableGridAction, SIGNAL(toggled(bool)), m_ui.graphicsView, SLOT(setVisibleGrid(bool)));
|
||||
}
|
||||
|
||||
|
@ -83,6 +86,14 @@ void LandscapeEditorWindow::open()
|
|||
{
|
||||
QStringList list = fileNames;
|
||||
_lastDir = QFileInfo(list.front()).absolutePath();
|
||||
Q_FOREACH(QString fileName, fileNames)
|
||||
{
|
||||
m_zoneRegionEditor.load(fileName.toStdString());
|
||||
m_landscapeScene->processZoneRegion(m_zoneRegionEditor.zoneRegion());
|
||||
m_landscapeScene->setCurrentZoneRegion(&m_zoneRegionEditor.zoneRegion());
|
||||
m_ui.graphicsView->centerOn(m_zoneRegionEditor.zoneRegion().getMinX() * m_landscapeScene->cellSize(),
|
||||
abs(m_zoneRegionEditor.zoneRegion().getMinY()) * m_landscapeScene->cellSize());
|
||||
}
|
||||
}
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
@ -100,6 +111,24 @@ void LandscapeEditorWindow::openProjectSettings()
|
|||
delete dialog;
|
||||
}
|
||||
|
||||
void LandscapeEditorWindow::openSnapshotDialog()
|
||||
{
|
||||
SnapshotDialog *dialog = new SnapshotDialog(this);
|
||||
dialog->show();
|
||||
int ok = dialog->exec();
|
||||
if (ok == QDialog::Accepted)
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this,
|
||||
tr("Save screenshot landscape"), _lastDir,
|
||||
tr("Image file (*.png)"));
|
||||
|
||||
setCursor(Qt::WaitCursor);
|
||||
m_landscapeScene->snapshot(fileName, 128);
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
delete dialog;
|
||||
}
|
||||
|
||||
void LandscapeEditorWindow::createMenus()
|
||||
{
|
||||
Core::IMenuManager *menuManager = Core::ICore::instance()->menuManager();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
// Project includes
|
||||
#include "ui_landscape_editor_window.h"
|
||||
#include "zone_region_editor.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QtGui/QUndoStack>
|
||||
|
@ -46,6 +47,7 @@ public Q_SLOTS:
|
|||
|
||||
private Q_SLOTS:
|
||||
void openProjectSettings();
|
||||
void openSnapshotDialog();
|
||||
|
||||
private:
|
||||
void createMenus();
|
||||
|
@ -53,6 +55,8 @@ private:
|
|||
void readSettings();
|
||||
void writeSettings();
|
||||
|
||||
ZoneRegionEditor m_zoneRegionEditor;
|
||||
|
||||
LandscapeScene *m_landscapeScene;
|
||||
ZoneBuilder *m_zoneBuilder;
|
||||
QUndoStack *m_undoStack;
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="snapshotAction"/>
|
||||
<addaction name="projectSettingsAction"/>
|
||||
<addaction name="enableGridAction"/>
|
||||
</widget>
|
||||
|
@ -101,6 +102,11 @@
|
|||
<string>Ctrl+G</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="snapshotAction">
|
||||
<property name="text">
|
||||
<string>snapshot</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
// Qt includes
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QGraphicsPixmapItem>
|
||||
#include <QtGui/QGraphicsSimpleTextItem>
|
||||
|
||||
namespace LandscapeEditor
|
||||
{
|
||||
|
@ -35,7 +36,8 @@ LandscapeScene::LandscapeScene(QUndoStack *undoStack, ListZonesWidget *listZones
|
|||
: QGraphicsScene(parent),
|
||||
m_undoStack(undoStack),
|
||||
m_listZonesWidget(listZonesWidget),
|
||||
m_zoneBuilder(zoneBuilder)
|
||||
m_zoneBuilder(zoneBuilder),
|
||||
m_zoneRegion(0)
|
||||
{
|
||||
m_cellSize = 160;
|
||||
}
|
||||
|
@ -44,27 +46,167 @@ LandscapeScene::~LandscapeScene()
|
|||
{
|
||||
}
|
||||
|
||||
void LandscapeScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||
int LandscapeScene::cellSize() const
|
||||
{
|
||||
if (mouseEvent->button() != Qt::LeftButton)
|
||||
return m_cellSize;
|
||||
}
|
||||
|
||||
QGraphicsItem *LandscapeScene::createZoneItem(const LigoData &data)
|
||||
{
|
||||
// Get image from pixmap database
|
||||
QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(data.ZoneName.c_str()));
|
||||
if (pixmap == 0)
|
||||
return 0;
|
||||
|
||||
// Rotate the image counterclockwise
|
||||
QMatrix matrix;
|
||||
matrix.rotate(-data.Rot * 90.0);
|
||||
|
||||
QGraphicsPixmapItem *item;
|
||||
|
||||
if (data.Flip == 0)
|
||||
{
|
||||
item = new QGraphicsPixmapItem(pixmap->transformed(matrix, Qt::SmoothTransformation), 0, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// mirror image
|
||||
QImage mirrorImage = pixmap->toImage();
|
||||
QPixmap mirrorPixmap = QPixmap::fromImage(mirrorImage.mirrored(true, false));
|
||||
item = new QGraphicsPixmapItem(mirrorPixmap.transformed(matrix, Qt::SmoothTransformation), 0, this);
|
||||
}
|
||||
// Enable bilinear filtering
|
||||
item->setTransformationMode(Qt::SmoothTransformation);
|
||||
|
||||
// Set position graphics item with offset for large piece
|
||||
NLLIGO::CZoneBankElement *zoneBankItem = m_zoneBuilder->getZoneBank().getElementByZoneName(data.ZoneName);
|
||||
item->setPos(data.PosX * m_cellSize, (abs(data.PosY) - zoneBankItem->getSizeY() + 1) * m_cellSize);
|
||||
|
||||
// The size graphics item should be equal or proportional m_cellSize
|
||||
item->setScale(m_cellSize / 256.0);
|
||||
|
||||
// add debug info
|
||||
QGraphicsSimpleTextItem *itemText = addSimpleText(QString("%1,%2 R-%3 F-%4").
|
||||
arg(data.PosX).arg(data.PosY).
|
||||
arg(data.Rot * 90.0).
|
||||
arg(data.Flip),
|
||||
QFont("Helvetica [Cronyx]", 14));
|
||||
|
||||
itemText->setZValue(2);
|
||||
itemText->setPos(data.PosX * m_cellSize + 10, (abs(data.PosY) - zoneBankItem->getSizeY() + 1) * m_cellSize + 10);
|
||||
itemText->setBrush(QBrush(Qt::white));
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void LandscapeScene::processZoneRegion(const NLLIGO::CZoneRegion &zoneRegion)
|
||||
{
|
||||
for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i)
|
||||
{
|
||||
for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j)
|
||||
{
|
||||
std::string zoneName = zoneRegion.getName(i, j);
|
||||
if ((!zoneName.empty()) &&
|
||||
(zoneName != STRING_UNUSED) &&
|
||||
(zoneRegion.getPosX(i, j) == 0) &&
|
||||
(zoneRegion.getPosY(i, j) == 0))
|
||||
{
|
||||
LigoData data;
|
||||
data.PosX = i;
|
||||
data.PosY = j;
|
||||
data.ZoneName = zoneName;
|
||||
data.Rot = zoneRegion.getRot(i, j);
|
||||
data.Flip = zoneRegion.getFlip(i, j);
|
||||
QGraphicsItem *item = createZoneItem(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LandscapeScene::setCurrentZoneRegion(NLLIGO::CZoneRegion *zoneRegion)
|
||||
{
|
||||
m_zoneRegion = zoneRegion;
|
||||
}
|
||||
|
||||
void LandscapeScene::snapshot(const QString &fileName, int sizeSource)
|
||||
{
|
||||
if (m_zoneRegion == 0)
|
||||
return;
|
||||
|
||||
sint32 regionMinX = m_zoneRegion->getMinX();
|
||||
sint32 regionMaxX = m_zoneRegion->getMaxX();
|
||||
sint32 regionMinY = m_zoneRegion->getMinY();
|
||||
sint32 regionMaxY = m_zoneRegion->getMaxY();
|
||||
|
||||
int regionWidth = (regionMaxX - regionMinX + 1);
|
||||
int regionHeight = (regionMaxY - regionMinY + 1);
|
||||
|
||||
snapshot(fileName, regionWidth * sizeSource, regionHeight * sizeSource);
|
||||
}
|
||||
|
||||
void LandscapeScene::snapshot(const QString &fileName, int width, int height)
|
||||
{
|
||||
if (m_zoneRegion == 0)
|
||||
return;
|
||||
|
||||
sint32 regionMinX = m_zoneRegion->getMinX();
|
||||
sint32 regionMaxX = m_zoneRegion->getMaxX();
|
||||
sint32 regionMinY = m_zoneRegion->getMinY();
|
||||
sint32 regionMaxY = m_zoneRegion->getMaxY();
|
||||
|
||||
int regionWidth = (regionMaxX - regionMinX + 1);
|
||||
int regionHeight = (regionMaxY - regionMinY + 1);
|
||||
|
||||
QImage image(width, height, QImage::Format_RGB888);
|
||||
QPainter painter(&image);
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
|
||||
// add white background
|
||||
painter.setBrush(QBrush(Qt::white));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRect(0, 0, width, height);
|
||||
|
||||
render(&painter, QRectF(0, 0, width, height),
|
||||
QRectF(regionMinX * m_cellSize, abs(regionMaxY) * m_cellSize, regionWidth * m_cellSize, regionHeight * m_cellSize));
|
||||
|
||||
image.save(fileName);
|
||||
|
||||
}
|
||||
|
||||
void LandscapeScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||
{
|
||||
qreal x = mouseEvent->scenePos().rx();
|
||||
qreal y = mouseEvent->scenePos().ry();
|
||||
if ((x < 0) || (y < 0))
|
||||
return;
|
||||
|
||||
if (mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
// Add new zone brick
|
||||
LigoData ligoData = m_listZonesWidget->currentLigoData();
|
||||
if (ligoData.ZoneName == "")
|
||||
return;
|
||||
|
||||
ligoData.PosX = m_cellSize * int(x / m_cellSize);;
|
||||
ligoData.PosY = m_cellSize * int(y / m_cellSize);
|
||||
ligoData.Scale = m_cellSize / 256.0;
|
||||
ligoData.PosX = int(floor(x / m_cellSize));
|
||||
ligoData.PosY = int(-floor(y / m_cellSize));
|
||||
|
||||
LigoTileCommand *action = new LigoTileCommand(ligoData, m_zoneBuilder, this);
|
||||
AddLigoTileCommand *action = new AddLigoTileCommand(ligoData, this);
|
||||
m_undoStack->push(action);
|
||||
}
|
||||
|
||||
/*if (mouseEvent->button() == Qt::RightButton)
|
||||
{
|
||||
// Delete zone brick
|
||||
LigoData ligoData;
|
||||
|
||||
ligoData.PosX = int(floor(x / m_cellSize));
|
||||
ligoData.PosY = int(floor(y / m_cellSize));
|
||||
ligoData.ZoneName = m_zoneRegion->getName(ligoData.PosX, -ligoData.PosY);
|
||||
ligoData.Flip = m_zoneRegion->getFlip(ligoData.PosX, -ligoData.PosY);
|
||||
ligoData.Rot = m_zoneRegion->getRot(ligoData.PosX, -ligoData.PosY);
|
||||
DelLigoTileCommand *action = new DelLigoTileCommand(ligoData, this);
|
||||
m_undoStack->push(action);
|
||||
}*/
|
||||
QGraphicsScene::mousePressEvent(mouseEvent);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
// Project includes
|
||||
|
||||
// NeL includes
|
||||
#include <nel/ligo/zone_region.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QtGui/QGraphicsScene>
|
||||
|
@ -32,6 +33,34 @@ namespace LandscapeEditor
|
|||
class ZoneBuilder;
|
||||
class ListZonesWidget;
|
||||
|
||||
// Data
|
||||
struct LigoData
|
||||
{
|
||||
sint32 PosX;
|
||||
sint32 PosY;
|
||||
uint8 Rot;
|
||||
uint8 Flip;
|
||||
std::string ZoneName;
|
||||
std::string SharingMatNames[4];
|
||||
uint8 SharingCutEdges[4];
|
||||
bool operator!= (const LigoData& other) const
|
||||
{
|
||||
return (PosX != other.PosX) ||
|
||||
(PosY != other.PosY) ||
|
||||
(Rot != other.Rot) ||
|
||||
(Flip != other.Flip) ||
|
||||
(ZoneName != other.ZoneName) ||
|
||||
(SharingMatNames[0] != other.SharingMatNames[0]) ||
|
||||
(SharingMatNames[1] != other.SharingMatNames[1]) ||
|
||||
(SharingMatNames[2] != other.SharingMatNames[2]) ||
|
||||
(SharingMatNames[3] != other.SharingMatNames[3]) ||
|
||||
(SharingCutEdges[0] != other.SharingCutEdges[0]) ||
|
||||
(SharingCutEdges[1] != other.SharingCutEdges[1]) ||
|
||||
(SharingCutEdges[2] != other.SharingCutEdges[2]) ||
|
||||
(SharingCutEdges[3] != other.SharingCutEdges[3]);
|
||||
}
|
||||
};
|
||||
|
||||
class LandscapeScene : public QGraphicsScene
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -40,6 +69,15 @@ public:
|
|||
LandscapeScene(QUndoStack *undoStack, ListZonesWidget *listZonesWidget, ZoneBuilder *zoneBuilder, QObject *parent = 0);
|
||||
virtual ~LandscapeScene();
|
||||
|
||||
int cellSize() const;
|
||||
|
||||
QGraphicsItem *createZoneItem(const LigoData &data);
|
||||
void processZoneRegion(const NLLIGO::CZoneRegion &zoneRegion);
|
||||
void setCurrentZoneRegion(NLLIGO::CZoneRegion *zoneRegion);
|
||||
|
||||
void snapshot(const QString &fileName, int sizeSource);
|
||||
void snapshot(const QString &fileName, int width, int height);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
|
||||
|
||||
|
@ -49,6 +87,7 @@ private:
|
|||
ListZonesWidget *m_listZonesWidget;
|
||||
QUndoStack *m_undoStack;
|
||||
ZoneBuilder *m_zoneBuilder;
|
||||
NLLIGO::CZoneRegion *m_zoneRegion;
|
||||
};
|
||||
|
||||
} /* namespace LandscapeEditor */
|
||||
|
|
|
@ -114,11 +114,11 @@ void LandscapeView::drawForeground(QPainter *painter, const QRectF &rect)
|
|||
return;
|
||||
|
||||
qreal scaleFactor = transform().m11();
|
||||
painter->setPen(QPen(Qt::white, 1 / scaleFactor, Qt::SolidLine));
|
||||
painter->setPen(QPen(Qt::white, 0, Qt::SolidLine));
|
||||
|
||||
// draw grid
|
||||
qreal left = m_cellSize * int(rect.left() / m_cellSize);
|
||||
qreal top = m_cellSize * int(rect.top() / m_cellSize);
|
||||
qreal left = m_cellSize * floor(rect.left() / m_cellSize);
|
||||
qreal top = m_cellSize * floor(rect.top() / m_cellSize);
|
||||
|
||||
// draw vertical lines
|
||||
while (left < rect.right())
|
||||
|
|
|
@ -107,6 +107,9 @@ LigoData ListZonesWidget::currentLigoData() const
|
|||
QModelIndex index = m_ui.listView->currentIndex();
|
||||
if (index.isValid())
|
||||
ligoData.ZoneName = index.data().toString().toStdString();
|
||||
|
||||
ligoData.Rot = m_ui.rotComboBox->currentIndex();
|
||||
ligoData.Flip = m_ui.flipComboBox->currentIndex();
|
||||
return ligoData;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
// Project includes
|
||||
#include "ui_list_zones_widget.h"
|
||||
#include "builder_zone.h"
|
||||
#include "landscape_scene.h"
|
||||
|
||||
// NeL includes
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<widget class="QComboBox" name="rotComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0°</string>
|
||||
|
@ -233,7 +233,7 @@
|
|||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>170°</string>
|
||||
<string>270°</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -249,7 +249,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<widget class="QComboBox" name="flipComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NoFlip</string>
|
||||
|
@ -273,14 +273,14 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<widget class="QCheckBox" name="forceCheckBox">
|
||||
<property name="text">
|
||||
<string>Force</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QCheckBox" name="checkBox_2">
|
||||
<widget class="QCheckBox" name="propogateCheckBox">
|
||||
<property name="text">
|
||||
<string>Not propogate</string>
|
||||
</property>
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
<property name="text">
|
||||
<string>Data directory:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pathLineEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
|
@ -40,6 +43,9 @@
|
|||
<property name="text">
|
||||
<string>Context:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>contextComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
|
@ -68,8 +74,8 @@
|
|||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
<x>257</x>
|
||||
<y>83</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
|
@ -84,8 +90,8 @@
|
|||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
<x>325</x>
|
||||
<y>83</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SnapshotDialog</class>
|
||||
<widget class="QDialog" name="SnapshotDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>286</width>
|
||||
<height>182</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Snapshot</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="originalSizeRadioButton">
|
||||
<property name="text">
|
||||
<string>Original size</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="customSizeRadioButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="widthSpinBox">
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>512</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>heightSpinBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="heightSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>512</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>widthSpinBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="keepRatioCheckBox">
|
||||
<property name="text">
|
||||
<string>Keep bitmap ratio</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>originalSizeRadioButton</tabstop>
|
||||
<tabstop>customSizeRadioButton</tabstop>
|
||||
<tabstop>widthSpinBox</tabstop>
|
||||
<tabstop>heightSpinBox</tabstop>
|
||||
<tabstop>keepRatioCheckBox</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SnapshotDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>227</x>
|
||||
<y>164</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>158</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SnapshotDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>276</x>
|
||||
<y>170</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>285</x>
|
||||
<y>158</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>customSizeRadioButton</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>groupBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>59</x>
|
||||
<y>39</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>78</x>
|
||||
<y>62</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>keepRatioCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>heightSpinBox</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>84</x>
|
||||
<y>122</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>178</x>
|
||||
<y>106</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>keepRatioCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>label_2</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>55</x>
|
||||
<y>129</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>48</x>
|
||||
<y>103</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -0,0 +1,45 @@
|
|||
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Project includes
|
||||
#include "snapshot_dialog.h"
|
||||
#include "landscape_editor_constants.h"
|
||||
|
||||
#include "../core/icore.h"
|
||||
#include "../core/core_constants.h"
|
||||
|
||||
// NeL includes
|
||||
#include <nel/misc/debug.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QFileDialog>
|
||||
|
||||
namespace LandscapeEditor
|
||||
{
|
||||
|
||||
SnapshotDialog::SnapshotDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
}
|
||||
|
||||
SnapshotDialog::~SnapshotDialog()
|
||||
{
|
||||
}
|
||||
|
||||
} /* namespace LandscapeEditor */
|
|
@ -0,0 +1,47 @@
|
|||
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SNAPSHOT_DIALOG_H
|
||||
#define SNAPSHOT_DIALOG_H
|
||||
|
||||
// Project includes
|
||||
#include "ui_shapshot_dialog.h"
|
||||
|
||||
// Qt includes
|
||||
|
||||
namespace LandscapeEditor
|
||||
{
|
||||
|
||||
class SnapshotDialog: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SnapshotDialog(QWidget *parent = 0);
|
||||
~SnapshotDialog();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Ui::SnapshotDialog m_ui;
|
||||
}; /* class SnapshotDialog */
|
||||
|
||||
} /* namespace LandscapeEditor */
|
||||
|
||||
#endif // SNAPSHOT_DIALOG_H
|
|
@ -0,0 +1,119 @@
|
|||
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Project includes
|
||||
#include "zone_region_editor.h"
|
||||
|
||||
// NeL includes
|
||||
#include <nel/misc/debug.h>
|
||||
#include <nel/misc/file.h>
|
||||
#include <nel/misc/i_xml.h>
|
||||
#include <nel/misc/o_xml.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
namespace LandscapeEditor
|
||||
{
|
||||
|
||||
ZoneRegionEditor::ZoneRegionEditor()
|
||||
{
|
||||
m_fileName = "";
|
||||
}
|
||||
|
||||
ZoneRegionEditor::~ZoneRegionEditor()
|
||||
{
|
||||
}
|
||||
|
||||
bool ZoneRegionEditor::load(const std::string &fileName)
|
||||
{
|
||||
bool result = true;
|
||||
try
|
||||
{
|
||||
// Open it
|
||||
NLMISC::CIFile fileIn;
|
||||
if (fileIn.open(fileName))
|
||||
{
|
||||
NLMISC::CIXml xml(true);
|
||||
xml.init(fileIn);
|
||||
m_zoneRegion.serial(xml);
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Can't open file %s for reading", fileName.c_str());
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
catch (NLMISC::Exception& e)
|
||||
{
|
||||
nlwarning("Error reading file %s : %s", fileName.c_str(), e.what ());
|
||||
result = false;
|
||||
}
|
||||
if (result)
|
||||
m_fileName = fileName;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ZoneRegionEditor::save()
|
||||
{
|
||||
if (m_fileName.empty())
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
// Save the landscape
|
||||
try
|
||||
{
|
||||
|
||||
// Open file for writing
|
||||
NLMISC::COFile fileOut;
|
||||
if (fileOut.open(m_fileName, false, false, true))
|
||||
{
|
||||
// Be careful with the flushing of the COXml object
|
||||
{
|
||||
NLMISC::COXml xmlOut;
|
||||
xmlOut.init(&fileOut);
|
||||
m_zoneRegion.serial(xmlOut);
|
||||
// Done
|
||||
m_modified = false;
|
||||
}
|
||||
fileOut.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning("Can't open file %s for writing.", m_fileName.c_str());
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
catch (NLMISC::Exception& e)
|
||||
{
|
||||
nlwarning("Error writing file %s : %s", m_fileName.c_str(), e.what());
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ZoneRegionEditor::setFileName(const std::string &fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
NLLIGO::CZoneRegion &ZoneRegionEditor::zoneRegion()
|
||||
{
|
||||
return m_zoneRegion;
|
||||
}
|
||||
|
||||
} /* namespace LandscapeEditor */
|
|
@ -0,0 +1,62 @@
|
|||
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
// Copyright (C) 2011 Dzmitry Kamiahin <dnk-88@tut.by>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef LANDSCAPE_EDITOR_H
|
||||
#define LANDSCAPE_EDITOR_H
|
||||
|
||||
// Project includes
|
||||
|
||||
// NeL includes
|
||||
#include <nel/ligo/zone_bank.h>
|
||||
#include <nel/ligo/zone_region.h>
|
||||
|
||||
// STL includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
|
||||
namespace LandscapeEditor
|
||||
{
|
||||
|
||||
class ZoneRegionEditor
|
||||
{
|
||||
public:
|
||||
ZoneRegionEditor();
|
||||
~ZoneRegionEditor();
|
||||
|
||||
// Load landscape data from file
|
||||
bool load(const std::string &fileName);
|
||||
|
||||
// Save landscape data to file
|
||||
bool save();
|
||||
|
||||
// Set file name
|
||||
void setFileName(const std::string &fileName);
|
||||
|
||||
NLLIGO::CZoneRegion &zoneRegion();
|
||||
|
||||
private:
|
||||
|
||||
bool m_modified;
|
||||
bool m_editable;
|
||||
std::string m_fileName;
|
||||
NLLIGO::CZoneRegion m_zoneRegion;
|
||||
};
|
||||
|
||||
} /* namespace LandscapeEditor */
|
||||
|
||||
#endif // LANDSCAPE_EDITOR_H
|
Loading…
Reference in a new issue