Skip to content

Commit

Permalink
Resolved all conflicts by accepting incoming changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Hexalgo committed Jun 25, 2024
2 parents e05a121 + a076f45 commit 88e5767
Show file tree
Hide file tree
Showing 197 changed files with 29,164 additions and 25,374 deletions.
3 changes: 1 addition & 2 deletions pydofus2/Ankama_Common/Common.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from pydofus2.Ankama_Common.ui.items.RecipesFilterWrapper import RecipesFilterWrapper
from pydofus2.com.ankamagames.jerakine.metaclasses.Singleton import Singleton
from pydofus2.com.ankamagames.jerakine.metaclass.Singleton import Singleton


class Common(metaclass=Singleton):

def __init__(self) -> None:
self._jobSearchOptions = dict[int, RecipesFilterWrapper]()

Expand Down
34 changes: 34 additions & 0 deletions pydofus2/DofusUI/AnimatedGifItem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from PyQt5.QtCore import QRectF
from PyQt5.QtGui import QMovie
from PyQt5.QtWidgets import QGraphicsPixmapItem


class AnimatedGifItem(QGraphicsPixmapItem):
def __init__(self, gif_path=None, parent=None):
super(AnimatedGifItem, self).__init__(parent)
self.movie = QMovie(gif_path) if gif_path else QMovie()
self.movie.frameChanged.connect(self.updatePixmap)

def setGifPath(self, path):
self.movie.setFileName(path)
self.movie.start()

def updatePixmap(self, frame_number):
self.setPixmap(self.movie.currentPixmap())

def play(self):
if self.movie.state() in [QMovie.NotRunning, QMovie.Paused]:
self.movie.start()

def pause(self):
if self.movie.state() == QMovie.Running:
self.movie.setPaused(True)

def resume(self):
self.movie.setPaused(False)

def stop(self):
self.movie.stop()

def boundingRect(self):
return QRectF(self.pixmap().rect())
136 changes: 136 additions & 0 deletions pydofus2/DofusUI/DofusUI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QScreen
from PyQt5.QtWidgets import QApplication, QDesktopWidget, QGraphicsView, QMainWindow
from Stage import Stage
from StageShareManager import StageShareManager

from pydofus2.com.ankamagames.atouin.Atouin import Atouin
from pydofus2.com.ankamagames.atouin.data.elements.Elements import Elements
from pydofus2.com.ankamagames.atouin.managers.MapDisplayManager import MapDisplayManager
from pydofus2.com.ankamagames.atouin.types.AtouinOptions import AtouinOptions
from pydofus2.com.ankamagames.atouin.types.DataMapContainer import DataMapContainer
from pydofus2.com.ankamagames.atouin.types.SimpleGraphicsContainer import SimpleGraphicsContainer
from pydofus2.com.ankamagames.dofus.kernel.Kernel import Kernel
from pydofus2.com.ankamagames.dofus.types.DofusOptions import DofusOptions
from pydofus2.com.ankamagames.jerakine.logger.Logger import Logger
from pydofus2.com.ankamagames.jerakine.managers.LangManager import LangManager
from pydofus2.com.ankamagames.jerakine.types.CustomSharedObject import CustomSharedObject
from pydofus2.DofusUI.MapRenderer import MapRenderer
from pydofus2.DofusUI.OptionManager import OptionManager


class DofusUI(QMainWindow):
_instance = None
_initialized = False

def __new__(cls):
if not cls._instance:
cls._instance = super(DofusUI, cls).__new__(cls)
return cls._instance

def __init__(self, parent=None):
if self._initialized:
return
super(DofusUI, self).__init__(parent)
self.setObjectName("sharedStage")
self.setWindowTitle("DofusUI")
self.stage = Stage(self)
self.view = QGraphicsView(self.stage)
self.view.setObjectName("stage main view")
self.setCentralWidget(self.view)
self._windowInitialized = False
self._worldContainer = SimpleGraphicsContainer()
self.stage.addItem(self._worldContainer)
StageShareManager().stage = self.stage
StageShareManager().qMainWindow = self
self.initOptions()

def initWindow(self, isFullScreen):
if self._windowInitialized:
return
self._windowInitialized = True
clientDimensionSo = CustomSharedObject.getLocal("clientData")
if clientDimensionSo.data.get("width") > 0 and clientDimensionSo.data.get("height") > 0:
self.resize(clientDimensionSo.data["width"], clientDimensionSo.data["height"])
if not isFullScreen and clientDimensionSo.data.get("displayState") == "maximized":
self.setWindowState(Qt.WindowMaximized)
else:
mainScreen = QScreen.availableGeometry(QApplication.primaryScreen())
self.resize(mainScreen.width() * 0.8, mainScreen.height() * 0.8)
self.setWindowState(Qt.WindowMaximized)
self.centerOnScreen()
self.show()

def centerOnScreen(self):
qr = self.frameGeometry()
desktop_geom = QDesktopWidget().availableGeometry()
cp = desktop_geom.center()
qr.moveCenter(cp)
self.move(qr.topLeft())

def setDisplayOptions(self, opt: DofusOptions):
self.initWindow(opt.getOption("fullScreen"))
self._doOptions = opt
self._doOptions.propertyChanged.connect(self.onOptionChange)

def onOptionChange(self, name, value, oldValue):
Logger().info(f"DofusUI property {name} changed from {oldValue} to {value}")

def getWorldContainer(self):
return self._worldContainer

def initOptions(self):
from pydofus2.com.ankamagames.atouin.Atouin import Atouin
from pydofus2.com.ankamagames.atouin.Frustum import Frustum

