Editor Informations

Downloads

Source code
Executable for the map editor (Windows 32bits)
Executable for the game - exactly the same as in part 7 (Windows 32bits)

Before you try to compile the code go to the "Projects" tab on the left menu, select the "Run" settings for your kit,
and set the "Working directory" to the path of "editor\data" for the editor or "game\data" for the game.

Sending datas to the qml

To clean up the "editor.cpp" file, I moved all the functions to draw the cursor and the selections in a file called "rectangles.cpp".

Until now we have only sent datas from the QML to the C++ part by calling functions in the bridge.cpp.
Now we will sent data in the other way to display informations about the map in the editor.
To send a variable to the QML it is a little bit more complicated than just calling a function.
In bridge.h you will find a macro:

		#define qmlMember(_type,_name) \
			public: \
				Q_PROPERTY(_type _name MEMBER m_##_name READ get_##_name WRITE set_##_name NOTIFY _name##Changed); \
				_type get_##_name() const {return m_##_name;} \
				void set_##_name(_type val) {m_##_name = val; emit _name##Changed(val);} \
			private: \
				_type m_##_name;
				
As you see, we need to call "Q_PROPERTY" with the following parameters:
The macro defines all the needed parameters for the variable except the signal because it would cause problems during the compilation.

The cursor position

Now we will use this for a simple task: we will display the coordinates of the cursor at the bottom of the screen.
In "editor.cpp" I added a function getPositionString() that returns the string that we want to display according to the current tab.
In "bridge.h" we define our variable:

			qmlMember(QString,cursorInfo)
			[...]

		signals:
			[...]
			void    cursorInfoChanged(QString);
				
In "MainForm.ui.qml" we simply display it inside a rectangle:

		Rectangle {
			id: rectangle
			y: 446
			height: cursorInfos.height + 8
			color: "#00000000"
			border.color: "#808080"
			border.width: 1
			[...]

			Label {
				id: cursorInfos
				x: 0
				text: bridge.cursorInfo
				[...]
			}
		}
				
And in "rectangles.cpp", we modify the variable every time we draw the cursor:

		void Rectangles::drawCursor(QImage* image, CVec2 mousePos, ETabIndex tabIndex)
		{
			if (mousePos.x != -1)
			{
				if (tabIndex == eTabTiles)
					drawTileRect(image, mousePos, CURSOR_COLOR);
				else if (tabIndex == eTabWalls)
					drawWallRect(image, mousePos, CURSOR_COLOR);
				else if (tabIndex == eTabObjects)
					drawObjectRect(image, mousePos, CURSOR_COLOR);

				QString text = editor.getPositionString(mousePos, tabIndex);
				bridge.set_cursorInfo(text);
			}
			else
			{
				bridge.set_cursorInfo(QString());
			}
		}
				

The selection informations

Under the TabView we will now display a box with informations about the selection.
There will be 4 different contents depending on either we selected 1 tile, 1 wall, 1 object square or a rectangle of tiles:

		GroupBox {
			id: selectionBox
			x: 403
			width: tabView1.width
			[...]
			title: qsTr("Selection")

			ScrollView {
				id: tileSelScroll
				visible: bridge.tileSelScrollVis
				anchors.fill: parent

				Grid {
					id: tSelGrid
					spacing: 4
					rows: 3
					columns: 2
					anchors.fill: parent
					[...]
				}
			}

			ScrollView {
				id: wallSelScroll
				visible: bridge.wallSelScrollVis
				anchors.fill: parent

				Grid {
					id: wSelGrid
					spacing: 4
					rows: 3
					columns: 2
					anchors.fill: parent
					[...]
				}
			}

			ScrollView {
				id: objectSelScroll
				visible: bridge.objectSelScrollVis
				anchors.fill: parent

				Grid {
					id: oSelGrid
					spacing: 4
					rows: 3
					columns: 2
					anchors.fill: parent
					[...]
				}
			}

			ScrollView {
				id: rectSelScroll
				visible: bridge.rectSelScrollVis
				anchors.fill: parent

				Grid {
					id: rSelGrid
					spacing: 4
					rows: 3
					columns: 2
					anchors.fill: parent
					[...]
				}
			}
		}
				
As you can see, each of the ScrollViews can be shown or hidden by modifying the corresponding variable tileSelScrollVis, wallSelScrollVis,
objectSelScrollVis or rectSelScrollVis.
Those variables are defined in the same way as we defined the cursor coordinate above.

Inside each of those ScrollViews there is a Grid to organize the content in rows.
The first line of each content will be the same: the coordinates of the selection. For example:

		Label {
			id: tPosLabel
			height: 20
			text: qsTr("Position:")
			verticalAlignment: Text.AlignVCenter
			renderType: Text.QtRendering
		}

		Label {
			id: tPosValue
			height: 20
			text: bridge.selPosition
			verticalAlignment: Text.AlignVCenter
		}
				
This position is set using the same function getPositionString() that we used before.

We won't add anything to the content of the "objects" tab for the moment. We will see in the future how we handle them.
For the "rectangular selection", the second line will simply be the size of the rectangle.
For the "tile" and the "wall" contents, the second line will contain a ComboBox that will allow us to change the type of the selected element.

The ComboBoxes

Inside our grids the ComboBoxes lines are defined like that:

		Label {
			id: tTypeLabel
			height: 20
			text: qsTr("Type:")
			verticalAlignment: Text.AlignVCenter
			horizontalAlignment: Text.AlignLeft
		}

		ComboBox {
			id: tTypeValue
			model: tilesList
			currentIndex: bridge.selTileType
		}
				
The "model" represents all the values that will be displayed in the ComboBox. It is a list of strings that is defined by the function
initLists() in "editor.cpp" and registered for the QML in main.cpp:

		// register our functions
		ctxt = engine.rootContext();
		editor.initLists();
		ctxt->setContextProperty("bridge", &bridge);
		ctxt->setContextProperty("tilesList", QVariant::fromValue(bridge.tilesList));
		ctxt->setContextProperty("wallsList", QVariant::fromValue(bridge.wallsList));
				
The "currentIndex" is the variable we will use to set the type of the selected item from the C++ side.
Now if I choosed to put a comboBox, it's to be able to change the type of the selected item, so when we change the value of the ComboBox,
we need to send it from the QML to the C++. It is done in "main.qml":

		tTypeValue.onCurrentIndexChanged: bridge.setSelTileType(tTypeValue.currentIndex);
		wTypeValue.onCurrentIndexChanged: bridge.setSelWallType(wTypeValue.currentIndex);
				
You can see how those values are handled in the C++ code by searching for the corresponding variables and functions.