Fixes
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
schema_version = "1.0.0"
|
schema_version = "1.0.0"
|
||||||
|
|
||||||
id = "avatar_toolkit"
|
id = "avatar_toolkit"
|
||||||
version = "4.3.1"
|
version = "0.1.0"
|
||||||
name = "Avatar Toolkit"
|
name = "Avatar Toolkit"
|
||||||
tagline = "A modern tool for importing and optimizing models for VRChat, Resonite, and other similar games."
|
tagline = "A modern tool for importing and optimizing models for VRChat, Resonite, and other similar games."
|
||||||
maintainer = "Team NekoNeo"
|
maintainer = "Team NekoNeo"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import os
|
import os
|
||||||
|
import toml
|
||||||
import json
|
import json
|
||||||
from bpy.types import AddonPreferences
|
from bpy.types import AddonPreferences
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
@@ -8,6 +9,13 @@ from typing import Any, Dict
|
|||||||
PREFERENCES_DIR = os.path.dirname(os.path.abspath(__file__))
|
PREFERENCES_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
PREFERENCES_FILE = os.path.join(PREFERENCES_DIR, "preferences.json")
|
PREFERENCES_FILE = os.path.join(PREFERENCES_DIR, "preferences.json")
|
||||||
|
|
||||||
|
def get_current_version():
|
||||||
|
main_dir = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
manifest_path = os.path.join(main_dir, "blender_manifest.toml")
|
||||||
|
with open(manifest_path, 'r') as f:
|
||||||
|
manifest_data = toml.load(f)
|
||||||
|
return manifest_data.get('version', 'Unknown')
|
||||||
|
|
||||||
def save_preference(key: str, value: Any) -> None:
|
def save_preference(key: str, value: Any) -> None:
|
||||||
"""Save a single preference to the JSON file."""
|
"""Save a single preference to the JSON file."""
|
||||||
prefs = load_preferences()
|
prefs = load_preferences()
|
||||||
|
|||||||
+87
-9
@@ -9,11 +9,11 @@ import zipfile
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
from ..functions.translations import t
|
from ..functions.translations import t
|
||||||
from .addon_preferences import get_preference
|
from .addon_preferences import get_preference, get_current_version, save_preference
|
||||||
from .register import register_wrap
|
from .register import register_wrap
|
||||||
from ..ui.panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
from ..ui.panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
|
|
||||||
GITHUB_REPO = "teamneoneko/Avatar-Toolkit-rinadev"
|
GITHUB_REPO = "teamneoneko/Avatar-Toolkit"
|
||||||
|
|
||||||
is_checking_for_update = False
|
is_checking_for_update = False
|
||||||
update_needed = False
|
update_needed = False
|
||||||
@@ -46,6 +46,26 @@ class AvatarToolkit_OT_UpdateToLatest(bpy.types.Operator):
|
|||||||
update_now(latest=True)
|
update_now(latest=True)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
@register_wrap
|
||||||
|
class AvatarToolkit_OT_UpdateNotificationPopup(bpy.types.Operator):
|
||||||
|
bl_idname = "avatar_toolkit.update_notification_popup"
|
||||||
|
bl_label = t('UpdateNotificationPopup.label')
|
||||||
|
bl_description = t('UpdateNotificationPopup.desc')
|
||||||
|
bl_options = {'INTERNAL'}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
update_now(latest=True)
|
||||||
|
self.report({'INFO'}, "Update started. Please wait for the process to complete.")
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=300)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.label(text=t('UpdateNotificationPopup.newUpdate', default="New update available: {version}").format(version=latest_version_str))
|
||||||
|
|
||||||
@register_wrap
|
@register_wrap
|
||||||
class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
|
class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
|
||||||
bl_label = t("Updater.label")
|
bl_label = t("Updater.label")
|
||||||
@@ -54,12 +74,39 @@ class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
|
|||||||
bl_region_type = 'UI'
|
bl_region_type = 'UI'
|
||||||
bl_category = CATEGORY_NAME
|
bl_category = CATEGORY_NAME
|
||||||
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
|
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
|
||||||
bl_order = 5
|
bl_order = 9
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
draw_updater_panel(context, layout)
|
draw_updater_panel(context, layout)
|
||||||
|
|
||||||
|
@register_wrap
|
||||||
|
class AvatarToolkit_OT_RestartBlenderPopup(bpy.types.Operator):
|
||||||
|
bl_idname = "avatar_toolkit.restart_blender_popup"
|
||||||
|
bl_label = t('RestartBlenderPopup.label', default="Restart Blender")
|
||||||
|
bl_description = t('RestartBlenderPopup.desc', default="Restart Blender to complete the update")
|
||||||
|
bl_options = {'INTERNAL'}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
return context.window_manager.invoke_props_dialog(self, width=300)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.label(text=t('RestartBlenderPopup.message', default="Update successful! Please restart Blender."))
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def check_for_update_on_start(dummy):
|
||||||
|
if get_preference("check_for_updates_on_startup", True):
|
||||||
|
current_time = time.time()
|
||||||
|
last_check = get_preference("last_update_check", 0)
|
||||||
|
if current_time - last_check > 86400: # 24 hours
|
||||||
|
check_for_update_background()
|
||||||
|
save_preference("last_update_check", current_time)
|
||||||
|
|
||||||
def check_for_update_background():
|
def check_for_update_background():
|
||||||
global is_checking_for_update
|
global is_checking_for_update
|
||||||
if is_checking_for_update:
|
if is_checking_for_update:
|
||||||
@@ -72,17 +119,18 @@ def check_for_update():
|
|||||||
global update_needed, latest_version, latest_version_str, version_list
|
global update_needed, latest_version, latest_version_str, version_list
|
||||||
|
|
||||||
if not get_github_releases():
|
if not get_github_releases():
|
||||||
finish_update_checking(error=t('check_for_update.cantCheck'))
|
bpy.app.timers.register(lambda: finish_update_checking(error=t('check_for_update.cantCheck')))
|
||||||
return
|
return
|
||||||
|
|
||||||
update_needed = check_for_update_available()
|
update_needed = check_for_update_available()
|
||||||
|
|
||||||
if update_needed:
|
if update_needed:
|
||||||
print('Update found!')
|
print('Update found!')
|
||||||
|
bpy.app.timers.register(lambda: bpy.ops.avatar_toolkit.update_notification_popup('INVOKE_DEFAULT') or None)
|
||||||
else:
|
else:
|
||||||
print('No update found.')
|
print('No update found.')
|
||||||
|
|
||||||
finish_update_checking()
|
bpy.app.timers.register(finish_update_checking)
|
||||||
|
|
||||||
def get_github_releases():
|
def get_github_releases():
|
||||||
global version_list
|
global version_list
|
||||||
@@ -114,16 +162,31 @@ def check_for_update_available():
|
|||||||
latest_version = max(version_list.keys(), key=lambda v: [int(x) for x in v.split('.')])
|
latest_version = max(version_list.keys(), key=lambda v: [int(x) for x in v.split('.')])
|
||||||
latest_version_str = latest_version
|
latest_version_str = latest_version
|
||||||
|
|
||||||
current_version = get_preference("version")
|
current_version = get_current_version()
|
||||||
|
print(f"Current version: {current_version}") # Debugging statement
|
||||||
|
|
||||||
|
if current_version is None:
|
||||||
|
print("Current version is None. Cannot check for updates.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Validate that the version string contains only numeric parts
|
||||||
current_version_parts = [int(x) for x in current_version.split('.')]
|
current_version_parts = [int(x) for x in current_version.split('.')]
|
||||||
latest_version_parts = [int(x) for x in latest_version.split('.')]
|
latest_version_parts = [int(x) for x in latest_version.split('.')]
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"Error parsing version numbers: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
return latest_version_parts > current_version_parts
|
return latest_version_parts > current_version_parts
|
||||||
|
|
||||||
|
|
||||||
def finish_update_checking(error=''):
|
def finish_update_checking(error=''):
|
||||||
global is_checking_for_update
|
global is_checking_for_update
|
||||||
is_checking_for_update = False
|
is_checking_for_update = False
|
||||||
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
if update_needed:
|
||||||
|
bpy.ops.avatar_toolkit.update_notification_popup('INVOKE_DEFAULT')
|
||||||
|
ui_refresh()
|
||||||
|
return None # Important for bpy.app.timers
|
||||||
|
|
||||||
def update_now(latest=False):
|
def update_now(latest=False):
|
||||||
if latest:
|
if latest:
|
||||||
@@ -132,6 +195,7 @@ def update_now(latest=False):
|
|||||||
update_link = version_list[bpy.context.scene.avatar_toolkit_updater_version_list][0]
|
update_link = version_list[bpy.context.scene.avatar_toolkit_updater_version_list][0]
|
||||||
|
|
||||||
download_file(update_link)
|
download_file(update_link)
|
||||||
|
ui_refresh()
|
||||||
|
|
||||||
def download_file(update_url):
|
def download_file(update_url):
|
||||||
update_zip_file = os.path.join(downloads_dir, "avatar-toolkit-update.zip")
|
update_zip_file = os.path.join(downloads_dir, "avatar-toolkit-update.zip")
|
||||||
@@ -198,7 +262,9 @@ def finish_update(error=''):
|
|||||||
print(f"Update failed: {error}")
|
print(f"Update failed: {error}")
|
||||||
else:
|
else:
|
||||||
print("Update successful!")
|
print("Update successful!")
|
||||||
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
save_preference("version", latest_version_str)
|
||||||
|
bpy.ops.avatar_toolkit.restart_blender_popup('INVOKE_DEFAULT')
|
||||||
|
ui_refresh()
|
||||||
|
|
||||||
def get_version_list(self, context):
|
def get_version_list(self, context):
|
||||||
return [(v, v, '') for v in version_list.keys()] if version_list else []
|
return [(v, v, '') for v in version_list.keys()] if version_list else []
|
||||||
@@ -219,5 +285,17 @@ def draw_updater_panel(context, layout):
|
|||||||
row.operator(AvatarToolkit_OT_UpdateToLatest.bl_idname, text=t('Updater.UpdateToSelectedButton.label'))
|
row.operator(AvatarToolkit_OT_UpdateToLatest.bl_idname, text=t('Updater.UpdateToSelectedButton.label'))
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
col.label(text=t('Updater.currentVersion').format(name=get_preference("version")))
|
col.label(text=t('Updater.currentVersion').format(name=get_current_version()))
|
||||||
|
|
||||||
|
def ui_refresh():
|
||||||
|
for windowManager in bpy.data.window_managers:
|
||||||
|
for window in windowManager.windows:
|
||||||
|
for area in window.screen.areas:
|
||||||
|
area.tag_redraw()
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.app.handlers.load_post.append(check_for_update_on_start)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
if check_for_update_on_start in bpy.app.handlers.load_post:
|
||||||
|
bpy.app.handlers.load_post.remove(check_for_update_on_start)
|
||||||
|
|||||||
@@ -66,14 +66,14 @@ def load_translations() -> bool:
|
|||||||
|
|
||||||
return dictionary != old_dictionary
|
return dictionary != old_dictionary
|
||||||
|
|
||||||
def t(phrase: str, default: str = None) -> str:
|
def t(phrase: str, default: str = None, **kwargs) -> str:
|
||||||
output: str = dictionary.get(phrase)
|
output: str = dictionary.get(phrase)
|
||||||
if output is None:
|
if output is None:
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f'Warning: Unknown phrase: {phrase}')
|
print(f'Warning: Unknown phrase: {phrase}')
|
||||||
return default if default is not None else phrase
|
return default if default is not None else phrase
|
||||||
# print(f"Translating '{phrase}' to '{output}'") # Debug print
|
# print(f"Translating '{phrase}' to '{output}'") # Debug print
|
||||||
return output
|
return output.format(**kwargs) if kwargs else output
|
||||||
|
|
||||||
def get_language_display_name(lang: str) -> str:
|
def get_language_display_name(lang: str) -> str:
|
||||||
if lang == "auto":
|
if lang == "auto":
|
||||||
|
|||||||
Reference in New Issue
Block a user