add: right-click of changing skin for desktop pet (#99)
* fix: skin icon size * fix: skin icon size * fix: skin icon size * fix: skin icon size * fix: skin icon size * fix: skin icon size * add: right click logic of changing skin
This commit is contained in:
@@ -308,6 +308,7 @@ if sys.platform == 'darwin':
|
|||||||
|
|
||||||
# Load skin
|
# Load skin
|
||||||
self.load_skin(skin_name)
|
self.load_skin(skin_name)
|
||||||
|
self.available_skins = SkinLoader.list_skins()
|
||||||
|
|
||||||
# Get screen size
|
# Get screen size
|
||||||
from AppKit import NSScreen, NSWindowCollectionBehaviorCanJoinAllSpaces, NSWindowCollectionBehaviorStationary
|
from AppKit import NSScreen, NSWindowCollectionBehaviorCanJoinAllSpaces, NSWindowCollectionBehaviorStationary
|
||||||
@@ -393,6 +394,29 @@ if sys.platform == 'darwin':
|
|||||||
"""Accept first mouse click"""
|
"""Accept first mouse click"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def rightMouseDown_(self, event):
|
||||||
|
from AppKit import NSMenu, NSMenuItem, NSApp
|
||||||
|
|
||||||
|
menu = NSMenu.alloc().init()
|
||||||
|
pet = self.window().delegate() # Assuming the window’s delegate is MacPet instance
|
||||||
|
|
||||||
|
for skin_name in pet.available_skins: # preload this in MacPet.__init__
|
||||||
|
item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
skin_name,
|
||||||
|
'changeSkin:',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
item.setTarget_(pet)
|
||||||
|
item.setRepresentedObject_(skin_name)
|
||||||
|
menu.addItem_(item)
|
||||||
|
|
||||||
|
menu.addItem_(NSMenuItem.separatorItem())
|
||||||
|
quit_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Quit', 'terminate:', '')
|
||||||
|
menu.addItem_(quit_item)
|
||||||
|
|
||||||
|
NSApp.activateIgnoringOtherApps_(True)
|
||||||
|
NSMenu.popUpContextMenu_withEvent_forView_(menu, event, self)
|
||||||
|
|
||||||
# Create draggable view
|
# Create draggable view
|
||||||
self.content_view = DraggableImageView.alloc().initWithFrame_(
|
self.content_view = DraggableImageView.alloc().initWithFrame_(
|
||||||
NSMakeRect(0, 0, self.display_width, self.display_height)
|
NSMakeRect(0, 0, self.display_width, self.display_height)
|
||||||
@@ -576,6 +600,13 @@ if sys.platform == 'darwin':
|
|||||||
def run(self):
|
def run(self):
|
||||||
"""Run the application"""
|
"""Run the application"""
|
||||||
AppHelper.runEventLoop()
|
AppHelper.runEventLoop()
|
||||||
|
|
||||||
|
def changeSkin_(self, sender):
|
||||||
|
skin_name = sender.representedObject()
|
||||||
|
print(f"Changing skin to: {skin_name}")
|
||||||
|
self.load_skin(skin_name)
|
||||||
|
self.current_state = 'idle'
|
||||||
|
self.frame_idx = 0
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Windows Implementation - tkinter with transparentcolor
|
# Windows Implementation - tkinter with transparentcolor
|
||||||
@@ -615,6 +646,7 @@ else:
|
|||||||
self.label.bind('<Button-1>', lambda e: setattr(self, '_d', (e.x, e.y)))
|
self.label.bind('<Button-1>', lambda e: setattr(self, '_d', (e.x, e.y)))
|
||||||
self.label.bind('<B1-Motion>', self._drag)
|
self.label.bind('<B1-Motion>', self._drag)
|
||||||
self.label.bind('<Double-1>', lambda e: (self.root.destroy(), os._exit(0)))
|
self.label.bind('<Double-1>', lambda e: (self.root.destroy(), os._exit(0)))
|
||||||
|
self.label.bind('<Button-3>', self._on_right_click)
|
||||||
|
|
||||||
# Animation state
|
# Animation state
|
||||||
self.current_state = 'idle'
|
self.current_state = 'idle'
|
||||||
@@ -754,6 +786,24 @@ else:
|
|||||||
def run(self):
|
def run(self):
|
||||||
"""Run the application (already in mainloop)"""
|
"""Run the application (already in mainloop)"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _on_right_click(self, event):
|
||||||
|
# Build a dynamic menu of all available skins
|
||||||
|
menu = tk.Menu(self.root, tearoff=0)
|
||||||
|
for skin_name in SkinLoader.list_skins():
|
||||||
|
menu.add_command(
|
||||||
|
label=skin_name,
|
||||||
|
command=lambda name=skin_name: self._change_skin(name)
|
||||||
|
)
|
||||||
|
menu.add_separator()
|
||||||
|
menu.add_command(label="Quit", command=lambda: (self.root.destroy(), os._exit(0)))
|
||||||
|
menu.tk_popup(event.x_root, event.y_root)
|
||||||
|
|
||||||
|
def _change_skin(self, skin_name):
|
||||||
|
print(f"Changing skin to: {skin_name}")
|
||||||
|
self.load_skin(skin_name)
|
||||||
|
self.current_state = 'idle'
|
||||||
|
self.frame_idx = 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Singleton: if port already in use, another instance is running
|
# Singleton: if port already in use, another instance is running
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
"style": "pixel",
|
"style": "pixel",
|
||||||
"format": "sprite",
|
"format": "sprite",
|
||||||
"size": {
|
"size": {
|
||||||
"width": 40,
|
"width": 80,
|
||||||
"height": 61
|
"height": 122
|
||||||
},
|
},
|
||||||
"animations": {
|
"animations": {
|
||||||
"idle": {
|
"idle": {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"description": "像素风小恐龙 Dinosaur",
|
"description": "像素风小恐龙 Dinosaur",
|
||||||
"style": "pixel",
|
"style": "pixel",
|
||||||
"format": "sprite",
|
"format": "sprite",
|
||||||
"size": { "width": 64, "height": 64 },
|
"size": { "width": 128, "height": 128 },
|
||||||
"animations": {
|
"animations": {
|
||||||
"idle": {
|
"idle": {
|
||||||
"file": "skin.png",
|
"file": "skin.png",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"description": "像素风小恐龙 Doux",
|
"description": "像素风小恐龙 Doux",
|
||||||
"style": "pixel",
|
"style": "pixel",
|
||||||
"format": "sprite",
|
"format": "sprite",
|
||||||
"size": { "width": 48, "height": 48 },
|
"size": { "width": 128, "height": 128 },
|
||||||
"animations": {
|
"animations": {
|
||||||
"idle": {
|
"idle": {
|
||||||
"file": "skin.png",
|
"file": "skin.png",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"description": "Line 角色皮肤",
|
"description": "Line 角色皮肤",
|
||||||
"style": "pixel",
|
"style": "pixel",
|
||||||
"format": "sprite",
|
"format": "sprite",
|
||||||
"size": { "width": 39, "height": 46 },
|
"size": { "width": 128, "height": 128 },
|
||||||
"animations": {
|
"animations": {
|
||||||
"idle": {
|
"idle": {
|
||||||
"file": "skin.png",
|
"file": "skin.png",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"description": "像素风小恐龙 Mort",
|
"description": "像素风小恐龙 Mort",
|
||||||
"style": "pixel",
|
"style": "pixel",
|
||||||
"format": "sprite",
|
"format": "sprite",
|
||||||
"size": { "width": 48, "height": 48 },
|
"size": { "width": 128, "height": 128 },
|
||||||
"animations": {
|
"animations": {
|
||||||
"idle": {
|
"idle": {
|
||||||
"file": "skin.png",
|
"file": "skin.png",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"description": "像素风小恐龙 Tard",
|
"description": "像素风小恐龙 Tard",
|
||||||
"style": "pixel",
|
"style": "pixel",
|
||||||
"format": "sprite",
|
"format": "sprite",
|
||||||
"size": { "width": 48, "height": 48 },
|
"size": { "width": 128, "height": 128 },
|
||||||
"animations": {
|
"animations": {
|
||||||
"idle": {
|
"idle": {
|
||||||
"file": "skin.png",
|
"file": "skin.png",
|
||||||
|
|||||||
Reference in New Issue
Block a user