Source code for RWESharp.Loaders.PropLoader

from RWESharp.Loaders.Prop import Props, PropCategory, Prop
from RWESharp.Loaders.Tile import Tile, TileCategory, Tiles
from RWESharp.Loaders.TileLoader import init_solve, colortable
from RWESharp.Configurable.PythonTypes import IntConfigurable
from RWESharp.utils import log, color_lerp
from RWESharp.info import PATH_FILES, PATH_DRIZZLE_PROPS, PATH_FILES_CACHE, CELLSIZE, PATH_DRIZZLE_CAST
from RWESharp.Core.lingoIO import fromarr, tojson
from RWESharp.ui.splashuiconnector import SplashDialog
from PySide6.QtCore import QThread, Qt, QSize, QPoint
from PySide6.QtGui import QImage, QColor, QPainter, QPixmap
import os
import multiprocessing


[docs] def load_prop(item: dict, colr, category, catnum, indx): # img.set_colorkey(pg.color.Color(255, 255, 255)) vars = max(item.get("vars", 1), 1) repeatl = item.get("repeatL", [1]) path = item["nm"] renderstep = 15 err = False if all(os.path.exists(os.path.join(PATH_FILES_CACHE, f"{path}_{i}.png")) for i in range(vars)): images = [] for i in range(vars): images.append(QImage(os.path.join(PATH_FILES_CACHE, f"{path}_{i}.png"))) return Prop(item, item.get("nm", "NoName"), item.get("tp"), repeatl, "None", images, item.get("colorTreatment", "standard"), vars, colr, QPoint(catnum, indx), item.get("tags", []), err, category, item.get("notes", []), images[0].size(), item.get("layerExceptions", []), rope=item.get("tp") == "rope", long=item.get("tp") == "long") standard = item.get("tp", "standard") in ["standard", "variedStandard"] soft = item.get("tp", "soft") in ["soft", "variedSoft"] rope_long = item.get("tp", "standard") in ["rope", "long"] imagepath = os.path.join(PATH_DRIZZLE_PROPS, f"{path}.png") if not os.path.exists(imagepath) and rope_long: for i in os.listdir(PATH_DRIZZLE_PROPS): if i.lower() == f"{path}.png".lower(): imagepath = os.path.join(PATH_DRIZZLE_PROPS, i) break if not os.path.exists(imagepath) and rope_long: for i in os.listdir(PATH_DRIZZLE_CAST): if i.endswith(f"{path}.png"): imagepath = os.path.join(PATH_DRIZZLE_CAST, i) break if not os.path.exists(imagepath): imagepath = os.path.join(PATH_FILES, "images", "notfound.png") img = QImage(imagepath) ws, hs = img.width(), img.height() w, h = ws, hs if item.get("pxlSize") is not None: w, h = fromarr(item["pxlSize"], "point") elif item.get("sz") is not None: w, h = fromarr(item["sz"], "point") w *= CELLSIZE h *= CELLSIZE images = [] if img is None: img = QImage(1, 1, QImage.Format.Format_Indexed8) if standard: try: if not img.colorTable(): img = img.convertToFormat(QImage.Format.Format_Indexed8, [4294901760, 4278255360, 4278190335, 4278190080, 4294967295, 0], Qt.ImageConversionFlag.ThresholdDither) img.setColor(img.colorTable().index(4294967295), 0) # img.setColor(img.colorTable().index(4278190080), 0) except ValueError: log(f"Error loading {item['nm']}", True) err = True if rope_long: mask = img.createMaskFromColor(QColor(255, 255, 255, 255).rgba(), Qt.MaskMode.MaskOutColor) mask.setColorTable([4294967295, 0]) newimg = QPixmap(img.size()) newimg.fill(QColor(0, 0, 0, 0)) painter = QPainter(newimg) painter.drawImage(0, 0, img) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_DestinationOut) painter.drawImage(0, 0, mask) painter.end() elif not standard or soft: mask = img.createMaskFromColor(QColor(255, 255, 255, 255).rgba(), Qt.MaskMode.MaskOutColor) mask.setColorTable([4294967295, 0]) mask2 = img.createMaskFromColor(QColor(0, 0, 0, 0).rgba(), Qt.MaskMode.MaskOutColor) mask2.setColorTable([4294967295, 0]) mask3 = img.createMaskFromColor(QColor(0, 0, 0, 255).rgba(), Qt.MaskMode.MaskOutColor) mask3.setColorTable([4294967295, 0]) # mask.save(os.path.join(PATH_FILES_CACHE, f"{path}_test_0.png")) # img.save(os.path.join(PATH_FILES_CACHE, f"{path}_test_1.png")) newimg = QPixmap(img.size()) newimg.fill(QColor(0, 0, 0, 0)) painter = QPainter(newimg) painter.drawImage(0, 0, img) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_DestinationOut) painter.drawImage(0, 0, mask) painter.drawImage(0, 0, mask2) painter.drawImage(0, 0, mask3) painter.end() # if soft: # newimg = newimg.copy(0, 0, ws, h) #newimg.save(os.path.join(PATH_FILES_CACHE, f"{path}_0.png")) else: newimg = QPixmap(ws, h) newimg.fill(QColor(0, 0, 0, 0)) painter = QPainter(newimg) wh = QColor("#ffffff") gr = QColor("#dddddd") bl = QColor("#000000") cons = 0.4 curcol = gr for i, v in zip(range(len(repeatl) - 1, -1, -1), reversed(repeatl)): if item.get("colorTreatment", "normal") == "bevel": curcol = color_lerp(curcol, bl, cons) # todo newi = img.copy(0, h * i, ws, h).createMaskFromColor(QColor(0, 0, 0).rgba(), Qt.MaskMode.MaskInColor) newi.setColorTable([0, QColor(0, 255, 0).rgba()]) painter.drawImage(0, 0, newi) else: painter.drawImage(0, 0, img.copy(0, h * i, ws, h)) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceAtop) painter.fillRect(0, 0, ws, h, QColor(0, 0, 0, renderstep)) painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceOver) painter.end() img3 = QImage(newimg.width(), newimg.height(), QImage.Format.Format_RGBA64) imagepix = newimg.toImage() # newimg.save(os.path.join(PATH_FILES_CACHE, f"test.png")) # print(ws, hs, w, h) for xp in range(img3.width()): for yp in range(img3.height()): pc = imagepix.pixelColor(xp, yp) if pc.alpha() == 0 or pc.rgb() == QColor(0, 0, 0).rgb(): img3.setPixelColor(xp, yp, QColor(0, 0, 0, 0)) continue if pc.red() > pc.green() == pc.blue(): pc = QColor(91 + (255 - pc.red()) // renderstep, 0, 0, 255) elif pc.green() > pc.red() == pc.blue(): pc = QColor(121 + (255 - pc.green()) // renderstep, 0, 0, 255) elif pc.blue() > pc.green() == pc.red(): pc = QColor(151 + (255 - pc.blue()) // renderstep, 0, 0, 255) img3.setPixelColor(xp, yp, pc) #img3.save(os.path.join(PATH_FILES_CACHE, f"test2.png")) newimg = img3.convertToFormat(QImage.Format.Format_Indexed8, colortable[0], Qt.ImageConversionFlag.ThresholdDither) newimg = QPixmap.fromImage(newimg) for i in range(vars): images.append(newimg.toImage().copy(w * i, 0, w, h)) images[-1].save(os.path.join(PATH_FILES_CACHE, f"{path}_{i}.png")) return Prop(item, item.get("nm", "NoName"), item.get("tp"), repeatl, "None", images, item.get("colorTreatment", "standard"), vars, colr, QPoint(catnum, indx), item.get("tags", []), err, category, item.get("notes", []), QSize(w, h), item.get("layerExceptions", []), rope=item.get("tp") == "rope", long = item.get("tp") == "long")
[docs] def tile2prop(tile: Tile, cat, category): err = tile.err if tile.type != "VoxelStruct" or "notProp" in tile.tags: err = True return Prop({"depth": 10 * (int(tile.cols1 != []) + 1)}, tile.name, "standard", tile.repeatl, tile.description, [tile.image3], "standard", 1, tile.color, cat, [*tile.tags, "tile"], err, category, ["Tile as Prop"], (tile.size + QSize(tile.bfTiles, tile.bfTiles) * 2) * CELLSIZE)
[docs] class PropPackLoader(QThread):
[docs] def __init__(self, data, parent=None): super().__init__(parent) self.data = data self.cats = [] self.progress = 0 self.errors = 0 self.amount = sum(list(map(lambda x: len(x["items"]), self.data))) self.finished.connect(self.deleteLater)
[docs] def run(self): for catnum, catitem in enumerate(self.data): proplist = [] propcat = PropCategory(catitem["name"], catitem["color"], proplist) items = catitem["items"] colr: QColor = catitem["color"] # self.data[catnum]["items"] = [] for indx, item in enumerate(items): tile = load_prop(item, colr, propcat, catnum, indx) self.progress += 1 if tile is None: self.errors += 1 continue proplist.append(tile) if tile.err: self.errors += 1 self.cats.append(propcat)
# self.finished.emit()
[docs] class Tile2PropLoader(QThread):
[docs] def __init__(self, categories: list[TileCategory], parent=None): super().__init__(parent) self.categories = categories self.cats = [] self.progress = 0 self.errors = 0 self.amount = sum(list(map(lambda x: len(x.tiles), self.categories))) self.finished.connect(self.deleteLater)
[docs] def run(self): for catnum, catitem in enumerate(self.categories): proplist = [] propcat = PropCategory(catitem.name, catitem.color, proplist) items = catitem.tiles colr: QColor = catitem.color # self.data[catnum]["items"] = [] if catitem.name == "materials": self.progress += len(items) continue for indx, item in enumerate(items): prop = tile2prop(item, QPoint(catnum, indx), propcat) self.progress += 1 if prop is None: self.errors += 1 continue proplist.append(prop) if prop.err: self.errors += 1 self.cats.append(propcat)
# self.finished.emit()
[docs] class PropProgress(QThread):
[docs] def __init__(self, window, workers): super().__init__() window.printmessage("Loading Props...") self.workers = workers self.window = window self.overall = sum(list(map(lambda x: x.amount, self.workers))) self.loaded = IntConfigurable(None, "da", 0) self.loaded.valueChanged.connect(self.window.ui.progressBar.setValue) self.finished.connect(self.deleteLater)
[docs] def run(self): loaded = sum(list(map(lambda x: x.progress, self.workers))) while loaded != self.overall: self.msleep(100) loaded = sum(list(map(lambda x: x.progress, self.workers))) self.window.ui.label_2.setText(f"({loaded}/{self.overall})") self.loaded.update_value(loaded / self.overall * 100)
[docs] def load_props(tiles: Tiles, window: SplashDialog): log("Loading Props") solved_copy = init_solve(os.path.join(PATH_DRIZZLE_PROPS, "Init.txt")) length = sum(list(map(lambda x: len(x["items"]), solved_copy.data))) additional = init_solve(os.path.join(PATH_FILES, "additionprops.txt")) for i in additional.data: solved_copy.append(i) log(f"Loading {length} Props") threadsnum = min(1, multiprocessing.cpu_count() - 1) catsnum = len(solved_copy.data) data_per_thread = catsnum // threadsnum unused = catsnum - data_per_thread * threadsnum workers: list[PropPackLoader] = [] for i in range(threadsnum): workers.append(PropPackLoader(solved_copy.data[i * data_per_thread:i * data_per_thread + data_per_thread])) if unused > 0: workers.append(PropPackLoader(solved_copy.data[-unused:])) progress = PropProgress(window, workers) for i in workers: i.start() progress.start() for i in workers: i.wait() progress.wait() categories = [] for i in workers: categories = [*categories, *i.cats] log(f"Loading Tiles as props") # yeah me lazy go brrrr catsnum = len(tiles.categories_nocustom) data_per_thread = catsnum // threadsnum unused = catsnum - data_per_thread * threadsnum workers: list[Tile2PropLoader] = [] for i in range(threadsnum): workers.append(Tile2PropLoader(tiles.categories_nocustom[i * data_per_thread:i * data_per_thread + data_per_thread])) if unused > 0: workers.append(Tile2PropLoader(tiles.categories_nocustom[-unused:])) progress = PropProgress(window, workers) for i in workers: i.start() progress.start() for i in workers: i.wait() progress.wait() for i in workers: categories = [*categories, *i.cats] window.printmessage("All Props loaded!") log("Finished Loading") return Props(categories)
[docs] def getcolors(): solved = open(os.path.join(PATH_DRIZZLE_PROPS, "propColors.txt")).readlines() cols = [] for line in solved: if line[0] != '[': continue l = tojson(line) l[1] = fromarr(l[1], "color") cols.append(l) return cols