diff --git a/LICENSE b/LICENSE index 5d2493d..87e7c9e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2017 Vlad - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2018 GambitER + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index ba530f3..76995fc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -##### World of Tanks - Mods -## .. GUIFlash .. -_Позволяет динамически создавать компоненты для отображения текстовой и графической информации в Flash интерфейсе игры World of Tanks. Создание и управление компонентами производится через Python скрипты (модификации клиента)._ - -Подробнее в [**Wiki**](https://github.com/GambitER/GUIFlash/wiki). +##### World of Tanks - Mods + +## .. GUIFlash .. + +_Позволяет динамически создавать компоненты для отображения текстовой и графической информации в Flash интерфейсе игры World of Tanks. Создание и управление компонентами производится через Python скрипты (модификации клиента)._ + +Подробнее в [**Wiki**](https://github.com/GambitER/GUIFlash/wiki). diff --git a/gambiter.guiflash_0.2.5.wotmod b/gambiter.guiflash_0.2.5.wotmod new file mode 100644 index 0000000..0562f2d Binary files /dev/null and b/gambiter.guiflash_0.2.5.wotmod differ diff --git a/meta.xml b/meta.xml index 29c4907..0fa75bd 100644 --- a/meta.xml +++ b/meta.xml @@ -1,6 +1,6 @@ - - gambiter.guiflash - 0.2.3 - GUIFlash - Flash components for use in python mods. - + + gambiter.guiflash + 0.2.5 + GUIFlash + Flash components for use in python mods. + diff --git a/res/gui/flash/GUIFlash.swf b/res/gui/flash/GUIFlash.swf index 5938191..70fff4e 100644 Binary files a/res/gui/flash/GUIFlash.swf and b/res/gui/flash/GUIFlash.swf differ diff --git a/res/gui/flash/as3proj/src/net/gambiter/FlashUI.as b/res/gui/flash/as3proj/src/net/gambiter/FlashUI.as index b65081d..3e4e0cd 100644 --- a/res/gui/flash/as3proj/src/net/gambiter/FlashUI.as +++ b/res/gui/flash/as3proj/src/net/gambiter/FlashUI.as @@ -7,7 +7,7 @@ import net.wg.infrastructure.managers.impl.ContainerManagerBase; import net.wg.gui.components.containers.MainViewContainer; - import net.wg.data.constants.ContainerTypes; + import net.wg.data.constants.generated.APP_CONTAINERS_NAMES; import net.wg.infrastructure.base.AbstractView; public class FlashUI extends AbstractView @@ -56,7 +56,7 @@ try { parent.removeChild(this); - viewContainer = (App.containerMgr as ContainerManagerBase).containersMap[ContainerTypes.VIEW]; + viewContainer = (App.containerMgr as ContainerManagerBase).containersMap[APP_CONTAINERS_NAMES.VIEWS]; viewContainer.setFocusedView(viewContainer.getTopmostView()); viewPage = viewContainer.getChildByName("main") as DisplayObjectContainer; } @@ -74,7 +74,8 @@ public function as_cursor(arg:Boolean):void { if (arg != showCursor) showCursor = arg; - if (showCursor) null; // App.cursor.loader.hitTestObject / App.cursor.loader.hitTestPoint + if (showCursor) + null; // App.cursor.loader.hitTestObject / App.cursor.loader.hitTestPoint else for (var alias:String in components) components[alias].hideCursor(); } diff --git a/res/gui/flash/as3proj/src/net/gambiter/components/LabelEx.as b/res/gui/flash/as3proj/src/net/gambiter/components/LabelEx.as index c10ebf1..ead3018 100644 --- a/res/gui/flash/as3proj/src/net/gambiter/components/LabelEx.as +++ b/res/gui/flash/as3proj/src/net/gambiter/components/LabelEx.as @@ -4,6 +4,7 @@ import flash.text.TextFormat; import flash.text.GridFitType; import flash.text.AntiAliasType; + import flash.text.TextFieldAutoSize; import scaleform.gfx.TextFieldEx; @@ -33,18 +34,24 @@ _hAlign = Align.LEFT; _vAlign = Align.TOP; - textField.mouseEnabled = false; + textField.width = 0; + textField.height = 0; + textField.mouseEnabled = false; + textField.wordWrap = false; textField.multiline = false; textField.selectable = false; + textField.background = false; + textField.backgroundColor = 0x000000; textField.embedFonts = true; - textField.gridFitType = GridFitType.PIXEL; + textField.gridFitType = GridFitType.PIXEL; + textField.autoSize = TextFieldAutoSize.LEFT; textField.antiAliasType = AntiAliasType.ADVANCED; textField.defaultTextFormat = new TextFormat("$UniversCondC", 12, 0xFFFFFF, false, false, false, "", "", "left", 0, 0, 0, 0); - Properties.setShadow(textField, {"distance": 4, "angle": 45, "color": 0, "alpha": 1, "blurX": 4, "blurY": 4, "strength": 1, "quality": 1}); + Properties.setShadow(textField, {"distance": 4, "angle": 45, "color": 0x999999, "alpha": 1, "blurX": 4, "blurY": 4, "strength": 1, "quality": 1}); } override protected function configUI():void @@ -71,7 +78,7 @@ { if (text == null || textField == null) return; if (isHtml) textField.htmlText = text; - else textField.text = text; + else textField.text = text; initialize(); } @@ -81,14 +88,16 @@ } override protected function updateSize():void - { + { if (autoSize) { - textField.width = _originalWidth; - textField.height = _originalHeight; + textField.autoSize = TextFieldAutoSize.LEFT; + // textField.width = _originalWidth; + // textField.height = _originalHeight; } else { + textField.autoSize = TextFieldAutoSize.NONE; textField.width = width; textField.height = height; } @@ -167,6 +176,26 @@ return textField.wordWrap; } + public function set background(value:Boolean):void + { + if (value != textField.background) textField.background = value; + } + + public function get background():Boolean + { + return textField.background; + } + + public function set backgroundColor(value:uint):void + { + if (value != textField.backgroundColor) textField.backgroundColor = value; + } + + public function get backgroundColor():uint + { + return textField.backgroundColor; + } + public function set shadow(args:Object):void { Properties.setShadow(textField, args); diff --git a/res/gui/flash/as3proj/src/net/gambiter/core/UIBorderEx.as b/res/gui/flash/as3proj/src/net/gambiter/core/UIBorderEx.as index 5439ea1..8307daa 100644 --- a/res/gui/flash/as3proj/src/net/gambiter/core/UIBorderEx.as +++ b/res/gui/flash/as3proj/src/net/gambiter/core/UIBorderEx.as @@ -14,27 +14,29 @@ super(); visible = false; - _rect = new Rectangle(0, 0, 100, 100); + _rect = new Rectangle(0, 0, 0, 0); } - public function show():void + private function draw():void { - if (obj) _rect = obj.getRect(obj); - graphics.clear(); graphics.beginFill(0x999999, 0.1); graphics.lineStyle(1, 0x999999, 1, true); graphics.drawRect(_rect.x, _rect.y, _rect.width, _rect.height); graphics.endFill(); - + } + + public function show():void + { + if (obj) _rect = obj.getRect(obj); + draw(); visible = true; } public function hide():void { - graphics.clear(); - + graphics.clear(); visible = false; } diff --git a/res/gui/flash/as3proj/src/net/gambiter/core/UIComponentEx.as b/res/gui/flash/as3proj/src/net/gambiter/core/UIComponentEx.as index 0eadfae..70522c5 100644 --- a/res/gui/flash/as3proj/src/net/gambiter/core/UIComponentEx.as +++ b/res/gui/flash/as3proj/src/net/gambiter/core/UIComponentEx.as @@ -76,6 +76,7 @@ override protected function draw():void { super.draw(); + refresh(); } public function refresh():void @@ -92,9 +93,9 @@ super.visible = _visible && (!FlashUI.ui.showFullStats || _fullStats) && (!FlashUI.ui.showRadialMenu || _radialMenu); } - private function updateIndex():void + private function updateIndex():void { - if (_index) parent.setChildIndex(this, Math.min(_index, parent.numChildren - 1)); + if ((_index != undefined) && (_index != parent.getChildIndex(this))) parent.setChildIndex(this, Math.min(_index, parent.numChildren - 1)); } protected function updateSize():void diff --git a/res/gui/flash/as3proj/swc/wg/base_app-1.0-SNAPSHOT.swc b/res/gui/flash/as3proj/swc/wg/base_app-1.0-SNAPSHOT.swc index d258cc8..e888b8c 100644 Binary files a/res/gui/flash/as3proj/swc/wg/base_app-1.0-SNAPSHOT.swc and b/res/gui/flash/as3proj/swc/wg/base_app-1.0-SNAPSHOT.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/battle.swc b/res/gui/flash/as3proj/swc/wg/battle.swc index f927d63..3910960 100644 Binary files a/res/gui/flash/as3proj/swc/wg/battle.swc and b/res/gui/flash/as3proj/swc/wg/battle.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/common-1.0-SNAPSHOT.swc b/res/gui/flash/as3proj/swc/wg/common-1.0-SNAPSHOT.swc index 8b3764d..48d3007 100644 Binary files a/res/gui/flash/as3proj/swc/wg/common-1.0-SNAPSHOT.swc and b/res/gui/flash/as3proj/swc/wg/common-1.0-SNAPSHOT.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/common_i18n_library-1.0-SNAPSHOT.swc b/res/gui/flash/as3proj/swc/wg/common_i18n_library-1.0-SNAPSHOT.swc index 74de14f..1371c81 100644 Binary files a/res/gui/flash/as3proj/swc/wg/common_i18n_library-1.0-SNAPSHOT.swc and b/res/gui/flash/as3proj/swc/wg/common_i18n_library-1.0-SNAPSHOT.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/gui_base-1.0-SNAPSHOT.swc b/res/gui/flash/as3proj/swc/wg/gui_base-1.0-SNAPSHOT.swc index 6288606..f6ff2df 100644 Binary files a/res/gui/flash/as3proj/swc/wg/gui_base-1.0-SNAPSHOT.swc and b/res/gui/flash/as3proj/swc/wg/gui_base-1.0-SNAPSHOT.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/gui_battle-1.0-SNAPSHOT.swc b/res/gui/flash/as3proj/swc/wg/gui_battle-1.0-SNAPSHOT.swc index af4ae23..cb51a55 100644 Binary files a/res/gui/flash/as3proj/swc/wg/gui_battle-1.0-SNAPSHOT.swc and b/res/gui/flash/as3proj/swc/wg/gui_battle-1.0-SNAPSHOT.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/gui_lobby-1.0-SNAPSHOT.swc b/res/gui/flash/as3proj/swc/wg/gui_lobby-1.0-SNAPSHOT.swc index dee6446..e6ec508 100644 Binary files a/res/gui/flash/as3proj/swc/wg/gui_lobby-1.0-SNAPSHOT.swc and b/res/gui/flash/as3proj/swc/wg/gui_lobby-1.0-SNAPSHOT.swc differ diff --git a/res/gui/flash/as3proj/swc/wg/lobby.swc b/res/gui/flash/as3proj/swc/wg/lobby.swc index 3b6d3f4..4fe97a3 100644 Binary files a/res/gui/flash/as3proj/swc/wg/lobby.swc and b/res/gui/flash/as3proj/swc/wg/lobby.swc differ diff --git a/res/scripts/client/gui/mods/gambiter/__init__.py b/res/scripts/client/gui/mods/gambiter/__init__.py index f4ab4af..30f9338 100644 --- a/res/scripts/client/gui/mods/gambiter/__init__.py +++ b/res/scripts/client/gui/mods/gambiter/__init__.py @@ -1,5 +1,5 @@ -# -*- coding: utf-8 -*- - -from flash import GUIFlash - -g_guiFlash = GUIFlash() +# -*- coding: utf-8 -*- + +from flash import GUIFlash + +g_guiFlash = GUIFlash() \ No newline at end of file diff --git a/res/scripts/client/gui/mods/gambiter/__init__.pyc b/res/scripts/client/gui/mods/gambiter/__init__.pyc index d5cf4d3..f8d429d 100644 Binary files a/res/scripts/client/gui/mods/gambiter/__init__.pyc and b/res/scripts/client/gui/mods/gambiter/__init__.pyc differ diff --git a/res/scripts/client/gui/mods/gambiter/flash.py b/res/scripts/client/gui/mods/gambiter/flash.py index bcd38b4..dd7f949 100644 --- a/res/scripts/client/gui/mods/gambiter/flash.py +++ b/res/scripts/client/gui/mods/gambiter/flash.py @@ -1,317 +1,330 @@ -# -*- coding: utf-8 -*- - -__all__ = ['COMPONENT_TYPE', 'COMPONENT_ALIGN', 'COMPONENT_EVENT'] - -import Event -import BattleReplay -import json, codecs -from gui.app_loader import g_appLoader -from gui.app_loader.settings import GUI_GLOBAL_SPACE_ID as SPACE_ID -from gui.shared import g_eventBus, events, EVENT_BUS_SCOPE -from gui.Scaleform.framework.entities.View import View -from gui.Scaleform.framework.managers.loaders import ViewLoadParams -from gui.Scaleform.framework import g_entitiesFactories, ViewSettings, ViewTypes, ScopeTemplates -from utils import LOG_NOTE, LOG_DEBUG, LOG_ERROR - - -class CONSTANTS(object): - FILE_NAME = 'GUIFlash.swf' - VIEW_ALIAS = 'GUIFlash' - - -class COMPONENT_TYPE(object): - PANEL = 'Panel' - LABEL = 'Label' - IMAGE = 'Image' - SHAPE = 'Shape' - - -ALL_COMPONENT_TYPES = (COMPONENT_TYPE.PANEL, COMPONENT_TYPE.LABEL, COMPONENT_TYPE.IMAGE, COMPONENT_TYPE.SHAPE) - - -class COMPONENT_ALIGN(object): - LEFT = 'left' - RIGHT = 'right' - CENTER = 'center' - TOP = "top" - BOTTOM = 'bottom' - - -class COMPONENT_STATE(object): - INIT = 1 - LOAD = 2 - UNLOAD = 3 - - -class COMPONENT_EVENT(object): - LOADED = Event.Event() - UPDATED = Event.Event() - UNLOADED = Event.Event() - - -class Cache(object): - def __init__(self): - self.components = {} - - def create(self, alias, type, props): - self.components[alias] = {'type': type, 'props': props} - - def update(self, alias, props): - self.components[alias].get('props').update(props) - - def delete(self, alias): - del self.components[alias] - - def isComponent(self, alias): - return alias in self.components - - def getComponent(self, alias=None): - if alias is None: - return self.components - return self.components.get(alias) - - def getKeys(self): - return sorted(self.components.keys()) - - def getCustomizedType(self, type): - return ''.join(type.split()).capitalize() - - def isTypeValid(self, type): - return type in ALL_COMPONENT_TYPES - - # .. - def readConfig(self, file): - LOG_DEBUG('GUIFlash :', 'Read config from file "%s".' % file) - with open(file, "r") as file: - data = json.load(file) - return data - - # .. - def saveConfig(self, file, data): - LOG_DEBUG('GUIFlash :', 'Save config in file "%s".' % file) - with open(file, 'wb') as file: - json.dump(data, codecs.getwriter('utf-8')(file), indent=4, sort_keys=True, ensure_ascii=False) - - -class Views(object): - def __init__(self): - self.ui = None - - def createAll(self): - for alias in g_guiCache.getKeys(): - component = g_guiCache.getComponent(alias) - self.create(alias, component.get('type'), component.get('props')) - - def create(self, alias, type, props): - if self.ui is not None: - self.ui.as_createS(alias, type, props) - - def update(self, alias, props): - if self.ui is not None: - self.ui.as_updateS(alias, props) - - def delete(self, alias): - if self.ui is not None: - self.ui.as_deleteS(alias) - - def cursor(self, isShow): - if self.ui is not None: - self.ui.as_cursorS(isShow) - - def fullStats(self, isShow): - if self.ui is not None: - self.ui.as_fullStatsS(isShow) - - def radialMenu(self, isShow): - if self.ui is not None: - self.ui.as_radialMenuS(isShow) - - -class Hooks(object): - def _start(self): - g_appLoader.onGUISpaceEntered += self.__onGUISpaceEntered - g_appLoader.onGUISpaceLeft += self.__onGUISpaceLeft - - def _destroy(self): - g_appLoader.onGUISpaceEntered -= self.__onGUISpaceEntered - g_appLoader.onGUISpaceLeft -= self.__onGUISpaceLeft - - def _populate(self): - g_eventBus.addListener(events.GameEvent.SHOW_CURSOR, self.__handleShowCursor, EVENT_BUS_SCOPE.GLOBAL) - g_eventBus.addListener(events.GameEvent.HIDE_CURSOR, self.__handleHideCursor, EVENT_BUS_SCOPE.GLOBAL) - g_eventBus.addListener(events.GameEvent.RADIAL_MENU_CMD, self.__toggleRadialMenu, scope=EVENT_BUS_SCOPE.BATTLE) - g_eventBus.addListener(events.GameEvent.FULL_STATS, self.__toggleFullStats, scope=EVENT_BUS_SCOPE.BATTLE) - - def _dispose(self): - g_eventBus.removeListener(events.GameEvent.SHOW_CURSOR, self.__handleShowCursor, EVENT_BUS_SCOPE.GLOBAL) - g_eventBus.removeListener(events.GameEvent.HIDE_CURSOR, self.__handleHideCursor, EVENT_BUS_SCOPE.GLOBAL) - g_eventBus.removeListener(events.GameEvent.RADIAL_MENU_CMD, self.__toggleRadialMenu, - scope=EVENT_BUS_SCOPE.BATTLE) - g_eventBus.removeListener(events.GameEvent.FULL_STATS, self.__toggleFullStats, scope=EVENT_BUS_SCOPE.BATTLE) - - def __onGUISpaceEntered(self, spaceID): - if spaceID == SPACE_ID.LOGIN: - g_guiEvents.goToLogin() - elif spaceID == SPACE_ID.LOBBY: - g_guiEvents.goToLobby() - elif spaceID == SPACE_ID.BATTLE_LOADING: - g_guiEvents.goToBattleLoading() - elif spaceID == SPACE_ID.BATTLE: - g_guiEvents.goToBattle() - - def __onGUISpaceLeft(self, spaceID): - if spaceID == SPACE_ID.LOBBY: - g_guiEvents.leaveLobby() - elif spaceID == SPACE_ID.BATTLE: - g_guiEvents.leaveBattle() - - def __handleShowCursor(self, _): - isShow = True - g_guiEvents.toggleCursor(isShow) - - def __handleHideCursor(self, _): - isShow = False - g_guiEvents.toggleCursor(isShow) - - def __toggleFullStats(self, event): - isDown = event.ctx['isDown'] - g_guiEvents.toggleFullStats(isDown) - - def __toggleRadialMenu(self, event): - if BattleReplay.isPlaying(): - return - isDown = event.ctx['isDown'] - g_guiEvents.toggleRadialMenu(isDown) - - -class Events(object): - def goToLogin(self): - pass - - def goToLobby(self): - pass - - def goToBattleLoading(self): - pass - - def goToBattle(self): - g_appLoader.getApp().loadView(ViewLoadParams(CONSTANTS.VIEW_ALIAS)) - - def leaveLobby(self): - pass - - def leaveBattle(self): - pass - - def toggleCursor(self, isShow): - g_guiViews.cursor(isShow) - - def toggleFullStats(self, isShow): - g_guiViews.fullStats(isShow) - - def toggleRadialMenu(self, isShow): - g_guiViews.radialMenu(isShow) - - -class Settings(object): - def _start(self): - g_entitiesFactories.addSettings( - ViewSettings(CONSTANTS.VIEW_ALIAS, Flash_UI, CONSTANTS.FILE_NAME, ViewTypes.WINDOW, None, - ScopeTemplates.GLOBAL_SCOPE)) - - def _destroy(self): - g_entitiesFactories.removeSettings(CONSTANTS.VIEW_ALIAS) - - -class Flash_Meta(View): - def py_log(self, *args): - self._printOverrideError('py_log') - - def py_update(self, alias, props): - self._printOverrideError('py_update') - - def as_createS(self, alias, type, props): - if self._isDAAPIInited(): - return self.flashObject.as_create(alias, type, props) - - def as_updateS(self, alias, props): - if self._isDAAPIInited(): - return self.flashObject.as_update(alias, props) - - def as_deleteS(self, alias): - if self._isDAAPIInited(): - return self.flashObject.as_delete(alias) - - def as_cursorS(self, isShow): - if self._isDAAPIInited(): - return self.flashObject.as_cursor(isShow) - - def as_fullStatsS(self, isShow): - if self._isDAAPIInited(): - return self.flashObject.as_fullStats(isShow) - - def as_radialMenuS(self, isShow): - if self._isDAAPIInited(): - return self.flashObject.as_radialMenu(isShow) - - -class Flash_UI(Flash_Meta): - def _populate(self): - super(Flash_UI, self)._populate() - g_guiHooks._populate() - g_guiViews.ui = self - g_guiViews.createAll() - - def _dispose(self): - g_guiViews.ui = None - g_guiHooks._dispose() - super(Flash_UI, self)._dispose() - - def py_log(self, *args): - LOG_NOTE('GUIFlash :', *args) - - def py_update(self, alias, props): - g_guiCache.update(alias, props.toDict()) - COMPONENT_EVENT.UPDATED(alias, props.toDict()) - - -class GUIFlash(object): - def __init__(self): - g_guiSettings._start() - g_guiHooks._start() - - def __del__(self): - g_guiHooks._destroy() - g_guiSettings._destroy() - - def createComponent(self, alias, type, props=None): - if not g_guiCache.isComponent(alias): - type = g_guiCache.getCustomizedType(type) - if g_guiCache.isTypeValid(type): - g_guiCache.create(alias, type, props) - g_guiViews.create(alias, type, props) - else: - LOG_ERROR('GUIFlash :', 'Invalid type of component "%s"!' % alias) - else: - LOG_ERROR('GUIFlash :', 'Component "%s" already exists!' % alias) - - def updateComponent(self, alias, props): - if g_guiCache.isComponent(alias): - g_guiCache.update(alias, props) - g_guiViews.update(alias, props) - else: - LOG_ERROR('GUIFlash :', 'Component "%s" not found!' % alias) - - def deleteComponent(self, alias): - if g_guiCache.isComponent(alias): - g_guiCache.delete(alias) - g_guiViews.delete(alias) - else: - LOG_ERROR('GUIFlash :', 'Component "%s" not found!' % alias) - - -g_guiCache = Cache() -g_guiViews = Views() -g_guiHooks = Hooks() -g_guiEvents = Events() -g_guiSettings = Settings() +# -*- coding: utf-8 -*- + +__all__ = ['COMPONENT_TYPE', 'COMPONENT_ALIGN', 'COMPONENT_EVENT'] + +import Event +import BattleReplay +import json, codecs +from gui.app_loader import g_appLoader +from gui.app_loader.settings import GUI_GLOBAL_SPACE_ID as SPACE_ID +from gui.shared import g_eventBus, events, EVENT_BUS_SCOPE +from gui.Scaleform.framework.entities.View import View +from gui.Scaleform.framework.managers.loaders import SFViewLoadParams +from gui.Scaleform.framework import g_entitiesFactories, ViewSettings, ViewTypes, ScopeTemplates +from utils import LOG_NOTE, LOG_DEBUG, LOG_ERROR + + +class CONSTANTS(object): + FILE_NAME = 'GUIFlash.swf' + VIEW_ALIAS = 'GUIFlash' + + +class COMPONENT_TYPE(object): + PANEL = 'Panel' + LABEL = 'Label' + IMAGE = 'Image' + SHAPE = 'Shape' + + +ALL_COMPONENT_TYPES = (COMPONENT_TYPE.PANEL, COMPONENT_TYPE.LABEL, COMPONENT_TYPE.IMAGE, COMPONENT_TYPE.SHAPE) + + +class COMPONENT_ALIGN(object): + LEFT = 'left' + RIGHT = 'right' + CENTER = 'center' + TOP = "top" + BOTTOM = 'bottom' + + +class COMPONENT_STATE(object): + INIT = 1 + LOAD = 2 + UNLOAD = 3 + DESTROY = 4 + +class COMPONENT_EVENT(object): + LOADED = Event.Event() + UPDATED = Event.Event() + UNLOADED = Event.Event() + + +class Cache(object): + + def __init__(self): + self.components = {} + + def create(self, alias, type, props): + self.components[alias] = {'type': type, 'props': props} + LOG_DEBUG('GUIFlash :', 'Cache "%s" [%s] created. Parameters: %s' % (alias, type, props)) + + def update(self, alias, props): + self.components[alias].get('props').update(props) + LOG_DEBUG('GUIFlash :', 'Cache "%s" updated. Parameters: %s' % (alias, props)) + + def delete(self, alias): + del self.components[alias] + LOG_DEBUG('GUIFlash :', 'Cache "%s" deleted.' % alias) + + def isComponent(self, alias): + return alias in self.components + + def getComponent(self, alias=None): + if alias is None: + return self.components + return self.components.get(alias) + + def getKeys(self): + return sorted(self.components.keys()) + + def getCustomizedType(self, type): + return ''.join(type.split()).capitalize() + + def isTypeValid(self, type): + return type in ALL_COMPONENT_TYPES + + # .. + def readConfig(self, file): + LOG_DEBUG('GUIFlash :', 'Read config from file "%s".' % file) + with open(file, "r") as file: + data = json.load(file) + return data + + # .. + def saveConfig(self, file, data): + LOG_DEBUG('GUIFlash :', 'Save config in file "%s".' % file) + with open(file, 'wb') as file: + json.dump(data, codecs.getwriter('utf-8')(file), indent=4, sort_keys=True, ensure_ascii=False) + + +class Views(object): + + def __init__(self): + self.ui = None + + def createAll(self): + for alias in g_guiCache.getKeys(): + component = g_guiCache.getComponent(alias) + self.create(alias, component.get('type'), component.get('props')) + + def create(self, alias, type, props): + if self.ui is not None: + self.ui.as_createS(alias, type, props) + LOG_DEBUG('GUIFlash :', 'Component "%s" [%s] created. Parameters: %s' % (alias, type, props)) + + def update(self, alias, props): + if self.ui is not None: + self.ui.as_updateS(alias, props) + LOG_DEBUG('GUIFlash :', 'Component "%s" updated. Parameters: %s' % (alias, props)) + + def delete(self, alias): + if self.ui is not None: + self.ui.as_deleteS(alias) + LOG_DEBUG('GUIFlash :', 'Component "%s" deleted.' % alias) + + def cursor(self, isShow): + if self.ui is not None: + self.ui.as_cursorS(isShow) + + def fullStats(self, isShow): + if self.ui is not None: + self.ui.as_fullStatsS(isShow) + + def radialMenu(self, isShow): + if self.ui is not None: + self.ui.as_radialMenuS(isShow) + + +class Hooks(object): + + def _start(self): + g_appLoader.onGUISpaceEntered += self.__onGUISpaceEntered + g_appLoader.onGUISpaceLeft += self.__onGUISpaceLeft + + def _destroy(self): + g_appLoader.onGUISpaceEntered -= self.__onGUISpaceEntered + g_appLoader.onGUISpaceLeft -= self.__onGUISpaceLeft + + def _populate(self): + g_eventBus.addListener(events.GameEvent.SHOW_CURSOR, self.__handleShowCursor, EVENT_BUS_SCOPE.GLOBAL) + g_eventBus.addListener(events.GameEvent.HIDE_CURSOR, self.__handleHideCursor, EVENT_BUS_SCOPE.GLOBAL) + g_eventBus.addListener(events.GameEvent.RADIAL_MENU_CMD, self.__toggleRadialMenu, scope=EVENT_BUS_SCOPE.BATTLE) + g_eventBus.addListener(events.GameEvent.FULL_STATS, self.__toggleFullStats, scope=EVENT_BUS_SCOPE.BATTLE) + + def _dispose(self): + g_eventBus.removeListener(events.GameEvent.SHOW_CURSOR, self.__handleShowCursor, EVENT_BUS_SCOPE.GLOBAL) + g_eventBus.removeListener(events.GameEvent.HIDE_CURSOR, self.__handleHideCursor, EVENT_BUS_SCOPE.GLOBAL) + g_eventBus.removeListener(events.GameEvent.RADIAL_MENU_CMD, self.__toggleRadialMenu, + scope=EVENT_BUS_SCOPE.BATTLE) + g_eventBus.removeListener(events.GameEvent.FULL_STATS, self.__toggleFullStats, scope=EVENT_BUS_SCOPE.BATTLE) + + def __onGUISpaceEntered(self, spaceID): + if spaceID == SPACE_ID.LOGIN: + g_guiEvents.goToLogin() + elif spaceID == SPACE_ID.LOBBY: + g_guiEvents.goToLobby() + elif spaceID == SPACE_ID.BATTLE_LOADING: + g_guiEvents.goToBattleLoading() + elif spaceID == SPACE_ID.BATTLE: + g_guiEvents.goToBattle() + + def __onGUISpaceLeft(self, spaceID): + if spaceID == SPACE_ID.LOBBY: + g_guiEvents.leaveLobby() + elif spaceID == SPACE_ID.BATTLE: + g_guiEvents.leaveBattle() + + def __handleShowCursor(self, _): + isShow = True + g_guiEvents.toggleCursor(isShow) + + def __handleHideCursor(self, _): + isShow = False + g_guiEvents.toggleCursor(isShow) + + def __toggleFullStats(self, event): + isDown = event.ctx['isDown'] + g_guiEvents.toggleFullStats(isDown) + + def __toggleRadialMenu(self, event): + if BattleReplay.isPlaying(): + return + isDown = event.ctx['isDown'] + g_guiEvents.toggleRadialMenu(isDown) + + +class Events(object): + + def goToLogin(self): + pass + + def goToLobby(self): + pass + + def goToBattleLoading(self): + pass + + def goToBattle(self): + g_appLoader.getApp().loadView(SFViewLoadParams(CONSTANTS.VIEW_ALIAS)) + + def leaveLobby(self): + pass + + def leaveBattle(self): + pass + + def toggleCursor(self, isShow): + g_guiViews.cursor(isShow) + + def toggleFullStats(self, isShow): + g_guiViews.fullStats(isShow) + + def toggleRadialMenu(self, isShow): + g_guiViews.radialMenu(isShow) + + +class Settings(object): + + def _start(self): + g_entitiesFactories.addSettings( + ViewSettings(CONSTANTS.VIEW_ALIAS, Flash_UI, CONSTANTS.FILE_NAME, ViewTypes.WINDOW, None, ScopeTemplates.GLOBAL_SCOPE)) + + def _destroy(self): + g_entitiesFactories.removeSettings(CONSTANTS.VIEW_ALIAS) + + +class Flash_Meta(View): + + def py_log(self, *args): + self._printOverrideError('py_log') + + def py_update(self, alias, props): + self._printOverrideError('py_update') + + def as_createS(self, alias, type, props): + if self._isDAAPIInited(): + return self.flashObject.as_create(alias, type, props) + + def as_updateS(self, alias, props): + if self._isDAAPIInited(): + return self.flashObject.as_update(alias, props) + + def as_deleteS(self, alias): + if self._isDAAPIInited(): + return self.flashObject.as_delete(alias) + + def as_cursorS(self, isShow): + if self._isDAAPIInited(): + return self.flashObject.as_cursor(isShow) + + def as_fullStatsS(self, isShow): + if self._isDAAPIInited(): + return self.flashObject.as_fullStats(isShow) + + def as_radialMenuS(self, isShow): + if self._isDAAPIInited(): + return self.flashObject.as_radialMenu(isShow) + + +class Flash_UI(Flash_Meta): + + def _populate(self): + super(Flash_UI, self)._populate() + g_guiHooks._populate() + g_guiViews.ui = self + g_guiViews.createAll() + + def _dispose(self): + g_guiViews.ui = None + g_guiHooks._dispose() + super(Flash_UI, self)._dispose() + + def py_log(self, *args): + LOG_NOTE('GUIFlash :', *args) + + def py_update(self, alias, props): + g_guiCache.update(alias, props.toDict()) + COMPONENT_EVENT.UPDATED(alias, props.toDict()) + + +class GUIFlash(object): + + def __init__(self): + g_guiSettings._start() + g_guiHooks._start() + + def __del__(self): + g_guiHooks._destroy() + g_guiSettings._destroy() + + def createComponent(self, alias, type, props=None): + if not g_guiCache.isComponent(alias): + type = g_guiCache.getCustomizedType(type) + if g_guiCache.isTypeValid(type): + g_guiCache.create(alias, type, props) + g_guiViews.create(alias, type, props) + else: + LOG_ERROR('GUIFlash :', 'Invalid type of component "%s"!' % alias) + else: + LOG_ERROR('GUIFlash :', 'Component "%s" already exists!' % alias) + + def updateComponent(self, alias, props): + if g_guiCache.isComponent(alias): + g_guiCache.update(alias, props) + g_guiViews.update(alias, props) + else: + LOG_ERROR('GUIFlash :', 'Component "%s" not found!' % alias) + + def deleteComponent(self, alias): + if g_guiCache.isComponent(alias): + g_guiCache.delete(alias) + g_guiViews.delete(alias) + else: + LOG_ERROR('GUIFlash :', 'Component "%s" not found!' % alias) + + +g_guiCache = Cache() +g_guiViews = Views() +g_guiHooks = Hooks() +g_guiEvents = Events() +g_guiSettings = Settings() diff --git a/res/scripts/client/gui/mods/gambiter/flash.pyc b/res/scripts/client/gui/mods/gambiter/flash.pyc index fcc316a..547fe88 100644 Binary files a/res/scripts/client/gui/mods/gambiter/flash.pyc and b/res/scripts/client/gui/mods/gambiter/flash.pyc differ diff --git a/res/scripts/client/gui/mods/gambiter/utils.py b/res/scripts/client/gui/mods/gambiter/utils.py index 8a80dff..c133d61 100644 --- a/res/scripts/client/gui/mods/gambiter/utils.py +++ b/res/scripts/client/gui/mods/gambiter/utils.py @@ -1,156 +1,163 @@ -# -*- coding: utf-8 -*- - - -IS_DEBUG = True - - -def LOG(arg, *args): - print str(arg), ' '.join([str(arg) for arg in args]) - - -def LOG_NOTE(*args): - LOG('[NOTE]', *args) - - -def LOG_ERROR(*args): - LOG('[ERROR]', *args) - - -def LOG_DEBUG(*args): - if IS_DEBUG: - LOG('[DEBUG]', *args) - - -def LOG_TRACE(exc=None): - import traceback - print('=') * 25 - if exc is not None: - LOG_ERROR(exc) - traceback.print_exc() - else: - traceback.print_stack() - print('=') * 25 - - -def LOG_DIR(object, include=None, exclude=None): - print('=') * 25 - for attr in dir(object): - if (include is None or attr.find(include) >= 0) and (exclude is None or attr.find(exclude) == -1): - try: - LOG('[DIR]', 'object.%s = %s' % (attr, getattr(object, attr))) - except: - LOG('[DIR]', 'object.%s = %s' % (attr, '')) - print('=') * 25 - - -def debugLog(func): - def wrapper(*args, **kwargs): - try: - func(*args, **kwargs) - LOG_DEBUG("Function '%s' completed!" % func.func_name) - except Exception as Error: - LOG_ERROR("Error in function '%s': %s!" % (func.func_name, Error)) - - return wrapper - - -def debugTime(func): - def wrapper(*args, **kwargs): - import time - startTime = time.time() - func(*args, **kwargs) - LOG_DEBUG("Method '%s' measuring time: %.10f" % (func.func_name, time.time() - startTime)) - - return wrapper - - -class EventHook(object): - def __init__(self): - self.__handlers = [] - - def __iadd__(self, handler): - self.__handlers.append(handler) - return self - - def __isub__(self, handler): - if handler in self.__handlers: - self.__handlers.remove(handler) - return self - - def fire(self, *args, **keywargs): - for handler in self.__handlers: - handler(*args, **keywargs) - - def clearObjectHandlers(self, inObject): - for theHandler in self.__handlers: - if theHandler.im_self == inObject: - self -= theHandler - - -def _RegisterEvent(handler, cls, method, prepend=False): - evt = '__event_%i_%s' % ((1 if prepend else 0), method) - if hasattr(cls, evt): - e = getattr(cls, evt) - else: - newm = '__orig_%i_%s' % ((1 if prepend else 0), method) - setattr(cls, evt, EventHook()) - setattr(cls, newm, getattr(cls, method)) - e = getattr(cls, evt) - m = getattr(cls, newm) - setattr(cls, method, lambda *a, **k: __event_handler(prepend, e, m, *a, **k)) - e += handler - - -def __event_handler(prepend, e, m, *a, **k): - try: - if prepend: - e.fire(*a, **k) - r = m(*a, **k) - else: - r = m(*a, **k) - e.fire(*a, **k) - return r - except: - LOG_TRACE(__file__) - - -def _override(cls, method, newm): - orig = getattr(cls, method) - if type(orig) is not property: - setattr(cls, method, newm) - else: - setattr(cls, method, property(newm)) - - -def _OverrideMethod(handler, cls, method): - orig = getattr(cls, method) - newm = lambda *a, **k: handler(orig, *a, **k) - _override(cls, method, newm) - - -def _OverrideStaticMethod(handler, cls, method): - orig = getattr(cls, method) - newm = staticmethod(lambda *a, **k: handler(orig, *a, **k)) - _override(cls, method, newm) - - -def _OverrideClassMethod(handler, cls, method): - orig = getattr(cls, method) - newm = classmethod(lambda *a, **k: handler(orig, *a, **k)) - _override(cls, method, newm) - - -def _hook_decorator(func): - def decorator1(*a, **k): - def decorator2(handler): - func(handler, *a, **k) - - return decorator2 - - return decorator1 - - -registerEvent = _hook_decorator(_RegisterEvent) -overrideMethod = _hook_decorator(_OverrideMethod) -overrideStaticMethod = _hook_decorator(_OverrideStaticMethod) -overrideClassMethod = _hook_decorator(_OverrideClassMethod) +# -*- coding: utf-8 -*- + + +IS_DEBUG = False + + +def LOG(arg, *args): + print str(arg), ' '.join([str(arg) for arg in args]) + + +def LOG_NOTE(*args): + LOG('[NOTE]', *args) + + +def LOG_ERROR(*args): + LOG('[ERROR]', *args) + + +def LOG_DEBUG(*args): + if IS_DEBUG: + LOG('[DEBUG]', *args) + + +def LOG_TRACE(exc=None): + + import traceback + + print('=') * 25 + if exc is not None: + LOG_ERROR(exc) + traceback.print_exc() + else: + traceback.print_stack() + print('=') * 25 + + +def LOG_DIR(object, include=None, exclude=None): + print('=') * 25 + for attr in dir(object): + if (include is None or attr.find(include) >= 0) and (exclude is None or attr.find(exclude) == -1): + try: + LOG('[DIR]', 'object.%s = %s' % (attr, getattr(object, attr))) + except: + LOG('[DIR]', 'object.%s = %s' % (attr, '')) + print('=') * 25 + + +def debugLog(func): + + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + LOG_DEBUG("Function '%s' completed!" % func.func_name) + except Exception as Error: + LOG_ERROR("Error in function '%s': %s!" % (func.func_name, Error)) + + return wrapper + + +def debugTime(func): + + def wrapper(*args, **kwargs): + import time + startTime = time.time() + func(*args, **kwargs) + LOG_DEBUG("Method '%s' measuring time: %.10f" % (func.func_name, time.time() - startTime)) + + return wrapper + + +class EventHook(object): + + def __init__(self): + self.__handlers = [] + + def __iadd__(self, handler): + self.__handlers.append(handler) + return self + + def __isub__(self, handler): + if handler in self.__handlers: + self.__handlers.remove(handler) + return self + + def fire(self, *args, **keywargs): + for handler in self.__handlers: + handler(*args, **keywargs) + + def clearObjectHandlers(self, inObject): + for theHandler in self.__handlers: + if theHandler.im_self == inObject: + self -= theHandler + + +def _RegisterEvent(handler, cls, method, prepend=False): + evt = '__event_%i_%s' % ((1 if prepend else 0), method) + if hasattr(cls, evt): + e = getattr(cls, evt) + else: + newm = '__orig_%i_%s' % ((1 if prepend else 0), method) + setattr(cls, evt, EventHook()) + setattr(cls, newm, getattr(cls, method)) + e = getattr(cls, evt) + m = getattr(cls, newm) + setattr(cls, method, lambda *a, **k: __event_handler(prepend, e, m, *a, **k)) + e += handler + + +def __event_handler(prepend, e, m, *a, **k): + try: + if prepend: + e.fire(*a, **k) + r = m(*a, **k) + else: + r = m(*a, **k) + e.fire(*a, **k) + return r + except: + LOG_TRACE(__file__) + + +def _override(cls, method, newm): + orig = getattr(cls, method) + if type(orig) is not property: + setattr(cls, method, newm) + else: + setattr(cls, method, property(newm)) + + +def _OverrideMethod(handler, cls, method): + orig = getattr(cls, method) + newm = lambda *a, **k: handler(orig, *a, **k) + _override(cls, method, newm) + + +def _OverrideStaticMethod(handler, cls, method): + orig = getattr(cls, method) + newm = staticmethod(lambda *a, **k: handler(orig, *a, **k)) + _override(cls, method, newm) + + +def _OverrideClassMethod(handler, cls, method): + orig = getattr(cls, method) + newm = classmethod(lambda *a, **k: handler(orig, *a, **k)) + _override(cls, method, newm) + + +def _hook_decorator(func): + + def decorator1(*a, **k): + + def decorator2(handler): + func(handler, *a, **k) + + return decorator2 + + return decorator1 + + +registerEvent = _hook_decorator(_RegisterEvent) +overrideMethod = _hook_decorator(_OverrideMethod) +overrideStaticMethod = _hook_decorator(_OverrideStaticMethod) +overrideClassMethod = _hook_decorator(_OverrideClassMethod) diff --git a/res/scripts/client/gui/mods/gambiter/utils.pyc b/res/scripts/client/gui/mods/gambiter/utils.pyc index b7d2db5..aa644a7 100644 Binary files a/res/scripts/client/gui/mods/gambiter/utils.pyc and b/res/scripts/client/gui/mods/gambiter/utils.pyc differ