Browse Source

A Billion small changes, trying to make the thing a bit more streamlined and logically structured before I start fleshing it out more

Adjusted Icons, still not happy, but well, better than before
master
Christian Voigt 1 year ago
parent
commit
f1ab76f4b2
  1. 1
      requirements.txt
  2. 82
      world_regions_widget/__init__.py
  3. BIN
      world_regions_widget/cursors/add_region.png
  4. BIN
      world_regions_widget/cursors/blank_action_cursor.png
  5. BIN
      world_regions_widget/cursors/blank_cursor.png
  6. BIN
      world_regions_widget/cursors/hover_region.png
  7. BIN
      world_regions_widget/cursors/plot_region.png
  8. BIN
      world_regions_widget/cursors/region_context.png
  9. BIN
      world_regions_widget/cursors/remove_region.png
  10. 115
      world_regions_widget/region_label.py
  11. 36
      world_regions_widget/region_label_collection.py

1
requirements.txt

@ -1,2 +1,3 @@
pyqt5
numpy
scikit-image

82
world_regions_widget/__init__.py

@ -7,7 +7,7 @@ from PyQt5.QtCore import (
Qt, QPoint, QSize
)
from PyQt5.QtGui import (
QCursor, QImage, QKeySequence, QPixmap
QCursor, QKeySequence, QPixmap
)
from PyQt5.QtWidgets import (
QWidget, QAction,
@ -25,7 +25,9 @@ class WorldRegionsWidget(QScrollArea):
max_zoom_factor = float
region_size = int
regions_per_row = int
world_loaded = bool
world_label_zoom_factor = float
world_label_region_size = float
@ -34,7 +36,6 @@ class WorldRegionsWidget(QScrollArea):
action_open_world_file = QAction
action_save_world_file = QAction
world_regions_image = QImage
world_regions_image_raw_data = np.array
currently_hovered_label = object
@ -46,6 +47,7 @@ class WorldRegionsWidget(QScrollArea):
def __init__(self, zoom_factor=1.0, min_zoom_factor=0.5, max_zoom_factor=24.0, region_size=48):
super().__init__()
self.world_loaded = False
self.min_zoom_factor = min_zoom_factor
self.max_zoom_factor = max_zoom_factor
@ -55,9 +57,7 @@ class WorldRegionsWidget(QScrollArea):
self.drag_in_progress = False
self.drag_start = QPoint(0, 0)
self.region_label_collection = RegionLabelCollection(
self, self.get_zoom_adjusted_label_size()
)
self.region_label_collection = RegionLabelCollection(self)
self.region_label_collection.setSpacing(0)
self.region_label_collection.setContentsMargins(0, 0, 0, 0)
@ -92,9 +92,7 @@ class WorldRegionsWidget(QScrollArea):
def init_cursors(self):
self.root_dir = os.path.dirname(os.path.abspath(__file__))
os.path.join(self.root_dir, 'cursors/hover_region.png')
cursor_size = QSize(32, 32)
cursor_size = QSize(86, 86)
self.cursor_hover_region = QCursor(QPixmap(
os.path.join(self.root_dir, 'cursors/hover_region.png')
).scaled(cursor_size, Qt.KeepAspectRatio), -1, -1)
@ -105,7 +103,7 @@ class WorldRegionsWidget(QScrollArea):
os.path.join(self.root_dir, 'cursors/remove_region.png')
).scaled(cursor_size, Qt.KeepAspectRatio), -1, -1)
self.cursor_plot_region = QCursor(QPixmap(
os.path.join(self.root_dir, 'cursors/plot_region.png')
os.path.join(self.root_dir, 'cursors/region_context.png')
).scaled(cursor_size, Qt.KeepAspectRatio), -1, -1)
self.setCursor(self.cursor_hover_region)
@ -126,7 +124,7 @@ class WorldRegionsWidget(QScrollArea):
self.get_zoom_adjusted_label_size()
)
self.adjust_scrollbar_positions()
self.adjust_mouse_position()
self.center_mouse_on_hovered_label()
def action_zoom_out(self):
self.world_label_zoom_factor -= self.min_zoom_factor
@ -138,7 +136,7 @@ class WorldRegionsWidget(QScrollArea):
self.get_zoom_adjusted_label_size()
)
self.adjust_scrollbar_positions()
self.adjust_mouse_position()
self.center_mouse_on_hovered_label()
def adjust_scrollbar_positions(self):
size = (self.currently_hovered_label.width())
@ -156,7 +154,7 @@ class WorldRegionsWidget(QScrollArea):
int(widget_position_y - size / 2 - self.height() / 2)
)
def adjust_mouse_position(self):
def center_mouse_on_hovered_label(self):
QCursor.setPos(self.currently_hovered_label.mapToGlobal(QPoint(
int(self.currently_hovered_label.width() / 2),
int(self.currently_hovered_label.height() / 2)
@ -164,42 +162,49 @@ class WorldRegionsWidget(QScrollArea):
def trigger_cursor_change(self, event=None):
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ControlModifier or (event is not None and event.key() in (16777249, 16777250)):
control_is_pressed = (
modifiers == Qt.ControlModifier or (event is not None and event.key() in (16777249, 16777250))
)
shift_is_pressed = (
modifiers == Qt.ShiftModifier or (event is not None and event.key() == 16777248)
)
if control_is_pressed:
try:
currently_hovered_region_is_marked = self.currently_hovered_label.is_marked
if self.currently_hovered_label.is_region:
if not self.currently_hovered_label.is_marked:
self.setCursor(self.cursor_add_region)
else:
self.setCursor(self.cursor_remove_region)
# all states are covered here, we can return
return
except AttributeError:
currently_hovered_region_is_marked = None
pass
if currently_hovered_region_is_marked:
self.setCursor(self.cursor_remove_region)
else:
self.setCursor(self.cursor_add_region)
elif modifiers == Qt.ShiftModifier or (event is not None and event.key() == 16777248):
elif shift_is_pressed:
try:
currently_hovered_region_is_region = self.currently_hovered_label.is_region
if self.currently_hovered_label.is_region:
self.setCursor(self.cursor_plot_region)
# it's either on or not
return
except AttributeError:
currently_hovered_region_is_region = None
pass
if currently_hovered_region_is_region:
self.setCursor(self.cursor_plot_region)
else:
self.setCursor(self.cursor_hover_region)
else:
self.setCursor(self.cursor_hover_region)
# sets the default, if none of the above applies
self.setCursor(self.cursor_hover_region)
""" altering class functions """
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.trigger_cursor_change()
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ShiftModifier and self.currently_hovered_label.is_region:
pass
if event.button() == Qt.RightButton:
self.drag_in_progress = True
self.drag_start.setX(event.x())
self.drag_start.setY(event.y())
self.setCursor(Qt.OpenHandCursor)
else:
self.drag_in_progress = False
@ -253,13 +258,13 @@ class WorldRegionsWidget(QScrollArea):
def open_world_file_dialogue(self):
dialog = QFileDialog()
file_name = QFileDialog.getOpenFileName(
caption='Select a world-file', options=dialog.options(), filter="*.raw"
caption='load a world-file', options=dialog.options(), filter="RAW files (*.raw)"
)[0]
if file_name:
length = int(math.sqrt(pathlib.Path(file_name).stat().st_size / 2))
regions_per_row = int(length / 512)
offset = int(32 / 2) - int(regions_per_row / 2)
self.regions_per_row = int(length / 512)
offset = int(32 / 2) - int(self.regions_per_row / 2)
with open(file_name, 'r') as raw_file:
raw_data_array = np.fromfile(raw_file, dtype=np.uint16)
@ -270,14 +275,15 @@ class WorldRegionsWidget(QScrollArea):
raw_data_array, length, offset=offset
)
self.world_loaded = True
def save_world_file_dialogue(self):
options = QFileDialog.Options()
file_name, _ = QFileDialog.getSaveFileName(
self, caption='QFileDialog.getSaveFileName()', filter='RAW files (*.raw)', options=options
self, caption='save the world', filter='RAW files (*.raw)', options=options
)
if file_name:
with open(file_name, 'w+b') as raw_file:
raw_file.write(
bytearray(self.world_regions_image_raw_data)
bytearray(np.flipud(self.region_label_collection.raw_map_data))
)

BIN
world_regions_widget/cursors/add_region.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
world_regions_widget/cursors/blank_action_cursor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
world_regions_widget/cursors/blank_cursor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
world_regions_widget/cursors/hover_region.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
world_regions_widget/cursors/plot_region.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

BIN
world_regions_widget/cursors/region_context.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
world_regions_widget/cursors/remove_region.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

115
world_regions_widget/region_label.py

@ -1,6 +1,9 @@
from typing import TYPE_CHECKING
import numpy as np
from PyQt5.QtCore import Qt
from PyQt5.QtCore import (
Qt, QSize
)
from PyQt5.QtGui import (
QPixmap, QColor, QImage
)
@ -8,42 +11,48 @@ from PyQt5.QtWidgets import (
QLabel, QGraphicsColorizeEffect, QApplication, QMenu, QAction, QWidgetAction, QFileDialog
)
if TYPE_CHECKING:
from world_regions_widget import RegionLabelCollection
class RegionLabel(QLabel):
dimensions = QSize
image = QImage
raw_data_array = np.array
parent_collection = 'RegionLabelCollection'
parent_collection_index = str
region_string = str
is_marked = bool
is_open_in_context_menu = bool
is_region = bool
is_selected = bool
parent_collection = object
parent_collection_index = str
context_menu_is_shown = bool
adjacent_marked_region_labels = dict
image = QImage
raw_data_array = np.array
def __init__(self, collection, x=None, y=None):
def __init__(self, collection: 'RegionLabelCollection', x=None, y=None, dimensions=QSize(512, 512)):
super(RegionLabel, self).__init__()
pixmap = QPixmap(512, 512)
fill_color = QColor(x, y, int(x * 2.5) + int(y * 0.5))
self.dimensions = dimensions
pixmap = QPixmap(dimensions)
self.is_marked = False
self.is_region = False
self.is_open_in_context_menu = False
self.context_menu_is_shown = False
self.is_selected = False
self.parent_collection = collection
self.parent_collection_index = "{y}-{x}".format(y=y, x=x)
self.region_string = "r.{}.{}.7rg".format(
int(x - 16),
int((y - 16) + 1) * -1
)
# 7dtd seems to be peculiar about their coordinate system. I arrived at this by trial and error,
# I haven't really grasped the logic of it :)
self.region_string = self.parent_collection.create_region_string_from_index(x, y)
self.setStatusTip(self.region_string)
pixmap.fill(fill_color)
pixmap.fill(self.get_color_by_coordinates(x, y))
self.setPixmap(pixmap)
self.setScaledContents(True)
self.setMouseTracking(True)
@ -58,38 +67,52 @@ class RegionLabel(QLabel):
widget_action.setDefaultWidget(label)
menu.addAction(widget_action)
menu.addSeparator()
menu.addAction(QAction('save region as...', self))
menu.addAction(QAction('replace region with file...', self))
action_save_region = QAction("save region as...", self)
action_save_region.triggered.connect(self.save_region_as)
menu.addAction(action_save_region)
action_replace_region = QAction("replace region with file...", self)
menu.addAction(action_replace_region)
menu.closeEvent = self.on_context_menu_close
self.context_menu = menu
def has_image(self) -> bool:
if isinstance(self.image, QImage):
return True
return False
""" getter + setter"""
def set_image(self, image: QImage = None) -> None:
self.image = image
def set_raw_data_array(self, raw_data_array: np.array = None) -> None:
self.raw_data_array = raw_data_array
def mark_as_region(self) -> None:
self.is_region = True
def set_adjacent_marked_region_labels(self, adjacent_marked_region_labels) -> None:
self.adjacent_marked_region_labels = adjacent_marked_region_labels
""" context menu """
def on_context_menu(self, point):
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ShiftModifier:
if modifiers == Qt.ShiftModifier and self.is_region:
self.parent_collection.toggle_open_in_context_menu(self)
self.context_menu.exec_(self.mapToGlobal(point))
def on_context_menu_close(self, point):
self.parent_collection.toggle_open_in_context_menu(self)
def clear_image(self):
self.image = None
def set_image(self, image: QImage):
self.image = image
def set_raw_data_array(self, raw_data_array: np.array):
self.raw_data_array = raw_data_array
def has_image(self):
if isinstance(self.image, QImage):
return True
def mark_as_region(self):
self.is_region = True
""" visual stuff"""
def set_adjacent_marked_region_labels(self, adjacent_marked_region_labels):
self.adjacent_marked_region_labels = adjacent_marked_region_labels
# if used in a grid, this is basically creating a gradient
@staticmethod
def get_color_by_coordinates(x=0, y=0) -> QColor:
return QColor(
int((((x + 1) * 4) + ((y + 1) * 4)) / 2 - 1),
int((((x + 1) * 4) + ((y + 1) * 4)) / 2 - 1),
int((((x + 1) * 4) + ((y + 1) * 4)) / 2 - 1)
)
def update_style_effects(self):
style = ""
@ -104,7 +127,7 @@ class RegionLabel(QLabel):
def update_graphics_effect(self):
effect = QGraphicsColorizeEffect()
if self.is_open_in_context_menu:
if self.context_menu_is_shown:
effect.setColor(QColor(255, 63, 63, 32))
else:
effect.setColor(QColor(255, 255, 255, 16))
@ -118,30 +141,28 @@ class RegionLabel(QLabel):
def save_region_as(self):
options = QFileDialog.Options()
file_name, _ = QFileDialog.getSaveFileName(
self, caption='QFileDialog.getSaveFileName()', filter='PNG files (*.png)', options=options
self, caption='save region file', filter='RAW files (*.raw)', options=options, directory=self.region_string
)
if file_name:
with open(file_name, 'w+b') as raw_file:
raw_file.write(
bytearray(self.raw_data_array)
bytearray(np.flipud(self.raw_data_array))
)
""" altering class functions """
def mousePressEvent(self, event):
def mouse_any_click_event(self, event):
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ControlModifier:
if modifiers == Qt.ControlModifier and self.is_region:
if event.buttons() == Qt.LeftButton:
self.parent_collection.toggle_marked(self)
def mousePressEvent(self, event):
self.mouse_any_click_event(event)
super().mousePressEvent(event)
def mouseDoubleClickEvent(self, event):
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ControlModifier:
if event.buttons() == Qt.LeftButton:
self.parent_collection.toggle_marked(self)
self.mouse_any_click_event(event)
super().mouseDoubleClickEvent(event)
def enterEvent(self, event) -> None:

36
world_regions_widget/region_label_collection.py

@ -13,13 +13,13 @@ class RegionLabelCollection(QGridLayout):
label_collection = dict
currently_hovered_label = RegionLabel
raw_map_data = np.array
def __init__(self, world_regions, size):
def __init__(self, world_regions):
super().__init__()
self.label_collection = {}
self.world_regions = world_regions
self.create_label_collection(size)
self.label_collection = {}
self.create_label_collection(self.world_regions.get_zoom_adjusted_label_size())
def set_currently_hovered_label(self, region_label):
self.world_regions.set_currently_hovered_label(region_label)
@ -31,6 +31,13 @@ class RegionLabelCollection(QGridLayout):
if region_label is not None:
region_label.update_graphics_effect()
@staticmethod
def create_region_string_from_index(x=0, y=0):
return "r.{x}.{y}.7rg".format(
x=int(x - 16),
y=int((y - 16) + 1) * -1
)
def get_adjacent_marked_region_labels(self, region_label: RegionLabel):
index_x = int(region_label.parent_collection_index.split("-")[1])
index_y = int(region_label.parent_collection_index.split("-")[0])
@ -70,9 +77,10 @@ class RegionLabelCollection(QGridLayout):
adjacent_marked_region_label.set_adjacent_marked_region_labels(neighbors_adjacent_marked_region_labels)
adjacent_marked_region_label.update_style_effects()
def toggle_open_in_context_menu(self, region_label=None):
@staticmethod
def toggle_open_in_context_menu(region_label=None):
if region_label is not None:
region_label.is_open_in_context_menu = not region_label.is_open_in_context_menu
region_label.context_menu_is_shown = not region_label.context_menu_is_shown
region_label.update_graphics_effect()
def trigger_cursor_change(self, region_label=None):
@ -99,15 +107,23 @@ class RegionLabelCollection(QGridLayout):
if label is not empty:
label.parent().adjustSize()
def clear_viewer_grid(self):
for i in reversed(range(self.count())):
self.itemAt(i).widget().setParent(None)
return self
def update_label_collection_with_raw_map_data(self, raw_map_data, length, offset=0):
flipped_raw_2d_map_data = np.reshape(raw_map_data, (length, length))
self.clear_viewer_grid().create_label_collection(self.world_regions.get_zoom_adjusted_label_size())
regions_per_row = int(length / 512)
blockshaped_map_data = view_as_blocks(np.flipud(flipped_raw_2d_map_data), (512, 512))
self.raw_map_data = np.flipud(np.reshape(raw_map_data, (length, length)))
blockshaped_map_data = view_as_blocks(self.raw_map_data, (512, 512))
for x in range(0, regions_per_row):
for y in range(0, regions_per_row):
chunk_raw_data = blockshaped_map_data[y][x].copy()
chunk = QImage(chunk_raw_data, 512, 512, QImage.Format_Grayscale16)
chunk_raw_data = blockshaped_map_data[y][x]
chunk = QImage(chunk_raw_data.copy(), 512, 512, QImage.Format_Grayscale16)
grid_slot = "{}-{}".format(y + offset, x + offset)
region_label = self.label_collection.get(grid_slot)

Loading…
Cancel
Save