123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- ########################################################################
- # Hello Worlds - Libre 3D RPG game.
- # Copyright (C) 2020 CYBERDEViL
- #
- # This file is part of Hello Worlds.
- #
- # Hello Worlds is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # Hello Worlds is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- #
- ########################################################################
- from LUIFrame import LUIFrame
- from LUILabel import LUILabel
- from LUIProgressbar import LUIProgressbar
- from LUILayouts import LUIHorizontalLayout
- from LUIVerticalLayout import LUIVerticalLayout
- from LUISprite import LUISprite
- from LUIObject import LUIObject
- from LUIInitialState import LUIInitialState
- from core.models import ItemModel
- class UI_ItemInfo(LUIFrame):
- def __init__(self, **kwargs):
- LUIFrame.__init__(self, style=LUIFrame.FS_raised, **kwargs)
- self.margin = 0
- self._model = None
- self._descLabelFmt = "Description: {}"
- self._descLabel = LUILabel("", parent=self, margin=0, left=3, top=3)
- self.hide()
- def setModel(self, model):
- self._model = model
- if model:
- self._descLabel.set_text(self._descLabelFmt.format(model.description))
- else: self._modelRemoved()
- def close(self): self.parent = None
- def _modelRemoved(self):
- self._descLabel.set_text(self._descLabelFmt)
- class UI_DragItem(LUIObject):
- icons = {
- 'unknown' : "assets/icons/unknown.png",
- 'empty' : "assets/icons/overlay_0.png"
- }
- def __init__(self, *args, **kwargs):
- LUIObject.__init__(self, *args)
- self.width = 48
- self.height = 48
- self._icon = LUISprite(self, self.icons['empty'], width=self.width, height=self.height)
- self.set_pos(100,100)
- class UI_Item(LUIObject):
- icons = {
- 'unknown' : "assets/icons/unknown.png",
- 'empty' : "assets/icons/overlay_0.png"
- }
- def __init__(self, *args, **kwargs):
- # Without solid=True it doesn't receive mouse-events
- LUIObject.__init__(self, *args, solid=True)
- self.width = 48
- self.height = 48
- self._model = None
- self._isDragging = False
- self._backupParent = self.parent
- self._dragItem = None
- self._icon = LUISprite(self, self.icons['empty'], width=self.width, height=self.height)
- self._label = LUILabel("", parent=self, margin=0, left=0, bottom=0)
- self._overlay = None
- LUIInitialState.init(self, kwargs)
- def mousePos(self):
- if base.mouseWatcherNode.hasMouse():
- mpos = base.mouseWatcherNode.getMouse()
- mousePos = (mpos.getX() * base.getAspectRatio(), mpos.getY())
- screenWidth = base.win.getProperties().getXSize()
- screenHeight = base.win.getProperties().getYSize()
- ratio = base.getAspectRatio()
- # https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
- left = (((mousePos[0] - -ratio) * (screenWidth - 0)) / (ratio - -ratio)) + 0
- top = (((mousePos[1] - 1) * (screenHeight - 0)) / (-1 - 1)) + 0
- return (left, top)
- return(0,0)
- def _dragWatcher(self, event=None):
- if not self._dragItem:
- print("Start drag")
- self._dragItem = UI_DragItem(base.luiRegion.root)
- self.unbind('mousemove')
- taskMgr.add(self._dragTask, 'dragWatcher')
- def _dragTask(self, task):
- self._dragItem.set_pos(self.mousePos())
- return task.cont
- def _stopDrag(self):
- if self._dragItem:
- print("Stop drag")
- taskMgr.remove('dragWatcher')
- self._dragItem.parent = None
- self._dragItem = None
- def on_mouseover(self, event):
- if self._model:
- pos = self.get_abs_pos()
- pos -= (-50,50)
- base.uiManager.spellInfoFrame.setModel(self._model)
- base.uiManager.spellInfoFrame.set_pos(pos)
- base.uiManager.spellInfoFrame.show()
- def on_mouseout(self, event):
- if self._model:
- base.uiManager.spellInfoFrame.hide()
- def on_mousedown(self, event):
- if self._model:
- #self.bind('mousemove', self._dragWatcher) # uncomment to enable drag 'n drop (that isn't complete yet)
- self._addOverlay()
- def on_mouseup(self, event):
- if self._model:
- self._stopDrag()
- self._removeOverlay()
- def _addOverlay(self):
- overlayPath = "assets/icons/overlay_1.png"
- if not self._overlay:
- self._overlay = LUISprite(self, overlayPath, width=self.width, height=self.height)
- def _removeOverlay(self):
- if self._overlay:
- self._overlay.parent = None
- self._overlay = None
- def setModel(self, model):
- self._model = model
- if model:
- self._icon.set_texture(model.iconPath, resize=False)
- self._label.set_text(model.name)
- else: self._modelRemoved()
- def _modelRemoved(self):
- self._icon.set_texture(self.icons['empty'], resize=False)
- self._label.set_text("")
- class UI_SpellBar(LUIFrame):
- def __init__(self, **kwargs):
- LUIFrame.__init__(self, style=LUIFrame.FS_sunken, **kwargs)
- self.height = 68
- self.margin = 0
- screenHeight = base.win.getProperties().getYSize()
- self.top = screenHeight - 68 - 3
- self.center_horizontal = True
- self._layout = LUIHorizontalLayout(parent=self)
- self._layout.spacing = 3
- maxItems = 10
- self._items = []
- for i in range(0, maxItems):
- self._items.append(UI_Item(self._layout.cell()))
- """ TODO TMP add some spells for testing
- These spells or actions? shouldn't be static like this..
- """
- spell1Test = ItemModel(
- name="Melee 1",
- iconPath="assets/icons/attack_0.png",
- desc="Melee attack level 1")
- self._items[0].setModel(spell1Test)
- spell1Test = ItemModel(
- name="Melee 2",
- iconPath="assets/icons/attack_0.png",
- desc="Melee attack level 2")
- self._items[1].setModel(spell1Test)
- base.accept('WINDOW_RESIZED', self.reposition)
- def reposition(self):
- self.top = base.win.getProperties().getYSize() - self.height - 10
- def close(self): self.parent = None
- class UI_PlayerInfoBox(LUIFrame):
- def __init__(self, parent=None, top=10, left=10):
- if not parent: parent = base.luiRegion.root
- LUIFrame.__init__(self, parent=parent, style=LUIFrame.FS_sunken, width=170, height=80, margin=0, top=top, left=left)
- self._layout = LUIVerticalLayout(self)
- self.nameLabel = LUILabel(parent=self._layout.cell(), text="Name: ")
- self.healthBar = LUIProgressbar(parent=self._layout.cell(), width=145, label_fmt="Health: {value}/{max}")
- self.energyBar = LUIProgressbar(parent=self._layout.cell(), width=145, label_fmt="Energy: {value}/{max}")
- self.healthBar.set_max(base.world.player.character.stats.health.max)
- self.healthBar.set_value(base.world.player.character.stats.health.value)
- self.energyBar.set_max(base.world.player.character.stats.energy.max)
- self.energyBar.set_value(base.world.player.character.stats.energy.value)
- base.world.player.character.stats.health.valueChanged.connect(self._healthChanged)
- base.world.player.character.stats.energy.valueChanged.connect(self._energyChanged)
- def _healthChanged(self, value): self.healthBar.set_value(value)
- def _energyChanged(self, value): self.energyBar.set_value(value)
- def close(self): self.parent = None
- class UI_CreatureInfoBox:
- def __init__(self, parent=None, top=100, left=10):
- if not parent: parent = base.luiRegion.root
- self._currentSpawnId = -1
- self._container = LUIFrame(parent=parent, width=175, height=55, style=LUIFrame.FS_sunken, margin=0, top=top, left=left)
- self.nameLabel = LUILabel(parent=self._container, text="Name: ", top=0)
- self.healthBar = LUIProgressbar(parent=self._container, width=145, top=20, label_fmt="Health: {value}/{max}")
- base.world.npcsManager.selectedNpcModel.changed.connect(self._selectionChanged)
- self.hide()
- def hasMouse(self): return self._container.hasMouse()
- def _selectionChanged(self, spawnId):
- if self._currentSpawnId == spawnId and self._currentSpawnId != -1:
- # Clicked twice or more
- # This is a TMP-test.. remove later TODO
- npc = base.world.npcsManager.getSpawn(self._currentSpawnId) # creaturesManager.Creature
- npc.stats.health.value -= 10
- if npc.stats.health.value <= 0: # NPC died
- spawnId = -1
- # Disconnect previously set connections
- if self._currentSpawnId != -1 and self._currentSpawnId != spawnId:
- oldNpc = base.world.npcsManager.getSpawn(self._currentSpawnId) # creaturesManager.Creature
- oldNpc.stats.health.valueChanged.disconnect(self._healthChanged)
- oldNpc.removeSelectPlane()
- # Hide if selected id is -1
- if spawnId == -1:
- self.hide()
- self._currentSpawnId = -1
- return
- if self._currentSpawnId != spawnId:
- self.show()
- npc = base.world.npcsManager.getSpawn(spawnId) # creaturesManager.Creature
- npc.addSelectPlane()
- # Name
- self.nameLabel.text = "{0} (id: {1} lvl: {2})".format(npc.data.name, npc.id, npc.stats.level.value)
- # Health
- self.healthBar.set_max(npc.stats.health.max)
- self.healthBar.set_value(npc.stats.health.value)
- self._currentSpawnId = spawnId
- npc.stats.health.valueChanged.connect(self._healthChanged)
- def _healthChanged(self, value):
- npc = base.world.npcsManager.getSpawn(self._currentSpawnId)
- self.healthBar.set_value(npc.stats.health.value)
- def close(self):
- self._container.parent = None
- self._container = None
- def hide(self):
- self._container.hide()
- def show(self):
- self._container.show()
- def isVisible(self): return self._container.visible
|