I recently got started with Python Qt and I'm trying to make a click-and-drag map editor that reads from and writes to a .json file. So far my progress is getting the QGraphicsView to accurately display the entire room layout with rectangles dynamically. But now I have no idea how to access the x and y offsets of each rectangle given that they can all be moved individually with the setFlag(QGraphicsItem.ItemIsMovable) property.
Here is a short version of my code:
import json
import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
TILEWIDTH = 25
TILEHEIGHT = 15
OUTLINE = 3
class Room:
def __init__(self, name, width, height, offset_x, offset_z):
self.name = name
self.width = width
self.height = height
self.offset_x = offset_x
self.offset_z = offset_z
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
#Setting up viewport
self.scene = QGraphicsScene(self)
self.view = QGraphicsView(self.scene, self)
self.view.scale(1, -1)
self.view.setStyleSheet("background:transparent; border: 0px")
self.setCentralWidget(self.view)
self.setGeometry(360, 190, 1200, 700)
self.showMaximized()
#Reading json and converting entries to rooms
self.room_list = []
with open("Data\Content\PB_DT_RoomMaster.json", "r") as file_reader:
self.content = json.load(file_reader)
for i in self.content:
self.room_list.append(self.convert_json_to_room(i))
self.draw_map()
def convert_json_to_room(self, json):
name = json["Key"]
width = json["Value"]["AreaWidthSize"] * TILEWIDTH
height = json["Value"]["AreaHeightSize"] * TILEHEIGHT
offset_x = round(json["Value"]["OffsetX"]/12.6) * TILEWIDTH
offset_z = round(json["Value"]["OffsetZ"]/7.2) * TILEHEIGHT
room = Room(name, width, height, offset_x, offset_z)
return room
def draw_map(self):
for i in self.room_list:
fill = QColor("#000000")
outline = QPen("#ffffff")
outline.setWidth(OUTLINE)
outline.setJoinStyle(Qt.MiterJoin)
#Drawing rooms
rect = self.scene.addRect(i.offset_x, i.offset_z, i.width, i.height, outline, fill)
rect.setFlag(QGraphicsItem.ItemIsMovable)
def main():
app = QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This is the json:
[
{
"Key": "m01SIP_000",
"Value": {
"LevelName": "m01SIP_000",
"EnemyPatternSuffix": "",
"AreaID": "EAreaID::m01SIP",
"SameRoom": "None",
"AdjacentRoomName": [
"m01SIP_001",
"m01SIP_024",
"m01SIP_023"
],
"OutOfMap": false,
"EventFlagNameForShowEventIfNotSeen": "None",
"EventFlagNameForMarkEventAsSeen": "None",
"WarpPositionX": 0.0,
"WarpPositionY": 0.0,
"WarpPositionZ": 0.0,
"RoomType": "ERoomType::Normal",
"RoomPath": "ERoomPath::Both",
"ConsiderLeft": true,
"ConsiderRight": true,
"ConsiderTop": true,
"ConsiderBottom": true,
"AreaWidthSize": 2,
"AreaHeightSize": 1,
"OffsetX": 25.2,
"OffsetZ": 0.0,
"DoorFlag": [
2,
32
],
"HiddenFlag": [],
"RoomCollisionFromSplineOnly": false,
"RoomCollisionFromGimmick": false,
"NoRoomOutBlinder": false,
"Collision2DProjectionDistance": -1.0,
"FlyMaterialDistance": 10.0,
"NoTraverse": [],
"MagCameraFovScale": 0.0,
"MagCameraVolumeScale": 1.5,
"DemagCameraFovScale": 0.77,
"DemagCameraVolumeScale": 0.0,
"BgmID": "BGM_m01SIP",
"BgmType": "ERoomBgmType::PlayNormal",
"Amb1": "AMB_01SIP_Ship_Roll01",
"AmbVol1": 70,
"Amb2": "",
"AmbVol2": 0,
"Amb3": "",
"AmbVol3": 0,
"Amb4": "",
"AmbVol4": 0,
"Decay_Near": 1260.0,
"Decay_Far": 2520.0,
"Decay_Far_Volume": 0.5,
"UseLava": false,
"FrameType": "EFramePlateType::FPT_Full",
"PerfLevel": 1
}
},
{
"Key": "m01SIP_001",
"Value": {
"LevelName": "m01SIP_001",
"EnemyPatternSuffix": "",
"AreaID": "EAreaID::m01SIP",
"SameRoom": "None",
"AdjacentRoomName": [
"m01SIP_000",
"m01SIP_023",
"m01SIP_002"
],
"OutOfMap": false,
"EventFlagNameForShowEventIfNotSeen": "None",
"EventFlagNameForMarkEventAsSeen": "None",
"WarpPositionX": 0.0,
"WarpPositionY": 0.0,
"WarpPositionZ": 0.0,
"RoomType": "ERoomType::Normal",
"RoomPath": "ERoomPath::Both",
"ConsiderLeft": true,
"ConsiderRight": true,
"ConsiderTop": true,
"ConsiderBottom": true,
"AreaWidthSize": 3,
"AreaHeightSize": 1,
"OffsetX": 50.4,
"OffsetZ": 0.0,
"DoorFlag": [
1,
24,
3,
8
],
"HiddenFlag": [],
"RoomCollisionFromSplineOnly": false,
"RoomCollisionFromGimmick": false,
"NoRoomOutBlinder": false,
"Collision2DProjectionDistance": -1.0,
"FlyMaterialDistance": 10.0,
"NoTraverse": [],
"MagCameraFovScale": 0.0,
"MagCameraVolumeScale": 1.5,
"DemagCameraFovScale": 0.77,
"DemagCameraVolumeScale": 0.0,
"BgmID": "BGM_m01SIP",
"BgmType": "ERoomBgmType::PlayNormal",
"Amb1": "AMB_01SIP_Ship_Roll01",
"AmbVol1": 70,
"Amb2": "AMB_01SIP_Wind02_LP",
"AmbVol2": 70,
"Amb3": "",
"AmbVol3": 0,
"Amb4": "",
"AmbVol4": 0,
"Decay_Near": 1260.0,
"Decay_Far": 2520.0,
"Decay_Far_Volume": 0.5,
"UseLava": false,
"FrameType": "EFramePlateType::FPT_Full",
"PerfLevel": 1
}
},
...
Basically I need to update the offsets of each room in the json after it's been moved on the map editor. What is the best way to approach this ?
You did not set the offset as a parameter of the rectangle since later you will have to do a conversion since it is in local coordinates of the item, instead use the method pos() that is in coordinates of the scene:
Then you can get the position after doing:
I don't see the need to separate the information as you can create an item that stores the information so it can be retrieved later.