Leenkx Theme
This commit is contained in:
240
leenkx/blender/theme/theme.py
Normal file
240
leenkx/blender/theme/theme.py
Normal file
@ -0,0 +1,240 @@
|
||||
import os
|
||||
import traceback
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
|
||||
preview_collection = None
|
||||
logo_icon_id = 0
|
||||
splash_icon_id = 0
|
||||
original_splash_cls = None
|
||||
|
||||
|
||||
def load_icons():
|
||||
global preview_collection, logo_icon_id, splash_icon_id
|
||||
if preview_collection is not None:
|
||||
return
|
||||
preview_collection = bpy.utils.previews.new()
|
||||
theme_dir = os.path.dirname(__file__)
|
||||
logo_path = os.path.join(theme_dir, "LeenkxLogo.png")
|
||||
splash_path = os.path.join(theme_dir, "splash.png")
|
||||
if os.path.exists(logo_path):
|
||||
preview_collection.load("logo", logo_path, 'IMAGE', force_reload=True)
|
||||
logo_icon_id = preview_collection["logo"].icon_id
|
||||
else:
|
||||
print("Leenkx theme: logo not found at", logo_path)
|
||||
if os.path.exists(splash_path):
|
||||
preview_collection.load("splash", splash_path, 'IMAGE', force_reload=True)
|
||||
splash_icon_id = preview_collection["splash"].icon_id
|
||||
else:
|
||||
print("Leenkx theme: splash not found at", splash_path)
|
||||
|
||||
|
||||
def install_theme(sdk_path: str):
|
||||
theme_xml = os.path.join(sdk_path, "leenkx", "blender",
|
||||
"theme", "BlenderLeenkxTheme.xml")
|
||||
if not os.path.exists(theme_xml):
|
||||
print("Leenkx theme: theme XML not found at", theme_xml)
|
||||
return
|
||||
|
||||
bpy.ops.preferences.theme_install(
|
||||
filepath=theme_xml, overwrite=True)
|
||||
|
||||
|
||||
def setup_splash(sdk_path: str):
|
||||
splash_png = os.path.join(sdk_path, "leenkx", "blender",
|
||||
"theme", "splash.png")
|
||||
if os.path.exists(splash_png):
|
||||
os.environ["BLENDER_CUSTOM_SPLASH"] = splash_png
|
||||
else:
|
||||
print("Leenkx splash: splash.png not found at", splash_png)
|
||||
|
||||
|
||||
class LEENKX_MT_splash(Menu):
|
||||
bl_label = "Splash"
|
||||
bl_idname = "WM_MT_splash"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'EXEC_DEFAULT'
|
||||
layout.emboss = 'PULLDOWN_MENU'
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col1 = split.column()
|
||||
col1.label(text="New File")
|
||||
|
||||
bpy.types.TOPBAR_MT_file_new.draw_ex(col1, context, use_splash=True)
|
||||
|
||||
col2 = split.column()
|
||||
col2_title = col2.row()
|
||||
|
||||
found_recent = col2.template_recent_files(rows=5)
|
||||
|
||||
if found_recent:
|
||||
col2_title.label(text="Recent Files")
|
||||
|
||||
col_more = col2.column()
|
||||
col_more.operator_context = 'INVOKE_DEFAULT'
|
||||
more_props = col_more.operator("wm.search_single_menu", text="More...", icon='VIEWZOOM')
|
||||
more_props.menu_idname = "TOPBAR_MT_file_open_recent"
|
||||
else:
|
||||
col2_title.label(text="Getting Started")
|
||||
|
||||
col2.operator("wm.url_open", text="Leenkx Docs",
|
||||
icon='URL').url = "https://leenkx.com/docs"
|
||||
col2.operator("wm.url_open", text="Support",
|
||||
icon='URL').url = "https://leenkx.com/support"
|
||||
col2.operator("wm.url_open", text="Community",
|
||||
icon='URL').url = "https://leenkx.com/community"
|
||||
col2.operator("wm.url_open", text="GitHub",
|
||||
icon='URL').url = "https://github.com/leenkx/leenkx"
|
||||
|
||||
col_sep = layout.column()
|
||||
col_sep.separator()
|
||||
col_sep.separator(type='LINE')
|
||||
col_sep.separator()
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col1 = split.column()
|
||||
sub = col1.row()
|
||||
sub.operator_context = 'INVOKE_DEFAULT'
|
||||
sub.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
|
||||
col1.operator("wm.recover_last_session", icon='RECOVER_LAST')
|
||||
|
||||
col2 = split.column()
|
||||
|
||||
col2.operator("wm.url_open", text="Support Leenkx",
|
||||
icon='FUND').url = "https://leenkx.com/donate"
|
||||
col2.operator("wm.url_open", text="Leenkx Website",
|
||||
icon='URL').url = "https://leenkx.com"
|
||||
|
||||
layout.separator()
|
||||
|
||||
if (not bpy.app.online_access) and bpy.app.online_access_override:
|
||||
self.layout.label(text="Running in Offline Mode", icon='INTERNET_OFFLINE')
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
def register_splash_menu():
|
||||
global original_splash_cls
|
||||
cls = getattr(bpy.types, "WM_MT_splash", None)
|
||||
if cls is not None and cls is not LEENKX_MT_splash:
|
||||
original_splash_cls = cls
|
||||
bpy.utils.unregister_class(cls)
|
||||
bpy.utils.register_class(LEENKX_MT_splash)
|
||||
|
||||
|
||||
def unregister_splash_menu():
|
||||
global original_splash_cls
|
||||
bpy.utils.unregister_class(LEENKX_MT_splash)
|
||||
if original_splash_cls is not None:
|
||||
bpy.utils.register_class(original_splash_cls)
|
||||
original_splash_cls = None
|
||||
|
||||
|
||||
saved_draws = {}
|
||||
|
||||
|
||||
def override_draw(bl_idname, new_draw):
|
||||
cls = getattr(bpy.types, bl_idname, None)
|
||||
if cls is None:
|
||||
print("Leenkx menu: class not found", bl_idname)
|
||||
return
|
||||
if bl_idname not in saved_draws:
|
||||
saved_draws[bl_idname] = cls.draw
|
||||
elif cls.draw is new_draw:
|
||||
return
|
||||
cls.draw = new_draw
|
||||
|
||||
|
||||
def restore_draw(bl_idname):
|
||||
cls = getattr(bpy.types, bl_idname, None)
|
||||
if cls is not None and bl_idname in saved_draws:
|
||||
cls.draw = saved_draws[bl_idname]
|
||||
|
||||
def editor_menus_draw(self, context):
|
||||
layout = self.layout
|
||||
if logo_icon_id:
|
||||
layout.menu("TOPBAR_MT_blender", text="", icon_value=logo_icon_id)
|
||||
else:
|
||||
layout.menu("TOPBAR_MT_blender", text="Leenkx")
|
||||
layout.menu("TOPBAR_MT_file")
|
||||
layout.menu("TOPBAR_MT_edit")
|
||||
layout.menu("TOPBAR_MT_render")
|
||||
layout.menu("TOPBAR_MT_window")
|
||||
layout.menu("TOPBAR_MT_help")
|
||||
|
||||
|
||||
def blender_draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.operator("wm.splash", text="Leenkx Splash")
|
||||
layout.separator()
|
||||
layout.operator("preferences.app_template_install",
|
||||
text="Install Application Template...")
|
||||
layout.separator()
|
||||
layout.menu("TOPBAR_MT_blender_system")
|
||||
|
||||
|
||||
def help_draw(self, context):
|
||||
layout = self.layout
|
||||
show_developer = context.preferences.view.show_developer_ui
|
||||
|
||||
layout.operator("wm.url_open", text="Leenkx Docs",
|
||||
icon='URL').url = "https://leenkx.com/api"
|
||||
layout.operator("wm.url_open", text="Leenkx Support",
|
||||
icon='URL').url = "https://leenkx.com/contact"
|
||||
layout.operator("wm.url_open", text="Tutorials",
|
||||
icon='URL').url = "https://leenkx.com/tutorials"
|
||||
layout.operator("wm.url_open", text="Community",
|
||||
icon='URL').url = "https://leenkx.com/community"
|
||||
layout.operator("wm.url_open", text="Support Leenkx (Donate)",
|
||||
icon='FUND').url = "https://leenkx.com/donate"
|
||||
|
||||
layout.separator()
|
||||
|
||||
if show_developer:
|
||||
layout.operator("wm.url_open", text="Developer Docs",
|
||||
icon='URL').url = "https://leenkx.com/wiki"
|
||||
layout.operator("wm.url_open_preset",
|
||||
text="Python API Reference").type = 'API'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("wm.url_open", text="Report a Bug",
|
||||
icon='URL').url = "https://leenkx.com/contact"
|
||||
layout.operator("wm.sysinfo")
|
||||
|
||||
|
||||
def register(sdk_path: str):
|
||||
install_theme(sdk_path)
|
||||
setup_splash(sdk_path)
|
||||
load_icons()
|
||||
register_splash_menu()
|
||||
override_draw("TOPBAR_MT_editor_menus", editor_menus_draw)
|
||||
override_draw("TOPBAR_MT_blender", blender_draw)
|
||||
override_draw("TOPBAR_MT_help", help_draw)
|
||||
|
||||
|
||||
def unregister():
|
||||
restore_draw("TOPBAR_MT_editor_menus")
|
||||
restore_draw("TOPBAR_MT_blender")
|
||||
restore_draw("TOPBAR_MT_help")
|
||||
saved_draws.clear()
|
||||
unregister_splash_menu()
|
||||
|
||||
global preview_collection
|
||||
if preview_collection is not None:
|
||||
bpy.utils.previews.remove(preview_collection)
|
||||
preview_collection = None
|
||||
os.environ.pop("BLENDER_CUSTOM_SPLASH", None)
|
||||
|
||||
window = bpy.context.window_manager.windows[0]
|
||||
if bpy.app.version >= (3, 0, 0):
|
||||
with bpy.context.temp_override(window=window):
|
||||
bpy.ops.preferences.reset_default_theme()
|
||||
else:
|
||||
override = bpy.context.copy()
|
||||
override['window'] = window
|
||||
bpy.ops.preferences.reset_default_theme(override_context=override)
|
||||
Reference in New Issue
Block a user