OptionManager.reset()
ao = AtouinOptions(self.getWorldContainer(), Kernel().worker)
ao.setOption(
"frustum",
Frustum(
LangManager().getIntEntry("config.atouin.frustum.marginLeft"),
LangManager().getIntEntry("config.atouin.frustum.marginTop"),
LangManager().getIntEntry("config.atouin.frustum.marginRight"),
LangManager().getIntEntry("config.atouin.frustum.marginBottom"),
),
)
ao.setOption("mapsPath", LangManager().getEntry("config.atouin.path.maps"))
ao.setOption("elementsIndexPath", LangManager().getEntry("config.atouin.path.elements"))
ao.setOption("elementsPath", LangManager().getEntry("config.gfx.path.cellElement"))
ao.setOption("swfPath", LangManager().getEntry("config.gfx.path.world.swf"))
ao.setOption("tacticalModeTemplatesPath", LangManager().getEntry("config.atouin.path.tacticalModeTemplates"))
Atouin().setDisplayOptions(ao)
self.setDisplayOptions(DofusOptions())

def saveClientSize(self):
clientDimensionSo = CustomSharedObject.getLocal("clientData")
clientDimensionSo.data["height"] = self.width()
clientDimensionSo.data["width"] = self.height()
clientDimensionSo.data["displayState"] = (
"maximized" if self.windowState() == Qt.WindowMaximized else str(self.windowState())
)
clientDimensionSo.flush()
clientDimensionSo.close()

def beforeExit(self):
# This is the method you want to execute before the window closes
print("Executing beforeExit: performing cleanup or saving settings.")
self.saveClientSize()

def closeEvent(self, event):
# This method is automatically called when the window is about to close
self.beforeExit() # Call your method here
event.accept() # Proceed with the window closure


if __name__ == "__main__":
Logger.logToConsole = True
app = QApplication(sys.argv)
main_window = DofusUI()
mapRenderer = MapRenderer(Atouin().worldContainer, Elements())
MapDisplayManager().loadMap(191104002.0)
dataMap = DataMapContainer(MapDisplayManager().dataMap)
mapRenderer.render(dataMap)
sys.exit(app.exec_())
95 changes: 95 additions & 0 deletions pydofus2/DofusUI/GfxParallelLoader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from queue import Queue

from PyQt5.QtCore import QMutex, QMutexLocker, QObject, QRunnable, QThreadPool, QWaitCondition, pyqtSignal

from pydofus2.com.ankamagames.jerakine.resources.protocols.impl.PakProtocol2 import PakProtocol2
from pydofus2.com.ankamagames.jerakine.types.Uri import Uri


class GfxLoaderWorker(QRunnable):
def __init__(
self, task_queue: Queue, mutex: QMutex, init_conditions: dict[str, QWaitCondition], loader: "GfxParallelLoader"
):
super().__init__()
self.task_queue = task_queue
self.mutex = mutex
self.loader = loader
self.init_conditions = init_conditions

def run(self):
with QMutexLocker(self.mutex):
self.loader.active_workers += 1

while True:
uri: Uri = None
with QMutexLocker(self.mutex):
if self.task_queue.empty():
break
uri = self.task_queue.get()

if uri:
try:
# Check and wait if initialization is needed and ongoing by another thread
self.wait_for_initialization(uri.path)

# Perform the initialization if needed
if uri.path not in self.loader.protocol.indexes:
with QMutexLocker(self.mutex):
# Check again to ensure it hasn't been initialized in the meantime
if uri.path not in self.loader.protocol.indexes:
self.init_conditions[uri.path] = QWaitCondition()
self.loader.protocol.initStreamsIndexTable(uri)
condition = self.init_conditions.pop(uri.path, None)
if condition:
condition.wakeAll()

# Load directly after ensuring the initialization is done
result = self.loader.protocol.loadDirectly(uri)
if result is None:
raise Exception(
f"No GFX found matching the uri {uri.path} / {uri.subPath} in the gfx d2o file index"
)

self.loader.progress.emit(uri.tag, result)

except Exception as e:
self.loader.error.emit(uri.tag, str(e))
with QMutexLocker(self.mutex):
self.loader.active_workers -= 1
self.loader.onWorkerDied()

def wait_for_initialization(self, path):
with QMutexLocker(self.mutex):
if path in self.loader.protocol._indexes:
return # Already initialized, no need to wait
if path in self.init_conditions:
condition = self.init_conditions[path]
condition.wait(self.mutex) # Wait until initialization is complete


class GfxParallelLoader(QObject):
progress = pyqtSignal(int, bytes) # Emit tag and result
error = pyqtSignal(int, Exception) # Emit error message
finished = pyqtSignal() # Emit when all tasks are done

def __init__(self, maxThreads=6):
super().__init__()
self.task_queue = Queue()
self.mutex = QMutex()
self.pool = QThreadPool()
self.protocol = PakProtocol2()
self.pool.setMaxThreadCount(maxThreads)
self.active_workers = 0
self.init_conditions = {}

def loadItems(self, uris: list[Uri]):
for uri in uris:
self.task_queue.put(uri)
if not self.pool.activeThreadCount():
for _ in range(self.pool.maxThreadCount()):
worker = GfxLoaderWorker(self.task_queue, self.mutex, self.init_conditions, self)
self.pool.start(worker)

def onWorkerDied(self):
if self.active_workers == 0:
self.finished.emit()
Loading

0 comments on commit 88e5767

Please sign in to comment.