Settings & UI: Port persistent JSON Settings system and revamped tabbed OptionsPage ShtikerBook
This commit is contained in:
parent
54f87a9230
commit
ff1a95e360
|
|
@ -4,3 +4,44 @@ from .SCStaticTextTerminal import SCStaticTextMsgEvent
|
|||
from .SCGMTextTerminal import SCGMTextMsgEvent
|
||||
from .SCCustomTerminal import SCCustomMsgEvent
|
||||
from .SCEmoteTerminal import SCEmoteMsgEvent, SCEmoteNoAccessEvent
|
||||
|
||||
speedChatStyles = ((2000,
|
||||
(200 / 255.0, 60 / 255.0, 229 / 255.0),
|
||||
(200 / 255.0, 135 / 255.0, 255 / 255.0),
|
||||
(220 / 255.0, 195 / 255.0, 229 / 255.0)),
|
||||
(2001,
|
||||
(0 / 255.0, 0 / 255.0, 255 / 255.0),
|
||||
(140 / 255.0, 150 / 255.0, 235 / 255.0),
|
||||
(201 / 255.0, 215 / 255.0, 255 / 255.0)),
|
||||
(2002,
|
||||
(90 / 255.0, 175 / 255.0, 225 / 255.0),
|
||||
(120 / 255.0, 215 / 255.0, 255 / 255.0),
|
||||
(208 / 255.0, 230 / 255.0, 250 / 255.0)),
|
||||
(2003,
|
||||
(130 / 255.0, 235 / 255.0, 235 / 255.0),
|
||||
(120 / 255.0, 225 / 255.0, 225 / 255.0),
|
||||
(234 / 255.0, 255 / 255.0, 255 / 255.0)),
|
||||
(2004,
|
||||
(0 / 255.0, 200 / 255.0, 70 / 255.0),
|
||||
(0 / 255.0, 200 / 255.0, 80 / 255.0),
|
||||
(204 / 255.0, 255 / 255.0, 204 / 255.0)),
|
||||
(2005,
|
||||
(235 / 255.0, 230 / 255.0, 0 / 255.0),
|
||||
(255 / 255.0, 250 / 255.0, 100 / 255.0),
|
||||
(255 / 255.0, 250 / 255.0, 204 / 255.0)),
|
||||
(2006,
|
||||
(255 / 255.0, 153 / 255.0, 0 / 255.0),
|
||||
(229 / 255.0, 147 / 255.0, 0 / 255.0),
|
||||
(255 / 255.0, 234 / 255.0, 204 / 255.0)),
|
||||
(2007,
|
||||
(255 / 255.0, 0 / 255.0, 50 / 255.0),
|
||||
(229 / 255.0, 0 / 255.0, 50 / 255.0),
|
||||
(255 / 255.0, 204 / 255.0, 204 / 255.0)),
|
||||
(2008,
|
||||
(255 / 255.0, 153 / 255.0, 193 / 255.0),
|
||||
(240 / 255.0, 157 / 255.0, 192 / 255.0),
|
||||
(255 / 255.0, 215 / 255.0, 238 / 255.0)),
|
||||
(2009,
|
||||
(170 / 255.0, 120 / 255.0, 20 / 255.0),
|
||||
(165 / 255.0, 120 / 255.0, 50 / 255.0),
|
||||
(210 / 255.0, 200 / 255.0, 180 / 255.0)))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from direct.distributed import DistributedObject
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from toontown.effects.FireworkShowMixin import FireworkShowMixin
|
||||
|
||||
class DistributedFireworkShow(DistributedObject.DistributedObject, FireworkShowMixin):
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ from .PartyGlobals import FireworksFinishedEvent
|
|||
from .PartyGlobals import FireworksPostLaunchDelay
|
||||
from .PartyGlobals import RocketSoundDelay
|
||||
from .PartyGlobals import RocketDirectionDelay
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from .DistributedPartyActivity import DistributedPartyActivity
|
||||
from .activityFSMs import FireworksActivityFSM
|
||||
from . import PartyGlobals
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from direct.gui.DirectGui import DirectFrame
|
|||
from direct.gui.DirectGui import DirectButton
|
||||
from direct.gui.DirectGui import DirectLabel
|
||||
from direct.gui import DirectGuiGlobals
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
|
||||
# Toontown imports
|
||||
from toontown.toonbase import ToontownGlobals
|
||||
|
|
|
|||
|
|
@ -0,0 +1,166 @@
|
|||
from dataclasses import asdict, dataclass, fields
|
||||
import json
|
||||
from typing import Union, Any
|
||||
from pathlib import Path
|
||||
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
# Valid types for a setting.
|
||||
ControlSetting = dict[str, str]
|
||||
Setting = Union[str, int, bool, list, float, ControlSetting]
|
||||
|
||||
|
||||
@dataclass
|
||||
class ControlSettings:
|
||||
MOVE_UP: str = "arrow_up"
|
||||
MOVE_DOWN: str = "arrow_down"
|
||||
MOVE_LEFT: str = "arrow_left"
|
||||
MOVE_RIGHT: str = "arrow_right"
|
||||
JUMP: str = "control"
|
||||
SPRINT: str = "shift"
|
||||
SCREENSHOT: str = "f9"
|
||||
TOGGLE_RUN_HOTKEY: str = "f8"
|
||||
MAP_PAGE_HOTKEY: str = "escape"
|
||||
FRIENDS_LIST_HOTKEY: str = "f7"
|
||||
STREET_MAP_HOTKEY: str = "alt"
|
||||
INVENTORY_HOTKEY: str = "home"
|
||||
QUEST_HOTKEY: str = "end"
|
||||
GALLERY_HOTKEY: str = "g"
|
||||
LOCATIONS_HOTKEY: str = "v"
|
||||
ELEVATOR_HOTKEY: str = "f"
|
||||
CRANE_GRAB_KEY: str = "control"
|
||||
ACTION_BUTTON: str = "delete"
|
||||
SECONDARY_ACTION: str = "insert"
|
||||
CHAT_HOTKEY: str = "t"
|
||||
|
||||
|
||||
class Settings:
|
||||
# All controls with their respective default values.
|
||||
controls = ControlSettings()
|
||||
|
||||
# All settings with their respective default values.
|
||||
defaultSettings = {
|
||||
"borderless": False,
|
||||
"music": True,
|
||||
"sfx": True,
|
||||
"toon-chat-sounds": True,
|
||||
"resolution": [1280, 720],
|
||||
"music-volume": 0.4,
|
||||
"sfx-volume": 0.4,
|
||||
"competitive-boss-scoring": True,
|
||||
"report-errors": True,
|
||||
"anti-aliasing": 0,
|
||||
"anisotropic-filter": 8,
|
||||
"frame-blending": True,
|
||||
"controls": asdict(controls),
|
||||
"vertical-sync": True,
|
||||
"frame-rate-meter": False,
|
||||
"fovEffects": True,
|
||||
"cam-toggle-lock": False,
|
||||
"movement_mode": "TTCC",
|
||||
"sprint_mode": "Hold",
|
||||
"magic-word-activator": 0,
|
||||
"camSensitivityX": 0.25,
|
||||
"camSensitivityY": 0.1,
|
||||
"fps-limit": 0,
|
||||
'laff-display': True,
|
||||
'battle-speed': 2,
|
||||
'random-music': False,
|
||||
'boss-alerts': True,
|
||||
# Lighting / shadows (OutdoorLighting.py)
|
||||
'want-modern-outdoor-lighting': True,
|
||||
'dynamic-shadows': True,
|
||||
'shadow-quality': 'high', # off | low | medium | high
|
||||
'lighting-bloom-enabled': True,
|
||||
'lighting-god-rays': True,
|
||||
'lighting-fog-enabled': True,
|
||||
'lighting-specular-enabled': True,
|
||||
'want-procedural-sky': True,
|
||||
'want-day-night-cycle': False,
|
||||
'want-water-reflections': True,
|
||||
# Drop-shadow (non-shader) fallback controls
|
||||
'drop-shadow-strength': 0.5,
|
||||
# Debug
|
||||
'lighting-debug': False,
|
||||
# Options below this comment will not be exposed by OptionsPage
|
||||
# They can still be configurable by the end user
|
||||
"want-legacy-models": False,
|
||||
"experimental-multithreading": False,
|
||||
'discord-rich-presence': False,
|
||||
"color-blind-mode": False,
|
||||
}
|
||||
settingsFile = Path.home() / "Documents" / "Super CFO" / "settings.json"
|
||||
|
||||
|
||||
def __init__(self) -> None:
|
||||
try:
|
||||
with self.settingsFile.open(encoding='utf-8') as f:
|
||||
self._settings = json.load(f)
|
||||
except FileNotFoundError:
|
||||
self.settingsFile.parent.mkdir(parents=True, exist_ok=True)
|
||||
self._settings = self.defaultSettings.copy()
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
# Backfill any newly-added defaults into existing settings files.
|
||||
# (clean() only removes unknown keys; it does not add missing ones.)
|
||||
for k, v in self.defaultSettings.items():
|
||||
if k not in self._settings:
|
||||
self._settings[k] = v
|
||||
|
||||
# Re-instantiate the ControlSettings with our saved controls.
|
||||
self.updateControls(self.get("controls"))
|
||||
self.write()
|
||||
|
||||
def get(self, setting: str) -> Setting:
|
||||
return self._settings.get(setting, self.defaultSettings.get(setting))
|
||||
|
||||
def getSetting(self, setting: str, default: Any = None) -> Any:
|
||||
if setting == 'windowed-mode':
|
||||
return not self.get('borderless')
|
||||
val = self._settings.get(setting)
|
||||
if val is None:
|
||||
val = self.defaultSettings.get(setting, default)
|
||||
return val
|
||||
|
||||
def readSettings(self) -> None:
|
||||
pass
|
||||
|
||||
def set(self, setting: str, value: Setting) -> None:
|
||||
if not isinstance(value, type(self.defaultSettings.get(setting))):
|
||||
return
|
||||
self._settings[setting] = value
|
||||
|
||||
def setControl(self, control: str, keybind: str) -> None:
|
||||
# First, get the control setting.
|
||||
controls: ControlSetting = self.get("controls")
|
||||
# Replace the keybind at the control.
|
||||
controls[control] = keybind
|
||||
# Update the control settings with our new controls.
|
||||
self.updateControls(controls)
|
||||
|
||||
def getControl(self, control: str) -> str:
|
||||
return self.getControls().get(control, "")
|
||||
|
||||
def getControls(self) -> dict[str, Any]:
|
||||
return asdict(self.controls)
|
||||
|
||||
def updateControls(self, controls: dict[str, str]) -> None:
|
||||
# Ensure that extra controls in our list dont crash (typically for going back to a previous version)
|
||||
valid_args = {f.name: controls[f.name] for f in fields(ControlSettings) if f.name in controls}
|
||||
self.controls = ControlSettings(**valid_args)
|
||||
self.set("controls", asdict(self.controls))
|
||||
|
||||
def write(self) -> None:
|
||||
with self.settingsFile.open("w", encoding='utf-8') as _settings:
|
||||
# Clean the settings dictionary before saving it to the file.
|
||||
self.clean()
|
||||
json.dump(self._settings, _settings, sort_keys=True, indent=4)
|
||||
|
||||
def clean(self) -> None:
|
||||
"""
|
||||
Removes all keys in settings which shouldn't exist.
|
||||
(they don't exist in defaultSettings)
|
||||
"""
|
||||
for setting in list(self._settings):
|
||||
if setting not in self.defaultSettings:
|
||||
del self._settings[setting]
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,118 @@
|
|||
from direct.gui.DirectGui import DirectButton, DirectLabel
|
||||
from panda3d.core import TextNode, Vec4
|
||||
|
||||
Preloaded = {}
|
||||
|
||||
def loadModels():
|
||||
if Preloaded:
|
||||
return
|
||||
gui = loader.loadModel('phase_3.5/models/gui/fishingBook.bam')
|
||||
Preloaded['tab1'] = gui.find('**/tabs/polySurface1')
|
||||
Preloaded['tab2'] = gui.find('**/tabs/polySurface2')
|
||||
gui.removeNode()
|
||||
del gui
|
||||
|
||||
guiButton = loader.loadModel('phase_3/models/gui/quit_button')
|
||||
Preloaded['button1'] = guiButton.find('**/QuitBtn_UP')
|
||||
Preloaded['button2'] = guiButton.find('**/QuitBtn_DN')
|
||||
Preloaded['button3'] = guiButton.find('**/QuitBtn_RLVR')
|
||||
guiButton.removeNode()
|
||||
del guiButton
|
||||
|
||||
normalColor = (1, 1, 1, 1)
|
||||
clickColor = (0.8, 0.8, 0, 1)
|
||||
rolloverColor = (0.15, 0.82, 1.0, 1)
|
||||
diabledColor = (1.0, 0.98, 0.15, 1)
|
||||
|
||||
|
||||
class OptionTab(DirectButton):
|
||||
def __init__(self, tabType=2, parent=None, **kw):
|
||||
loadModels()
|
||||
|
||||
if parent is None:
|
||||
parent = aspect2d
|
||||
|
||||
if tabType == 1:
|
||||
image = Preloaded['tab1']
|
||||
elif tabType == 2:
|
||||
image = Preloaded['tab2']
|
||||
else:
|
||||
image = None
|
||||
|
||||
optiondefs = (
|
||||
('relief', None, None),
|
||||
('text_align', TextNode.ALeft, None),
|
||||
('text_fg', Vec4(0.2, 0.1, 0, 1), None),
|
||||
('image', image, None),
|
||||
('image_color', normalColor, None),
|
||||
('image1_color', clickColor, None),
|
||||
('image2_color', rolloverColor, None),
|
||||
('image3_color', diabledColor, None),
|
||||
('image_scale', (0.033, 0.033, 0.035), None),
|
||||
('image_hpr', (0, 0, -90), None)
|
||||
)
|
||||
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectButton.__init__(self, parent)
|
||||
self.initialiseoptions(OptionTab)
|
||||
|
||||
buttonbase_xcoord = 0.35
|
||||
buttonbase_ycoord = 0.45
|
||||
|
||||
class OptionButton(DirectButton):
|
||||
def __init__(self, parent=None, wantLabel=False, z=buttonbase_ycoord, labelZ=None,
|
||||
labelOrientation='left', labelPos=None, labelText='', image_scale=(0.7, 1, 1), text='', **kw):
|
||||
loadModels()
|
||||
|
||||
if parent is None:
|
||||
parent = aspect2d
|
||||
|
||||
pos = (buttonbase_xcoord, 0, z) if not kw.get('pos') else kw['pos']
|
||||
optiondefs = (
|
||||
('relief', None, None),
|
||||
('image', (Preloaded['button1'], Preloaded['button2'], Preloaded['button3']), None),
|
||||
('image_scale', image_scale, None),
|
||||
('text', text, None),
|
||||
('text_scale', 0.052, None),
|
||||
('text_pos', (0, -0.02), None),
|
||||
('pos', pos, None),
|
||||
)
|
||||
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectButton.__init__(self, parent)
|
||||
self.initialiseoptions(OptionButton)
|
||||
if wantLabel:
|
||||
self.label=OptionLabel(parent=self, z=labelZ, pos=labelPos, orientation=labelOrientation,
|
||||
text=labelText)
|
||||
|
||||
titleHeight = 0.61
|
||||
textStartHeight = 0.45
|
||||
leftMargin = -0.72
|
||||
|
||||
class OptionLabel(DirectLabel):
|
||||
def __init__(self, parent=None, z=textStartHeight, text_wordwrap=16, text='',
|
||||
orientation='left', **kw):
|
||||
loadModels()
|
||||
|
||||
if parent is None:
|
||||
parent = aspect2d
|
||||
|
||||
if orientation == 'left':
|
||||
pos = (leftMargin, 0, z)
|
||||
text_align = TextNode.ALeft
|
||||
else:
|
||||
pos = kw['pos']
|
||||
text_align = TextNode.ACenter
|
||||
|
||||
optiondefs = (
|
||||
('relief', None, None),
|
||||
('pos', pos, None),
|
||||
('text_align', text_align, None),
|
||||
('text_scale', 0.052, None),
|
||||
('text_wordwrap', text_wordwrap, None),
|
||||
('text', text, None)
|
||||
)
|
||||
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectLabel.__init__(self, parent)
|
||||
self.initialiseoptions(OptionLabel)
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
from panda3d.core import *
|
||||
from panda3d.otp import *
|
||||
from libotp import *
|
||||
from toontown.toonbase import ToontownGlobals
|
||||
from direct.showbase import DirectObject
|
||||
from direct.fsm import StateData
|
||||
from direct.gui.DirectGui import *
|
||||
from panda3d.core import *
|
||||
from toontown.toonbase import TTLocalizer
|
||||
from toontown.effects import DistributedFireworkShow
|
||||
from toontown.parties import DistributedPartyFireworksActivity
|
||||
|
|
@ -32,11 +31,11 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
self.hide()
|
||||
self.setPos(0, 0, 0.1)
|
||||
self.pageOrder = [TTLocalizer.OptionsPageTitle,
|
||||
TTLocalizer.ShardPageTitle,
|
||||
TTLocalizer.CheckPageTitle,
|
||||
TTLocalizer.LocationPageTitle,
|
||||
TTLocalizer.MapPageTitle,
|
||||
TTLocalizer.InventoryPageTitle,
|
||||
TTLocalizer.QuestPageToonTasks,
|
||||
TTLocalizer.TrackPageShortTitle,
|
||||
TTLocalizer.SuitPageTitle,
|
||||
TTLocalizer.FishPageTitle,
|
||||
TTLocalizer.KartPageTitle,
|
||||
|
|
@ -45,7 +44,8 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
TTLocalizer.GardenPageTitle,
|
||||
TTLocalizer.GolfPageTitle,
|
||||
TTLocalizer.EventsPageName,
|
||||
TTLocalizer.NewsPageName]
|
||||
TTLocalizer.NewsPageName,
|
||||
TTLocalizer.SpellbookPageTitle]
|
||||
return
|
||||
|
||||
def setSafeMode(self, setting):
|
||||
|
|
@ -61,8 +61,8 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
messenger.send('stickerBookEntered')
|
||||
base.playSfx(self.openSound)
|
||||
base.disableMouse()
|
||||
base.render.hide()
|
||||
base.setBackgroundColor(0.05, 0.15, 0.4)
|
||||
# base.render.hide()
|
||||
# base.setBackgroundColor(0.05, 0.15, 0.4)
|
||||
base.setCellsAvailable([base.rightCells[0]], 0)
|
||||
self.oldMin2dAlpha = NametagGlobals.getMin2dAlpha()
|
||||
self.oldMax2dAlpha = NametagGlobals.getMax2dAlpha()
|
||||
|
|
@ -99,7 +99,7 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
else:
|
||||
base.setBackgroundColor(ToontownGlobals.DefaultBackgroundColor)
|
||||
gsg = base.win.getGsg()
|
||||
if gsg:
|
||||
if gsg and not base.config.GetString('threading-model', ''):
|
||||
base.render.prepareScene(gsg)
|
||||
NametagGlobals.setMin2dAlpha(self.oldMin2dAlpha)
|
||||
NametagGlobals.setMax2dAlpha(self.oldMax2dAlpha)
|
||||
|
|
@ -112,8 +112,8 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
self.ignore('shtiker-page-done')
|
||||
self.ignore(ToontownGlobals.StickerBookHotkey)
|
||||
self.ignore(ToontownGlobals.OptionsPageHotkey)
|
||||
self.ignore('arrow_right')
|
||||
self.ignore('arrow_left')
|
||||
self.ignore(ToontownGlobals.StickerBookPageLeft)
|
||||
self.ignore(ToontownGlobals.StickerBookPageRight)
|
||||
if base.config.GetBool('want-qa-regression', 0):
|
||||
self.notify.info('QA-REGRESSION: SHTICKERBOOK: Close')
|
||||
|
||||
|
|
@ -123,11 +123,8 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
self['image'] = bookModel.find('**/big_book')
|
||||
self['image_scale'] = (2, 1, 1.5)
|
||||
self.resetFrameSize()
|
||||
# Widescreen support - maintain distance from right edge
|
||||
baseXPos = 1.175
|
||||
adjustedXPos = base.getWidescreenXOffset(baseXPos, 'right') if hasattr(base, 'getWidescreenXOffset') else baseXPos
|
||||
self.bookOpenButton = DirectButton(image=(bookModel.find('**/BookIcon_CLSD'), bookModel.find('**/BookIcon_OPEN'), bookModel.find('**/BookIcon_RLVR')), relief=None, pos=(adjustedXPos, 0, -0.83), scale=0.305, command=self.__open)
|
||||
self.bookCloseButton = DirectButton(image=(bookModel.find('**/BookIcon_OPEN'), bookModel.find('**/BookIcon_CLSD'), bookModel.find('**/BookIcon_RLVR2')), relief=None, pos=(adjustedXPos, 0, -0.83), scale=0.305, command=self.__close)
|
||||
self.bookOpenButton = DirectButton(image=(bookModel.find('**/BookIcon_CLSD'), bookModel.find('**/BookIcon_OPEN'), bookModel.find('**/BookIcon_RLVR')), relief=None, pos=(-0.158, 0, 0.17), parent=base.a2dBottomRight, scale=0.305, command=self.__open)
|
||||
self.bookCloseButton = DirectButton(image=(bookModel.find('**/BookIcon_OPEN'), bookModel.find('**/BookIcon_CLSD'), bookModel.find('**/BookIcon_RLVR2')), relief=None, pos=(-0.158, 0, 0.17), parent=base.a2dBottomRight, scale=0.305, command=self.__close)
|
||||
self.bookOpenButton.hide()
|
||||
self.bookCloseButton.hide()
|
||||
self.nextArrow = DirectButton(parent=self, relief=None, image=(bookModel.find('**/arrow_button'), bookModel.find('**/arrow_down'), bookModel.find('**/arrow_rollover')), scale=(0.1, 0.1, 0.1), pos=(0.838, 0, -0.661), command=self.__pageChange, extraArgs=[1])
|
||||
|
|
@ -210,12 +207,21 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
extraArgs = []
|
||||
if pageName == TTLocalizer.OptionsPageTitle:
|
||||
iconModels = loader.loadModel('phase_3.5/models/gui/sos_textures')
|
||||
iconGeom = iconModels.find('**/switch')
|
||||
iconGeom = iconModels.find('**/switch1')
|
||||
iconModels.detachNode()
|
||||
elif pageName == TTLocalizer.ShardPageTitle:
|
||||
iconModels = loader.loadModel('phase_3.5/models/gui/sos_textures')
|
||||
iconGeom = iconModels.find('**/district')
|
||||
iconModels.detachNode()
|
||||
elif pageName == TTLocalizer.CheckPageTitle:
|
||||
iconModels = loader.loadModel('phase_4/models/parties/schtickerbookHostingGUI')
|
||||
iconGeom = iconModels.find('**/checkmark')
|
||||
iconScale = 25
|
||||
iconModels.detachNode()
|
||||
elif pageName == TTLocalizer.LocationPageTitle:
|
||||
iconModels = loader.loadModel('phase_3.5/models/gui/sos_textures')
|
||||
iconGeom = iconModels.find('**/district')
|
||||
iconModels.detachNode()
|
||||
elif pageName == TTLocalizer.MapPageTitle:
|
||||
iconModels = loader.loadModel('phase_3.5/models/gui/sos_textures')
|
||||
iconGeom = iconModels.find('**/teleportIcon')
|
||||
|
|
@ -256,6 +262,11 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
iconModels = loader.loadModel('phase_3.5/models/gui/playingCard')
|
||||
iconImage = iconModels.find('**/card_back')
|
||||
iconGeom = iconModels.find('**/logo')
|
||||
iconGeom.setState(RenderState.makeEmpty())
|
||||
cardTex = loader.loadTexture('phase_3/maps/toontown-logo.png')
|
||||
cardTex.setMinfilter(Texture.FTLinearMipmapLinear)
|
||||
cardTex.setMagfilter(Texture.FTLinear)
|
||||
iconGeom.setTexture(cardTex, 1)
|
||||
iconScale = 0.22
|
||||
iconModels.detachNode()
|
||||
elif pageName == TTLocalizer.KartPageTitle:
|
||||
|
|
@ -276,6 +287,10 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
iconModels.detachNode()
|
||||
buttonPressedCommand = self.goToNewsPage
|
||||
extraArgs = [page]
|
||||
elif pageName == TTLocalizer.SpellbookPageTitle:
|
||||
iconModels = loader.loadModel('phase_3.5/models/gui/sos_textures')
|
||||
iconGeom = iconModels.find('**/spellbookIcon')
|
||||
iconModels.detachNode()
|
||||
if pageName == TTLocalizer.OptionsPageTitle:
|
||||
pageName = TTLocalizer.OptionsTabTitle
|
||||
pageTab = DirectButton(parent=self.pageTabFrame, relief=DGG.RAISED, frameSize=(-0.575,
|
||||
|
|
@ -415,16 +430,20 @@ class ShtikerBook(DirectFrame, StateData.StateData):
|
|||
self.prevArrow.hide()
|
||||
self.nextArrow.show()
|
||||
|
||||
def hidePageArrows(self):
|
||||
self.prevArrow.hide()
|
||||
self.nextArrow.hide()
|
||||
|
||||
def __checkForNewsPage(self):
|
||||
from toontown.shtiker import NewsPage
|
||||
self.ignore('arrow_left')
|
||||
self.ignore('arrow_right')
|
||||
self.ignore(ToontownGlobals.StickerBookPageLeft)
|
||||
self.ignore(ToontownGlobals.StickerBookPageRight)
|
||||
if isinstance(self.pages[self.currPageIndex], NewsPage.NewsPage):
|
||||
self.ignore('arrow_left')
|
||||
self.ignore('arrow_right')
|
||||
self.ignore(ToontownGlobals.StickerBookPageLeft)
|
||||
self.ignore(ToontownGlobals.StickerBookPageRight)
|
||||
else:
|
||||
self.accept('arrow_right', self.__pageChange, [1])
|
||||
self.accept('arrow_left', self.__pageChange, [-1])
|
||||
self.accept(ToontownGlobals.StickerBookPageRight, self.__pageChange, [1])
|
||||
self.accept(ToontownGlobals.StickerBookPageLeft, self.__pageChange, [-1])
|
||||
|
||||
def goToNewsPage(self, page):
|
||||
messenger.send('wakeup')
|
||||
|
|
|
|||
|
|
@ -9791,3 +9791,111 @@ InteractivePropTrackBonusTerms = {0: 'Super Toon-Up!',
|
|||
5: 'Super Squirt!',
|
||||
6: ''}
|
||||
PlayingCardUnknown = 'Card Name is unknown'
|
||||
|
||||
OptionsPageTabs = {
|
||||
0: "Gameplay",
|
||||
1: "Privacy",
|
||||
2: "Controls",
|
||||
3: "Video",
|
||||
4: "Audio",
|
||||
}
|
||||
|
||||
OptionNames = {
|
||||
"camSensitivityX": "Camera X Sensitivity",
|
||||
"camSensitivityY": "Camera Y Sensitivity",
|
||||
"movement_mode": "Movement Mode",
|
||||
"sprint_mode": "Sprint Mode",
|
||||
"fovEffects": "Sprinting FOV Effects",
|
||||
"cam-toggle-lock": "Camera Toggle Lock",
|
||||
"speedchat-style": "Speedchat Color",
|
||||
'discord-rich-presence': 'Discord Rich Presence',
|
||||
'boss-alerts': "Cog Boss Attack Alerts",
|
||||
"color-blind-mode": "Colorblind Mode",
|
||||
"want-legacy-models": "Toggle TTO Species Models*",
|
||||
'laff-display': "Toggle Overhead Laff Meter",
|
||||
'battle-speed': "Battle Speed Multiplier",
|
||||
"competitive-boss-scoring": "Want Competitive Boss Scoring",
|
||||
"report-errors": "Report Crash Logs",
|
||||
"JUMP": "Jump",
|
||||
"MOVE_UP": "Move Up",
|
||||
"MOVE_DOWN": "Move Down",
|
||||
"MOVE_LEFT": "Move Left",
|
||||
"MOVE_RIGHT": "Move Right",
|
||||
"SPRINT": "Sprint",
|
||||
"SCREENSHOT": "Screenshot",
|
||||
"MAP_PAGE_HOTKEY": "Map Page Hotkey",
|
||||
"FRIENDS_LIST_HOTKEY": "Friends List Hotkey",
|
||||
"TOGGLE_RUN_HOTKEY": "Toggle Debug Run Speed",
|
||||
"STREET_MAP_HOTKEY": "Street Map Hotkey",
|
||||
"INVENTORY_HOTKEY": "Gag Menu Hotkey",
|
||||
"QUEST_HOTKEY": "ToonTask Hotkey",
|
||||
"GALLERY_HOTKEY": "Cog Gallery Hotkey",
|
||||
"LOCATIONS_HOTKEY": "Location Tracker Hotkey",
|
||||
"ELEVATOR_HOTKEY": "Skip Elevator Timer Hotkey",
|
||||
"CRANE_GRAB_KEY": "Crane Grab Key",
|
||||
"ACTION_BUTTON": "Action Button",
|
||||
"SECONDARY_ACTION": "Secondary Action Button",
|
||||
"CHAT_HOTKEY": "Chat Button",
|
||||
"borderless": "Borderless Window",
|
||||
"resolution": "Window Resolution",
|
||||
"vertical-sync": "Vertical Sync",
|
||||
"anisotropic-filter": "Anisotropic Filtering",
|
||||
"anti-aliasing": "Anti-Aliasing*",
|
||||
"frame-rate-meter": "FPS Meter",
|
||||
"fps-limit": "FPS Limit",
|
||||
"want-modern-outdoor-lighting": "Modern Outdoor Lighting",
|
||||
"dynamic-shadows": "Dynamic Shadows",
|
||||
"shadow-quality": "Shadow Quality",
|
||||
"lighting-bloom-enabled": "Bloom",
|
||||
"lighting-god-rays": "God Rays",
|
||||
"want-procedural-sky": "Procedural Sky",
|
||||
"want-day-night-cycle": "Day/Night Cycle",
|
||||
"want-water-reflections": "Water Reflections",
|
||||
"drop-shadow-strength": "Drop Shadow Strength",
|
||||
"music": "Music",
|
||||
"sfx": "Sound Effects",
|
||||
"music-volume": "Music Volume",
|
||||
"sfx-volume": "Sound Effects Volume",
|
||||
"toon-chat-sounds": "Toon Chat Sounds",
|
||||
"random-music": "Randomize Music",
|
||||
'ap-sounds': "AP Item Sounds",
|
||||
'refresh-audio': "Refresh Audio",
|
||||
}
|
||||
|
||||
OptionAntiAlias = {
|
||||
0: "Off",
|
||||
4: "4x MSAA",
|
||||
8: "8x MSAA",
|
||||
}
|
||||
|
||||
OptionBattleSpeed = {
|
||||
1: "1x Speed",
|
||||
2: "2x Speed",
|
||||
3: "3x Speed",
|
||||
4: "4x Speed",
|
||||
5: "5x Speed"
|
||||
}
|
||||
|
||||
OptionAnisotropic = {
|
||||
0: "Off",
|
||||
2: "Lowest",
|
||||
4: "Low",
|
||||
8: "High",
|
||||
16: "Highest",
|
||||
}
|
||||
OptionFPSLimit = {
|
||||
0: "Unlimited",
|
||||
30: "30 FPS",
|
||||
60: "60 FPS",
|
||||
120: "120 FPS",
|
||||
144: "144 FPS",
|
||||
165: "165 FPS",
|
||||
240: "240 FPS",
|
||||
360: "360 FPS"
|
||||
}
|
||||
|
||||
OptionEnabled = "Enabled"
|
||||
OptionDisabled = "Disabled"
|
||||
OptionRefresh = "Refresh"
|
||||
WinConditionMet = 'Congratulations, you have completed your goal! You may now talk to Flippy to redeem your reward!'
|
||||
RefreshDialogMsg = "Refreshing audio devices..."
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from otp.otpbase import OTPBase
|
||||
from otp.otpbase import OTPLauncherGlobals
|
||||
from otp.otpbase import OTPGlobals
|
||||
from otp.settings.Settings import Settings
|
||||
from toontown.settings.Settings import Settings
|
||||
from direct.showbase.PythonUtil import *
|
||||
from . import ToontownGlobals
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
from direct.gui.DirectGui import DirectFrame, DGG, DirectScrollBar
|
||||
from panda3d.core import NodePath, PGScrollFrame
|
||||
|
||||
|
||||
class ToontownScrolledFrame(DirectFrame):
|
||||
|
||||
def __init__(self, parent=None, **kw):
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, (
|
||||
('scrollDistance', 0.2, None),
|
||||
('scrollCondition', True, None),
|
||||
('pgFunc', PGScrollFrame, None),
|
||||
('frameSize', (-0.5, 0.5, -0.5, 0.5), None),
|
||||
('canvasSize', (-1, 1, -1, 1), self.setCanvasSize),
|
||||
('manageScrollBars', 1, self.setManageScrollBars),
|
||||
('autoHideScrollBars', 1, self.setAutoHideScrollBars),
|
||||
('scrollBarWidth', 0.08, self.setScrollBarWidth),
|
||||
('borderWidth', (0.01, 0.01), self.setBorderWidth),
|
||||
))
|
||||
super().__init__(parent, **kw)
|
||||
|
||||
w = self['scrollBarWidth']
|
||||
|
||||
self.verticalScroll = self.createcomponent(
|
||||
"verticalScroll", (), None,
|
||||
DirectScrollBar, (self,),
|
||||
borderWidth=self['borderWidth'],
|
||||
frameSize=(-w / 2.0, w / 2.0, -1, 1),
|
||||
orientation=DGG.VERTICAL
|
||||
)
|
||||
|
||||
self.guiItem.setVerticalSlider(self.verticalScroll.guiItem)
|
||||
|
||||
self.canvas = NodePath(self.guiItem.getCanvasNode())
|
||||
|
||||
# Call option initialization functions
|
||||
self.initialiseoptions(ToontownScrolledFrame)
|
||||
|
||||
# Bind the scroll wheel.
|
||||
self['state'] = DGG.NORMAL
|
||||
self.bindToScroll(self)
|
||||
self.bindToScroll(self.verticalScroll)
|
||||
self.bindToScroll(self.verticalScroll.thumb)
|
||||
self.bindToScroll(self.verticalScroll.incButton)
|
||||
self.bindToScroll(self.verticalScroll.decButton)
|
||||
|
||||
def scroll(self, direction):
|
||||
if bool(self['scrollCondition']) or (callable(self['scrollCondition']) and bool(self['scrollCondition']())):
|
||||
scrollPercent = self['scrollDistance'] / abs(self['canvasSize'][2] - self['canvasSize'][3])
|
||||
self['verticalScroll_value'] = self['verticalScroll_value'] + scrollPercent * direction
|
||||
|
||||
def bindToScroll(self, gui):
|
||||
gui.bind(DGG.WHEELUP, lambda _: self.scroll(-1))
|
||||
gui.bind(DGG.WHEELDOWN, lambda _: self.scroll(1))
|
||||
|
||||
def setScrollBarWidth(self):
|
||||
if self.fInit:
|
||||
return
|
||||
|
||||
w = self['scrollBarWidth']
|
||||
self.verticalScroll["frameSize"] = (
|
||||
-w / 2.0, w / 2.0, self.verticalScroll["frameSize"][2], self.verticalScroll["frameSize"][3])
|
||||
|
||||
def setCanvasSize(self):
|
||||
f = self['canvasSize']
|
||||
self.guiItem.setVirtualFrame(f[0], f[1], f[2], f[3])
|
||||
|
||||
def getCanvas(self):
|
||||
return self.canvas
|
||||
|
||||
def setManageScrollBars(self):
|
||||
self.guiItem.setManagePieces(self['manageScrollBars'])
|
||||
|
||||
def setAutoHideScrollBars(self):
|
||||
self.guiItem.setAutoHide(self['autoHideScrollBars'])
|
||||
|
||||
def commandFunc(self):
|
||||
if self['command']:
|
||||
self['command'](*self['extraArgs'])
|
||||
|
||||
def destroy(self):
|
||||
# Destroy children of the canvas
|
||||
for child in self.canvas.getChildren():
|
||||
childGui = self.guiDict.get(child.getName())
|
||||
if childGui:
|
||||
childGui.destroy()
|
||||
else:
|
||||
parts = child.getName().split('-')
|
||||
simpleChildGui = self.guiDict.get(parts[-1])
|
||||
if simpleChildGui:
|
||||
simpleChildGui.destroy()
|
||||
|
||||
if self.verticalScroll:
|
||||
self.verticalScroll.destroy()
|
||||
|
||||
self.verticalScroll = None
|
||||
|
||||
super().destroy()
|
||||
Loading…
Reference in New Issue