deployment
This commit is contained in:
BIN
src/operators/__pycache__/preset_ops.cpython-311.pyc
Normal file
BIN
src/operators/__pycache__/preset_ops.cpython-311.pyc
Normal file
Binary file not shown.
@@ -6,10 +6,11 @@ import json
|
||||
import time
|
||||
|
||||
# Import utility functions from main module
|
||||
from ..presets import (
|
||||
get_preset_path, get_persistent_preset_path, get_addon_version,
|
||||
get_blend_file_presets, save_blend_file_preset, delete_blend_file_preset,
|
||||
refresh_presets_sync, ensure_presets_available
|
||||
from ..presets.storage_system import (
|
||||
save_preset_unified, get_unified_preset_list,
|
||||
get_blend_file_presets, delete_blend_file_preset,
|
||||
refresh_presets_sync, ensure_presets_available,
|
||||
get_preset_path, get_persistent_preset_path
|
||||
)
|
||||
from ..utils import bl_info
|
||||
|
||||
@@ -161,46 +162,11 @@ class TEXT_TEXTURE_OT_save_preset(Operator):
|
||||
preset_data['image_overlays'].append(overlay_data)
|
||||
|
||||
try:
|
||||
# Primary: Save to blend file (new system)
|
||||
print(f"[PRESET SAVE DEBUG] Attempting to save to blend file...")
|
||||
blend_success = save_blend_file_preset(preset_name, preset_data)
|
||||
print(f"[PRESET SAVE DEBUG] Blend file save result: {blend_success}")
|
||||
# Save based on checkbox setting - single destination only
|
||||
success = save_preset_unified(preset_data, preset_name, props.save_with_blend_file)
|
||||
|
||||
# ALWAYS save to persistent storage for cross-blend-file sharing and addon update survival
|
||||
persistent_file = os.path.join(get_persistent_preset_path(), f"{preset_name}.json")
|
||||
print(f"[PRESET SAVE DEBUG] Attempting to save to persistent file: {persistent_file}")
|
||||
persistent_success = True
|
||||
try:
|
||||
with open(persistent_file, 'w') as f:
|
||||
json.dump(preset_data, f, indent=2)
|
||||
print(f"[PRESET SAVE DEBUG] Successfully saved preset '{preset_name}' to persistent storage")
|
||||
|
||||
# VERIFY: Read back the persistent file to confirm shader properties were saved
|
||||
print(f"[PRESET SAVE DEBUG] Verifying persistent file contents...")
|
||||
with open(persistent_file, 'r') as f:
|
||||
saved_data = json.load(f)
|
||||
print(f"[PRESET SAVE DEBUG] Persistent file shader properties verification:")
|
||||
print(f"[PRESET SAVE DEBUG] disable_shadows: {saved_data.get('disable_shadows', 'NOT FOUND')}")
|
||||
print(f"[PRESET SAVE DEBUG] disable_reflections: {saved_data.get('disable_reflections', 'NOT FOUND')}")
|
||||
print(f"[PRESET SAVE DEBUG] disable_backfacing: {saved_data.get('disable_backfacing', 'NOT FOUND')}")
|
||||
|
||||
except Exception as persistent_error:
|
||||
print(f"[PRESET SAVE DEBUG] Warning: Failed to save persistent preset file: {persistent_error}")
|
||||
persistent_success = False
|
||||
|
||||
# Also save to legacy location for backward compatibility (optional)
|
||||
legacy_success = True
|
||||
try:
|
||||
legacy_file = os.path.join(get_preset_path(), f"{preset_name}.json")
|
||||
with open(legacy_file, 'w') as f:
|
||||
json.dump(preset_data, f, indent=2)
|
||||
print(f"[PRESET SAVE DEBUG] Also saved to legacy location for backward compatibility")
|
||||
except Exception as legacy_error:
|
||||
print(f"[PRESET SAVE DEBUG] Note: Could not save to legacy location: {legacy_error}")
|
||||
legacy_success = False
|
||||
|
||||
if not blend_success and not persistent_success:
|
||||
self.report({'ERROR'}, f"Failed to save preset to both blend file and persistent storage")
|
||||
if not success:
|
||||
self.report({'ERROR'}, f"Failed to save preset '{preset_name}'")
|
||||
return {'CANCELLED'}
|
||||
|
||||
# Check if preset already exists in the collection and update it
|
||||
@@ -213,28 +179,18 @@ class TEXT_TEXTURE_OT_save_preset(Operator):
|
||||
if not existing_preset:
|
||||
preset = props.presets.add()
|
||||
preset.name = preset_name
|
||||
# Priority: Blend file > Persistent file
|
||||
preset.source = 'BLEND_FILE' if blend_success else 'PERSISTENT_FILE'
|
||||
preset.source = 'BLEND_FILE' if props.save_with_blend_file else 'PERSISTENT_FILE'
|
||||
else:
|
||||
# Update source based on where it was successfully saved
|
||||
existing_preset.source = 'BLEND_FILE' if blend_success else 'PERSISTENT_FILE'
|
||||
|
||||
# Don't clear the input field - keep the name for easy re-saving
|
||||
# props.new_preset_name = "New Preset"
|
||||
# Update source based on where it was saved
|
||||
existing_preset.source = 'BLEND_FILE' if props.save_with_blend_file else 'PERSISTENT_FILE'
|
||||
|
||||
# Provide clear feedback
|
||||
storage_info = ""
|
||||
if blend_success and persistent_success:
|
||||
storage_info = " (saved to blend file + persistent storage)"
|
||||
elif blend_success:
|
||||
storage_info = " (saved to blend file)"
|
||||
elif persistent_success:
|
||||
storage_info = " (saved to persistent storage)"
|
||||
location = "with .blend file" if props.save_with_blend_file else "to persistent storage"
|
||||
|
||||
if self.overwrite:
|
||||
self.report({'INFO'}, f"✅ Preset '{preset_name}' updated successfully{storage_info}")
|
||||
self.report({'INFO'}, f"✅ Preset '{preset_name}' updated {location}")
|
||||
else:
|
||||
self.report({'INFO'}, f"✅ Preset '{preset_name}' saved successfully{storage_info}")
|
||||
self.report({'INFO'}, f"✅ Preset '{preset_name}' saved {location}")
|
||||
|
||||
except (OSError, IOError, json.JSONEncodeError) as e:
|
||||
self.report({'ERROR'}, f"Failed to save preset: {str(e)}")
|
||||
@@ -301,57 +257,17 @@ class TEXT_TEXTURE_OT_load_preset(Operator):
|
||||
print(f"[PRESET LOAD DEBUG] shader_connection: {props.shader_connection}")
|
||||
|
||||
try:
|
||||
# Three-tier loading priority: Blend File > Persistent File > Legacy File
|
||||
blend_presets = get_blend_file_presets()
|
||||
preset_data = None
|
||||
source = 'BLEND_FILE'
|
||||
# Get unified preset list and find the one to load
|
||||
all_presets = get_unified_preset_list()
|
||||
|
||||
print(f"[PRESET LOAD DEBUG] Available blend file presets: {list(blend_presets.keys())}")
|
||||
|
||||
if self.preset_name in blend_presets:
|
||||
preset_data = blend_presets[self.preset_name]
|
||||
source = 'BLEND_FILE'
|
||||
print(f"[PRESET LOAD DEBUG] Loading preset '{self.preset_name}' from blend file")
|
||||
print(f"[PRESET LOAD DEBUG] Blend file preset shader properties:")
|
||||
print(f"[PRESET LOAD DEBUG] disable_shadows: {preset_data.get('disable_shadows', 'NOT FOUND')}")
|
||||
print(f"[PRESET LOAD DEBUG] disable_reflections: {preset_data.get('disable_reflections', 'NOT FOUND')}")
|
||||
print(f"[PRESET LOAD DEBUG] disable_backfacing: {preset_data.get('disable_backfacing', 'NOT FOUND')}")
|
||||
else:
|
||||
# Try persistent storage next
|
||||
persistent_file = os.path.join(get_persistent_preset_path(), f"{self.preset_name}.json")
|
||||
print(f"[PRESET LOAD DEBUG] Preset not in blend file, trying persistent file: {persistent_file}")
|
||||
if os.path.exists(persistent_file):
|
||||
with open(persistent_file, 'r') as f:
|
||||
preset_data = json.load(f)
|
||||
source = 'PERSISTENT_FILE'
|
||||
print(f"[PRESET LOAD DEBUG] Loading preset '{self.preset_name}' from persistent file")
|
||||
print(f"[PRESET LOAD DEBUG] Persistent file preset shader properties:")
|
||||
print(f"[PRESET LOAD DEBUG] disable_shadows: {preset_data.get('disable_shadows', 'NOT FOUND')}")
|
||||
print(f"[PRESET LOAD DEBUG] disable_reflections: {preset_data.get('disable_reflections', 'NOT FOUND')}")
|
||||
print(f"[PRESET LOAD DEBUG] disable_backfacing: {preset_data.get('disable_backfacing', 'NOT FOUND')}")
|
||||
else:
|
||||
# Fallback to legacy local file
|
||||
legacy_file = os.path.join(get_preset_path(), f"{self.preset_name}.json")
|
||||
print(f"[PRESET LOAD DEBUG] Preset not in persistent storage, trying legacy file: {legacy_file}")
|
||||
if os.path.exists(legacy_file):
|
||||
with open(legacy_file, 'r') as f:
|
||||
preset_data = json.load(f)
|
||||
source = 'LOCAL_FILE'
|
||||
print(f"[PRESET LOAD DEBUG] Loading preset '{self.preset_name}' from legacy file")
|
||||
print(f"[PRESET LOAD DEBUG] Legacy file preset shader properties:")
|
||||
print(f"[PRESET LOAD DEBUG] disable_shadows: {preset_data.get('disable_shadows', 'NOT FOUND')}")
|
||||
print(f"[PRESET LOAD DEBUG] disable_reflections: {preset_data.get('disable_reflections', 'NOT FOUND')}")
|
||||
print(f"[PRESET LOAD DEBUG] disable_backfacing: {preset_data.get('disable_backfacing', 'NOT FOUND')}")
|
||||
else:
|
||||
print(f"[PRESET LOAD DEBUG] Legacy file does not exist: {legacy_file}")
|
||||
self.report({'ERROR'}, f"Preset not found in any storage location: {self.preset_name}")
|
||||
return {'CANCELLED'}
|
||||
|
||||
if not preset_data:
|
||||
print(f"[PRESET LOAD DEBUG] No preset data found!")
|
||||
self.report({'ERROR'}, f"No data found for preset: {self.preset_name}")
|
||||
if self.preset_name not in all_presets:
|
||||
self.report({'ERROR'}, f"Preset '{self.preset_name}' not found")
|
||||
return {'CANCELLED'}
|
||||
|
||||
preset_data, source = all_presets[self.preset_name]
|
||||
|
||||
print(f"[PRESET LOAD DEBUG] Loading preset '{self.preset_name}' from {source}")
|
||||
|
||||
props.is_updating = True
|
||||
|
||||
# Skip loading text to prevent overwriting current text
|
||||
|
||||
BIN
src/presets/__pycache__/storage_system.cpython-311.pyc
Normal file
BIN
src/presets/__pycache__/storage_system.cpython-311.pyc
Normal file
Binary file not shown.
@@ -5,37 +5,31 @@ import time
|
||||
import platform
|
||||
|
||||
# ============================================================================
|
||||
# PRESET STORAGE SYSTEM - V2.0 (PERSISTENT STORAGE)
|
||||
# PRESET STORAGE SYSTEM - V3.0 (SIMPLIFIED TWO-TIER)
|
||||
# ============================================================================
|
||||
#
|
||||
# The Text Texture Generator now uses a THREE-TIER preset storage system
|
||||
# that ensures preset persistence across addon updates:
|
||||
# The Text Texture Generator uses a SIMPLIFIED TWO-TIER preset storage system:
|
||||
#
|
||||
# 1. BLEND FILE STORAGE (Highest Priority)
|
||||
# - Presets travel with the .blend file
|
||||
# - Perfect for project-specific presets
|
||||
# - Stored in scene custom properties
|
||||
#
|
||||
# 2. PERSISTENT FILE STORAGE (Medium Priority)
|
||||
# 1. PERSISTENT FILE STORAGE (Default)
|
||||
# - Survives addon updates and Blender upgrades
|
||||
# - Stored in Blender's user config directory
|
||||
# - Shared across all blend files
|
||||
# - Default behavior when checkbox is unchecked
|
||||
#
|
||||
# 3. LEGACY FILE STORAGE (Lowest Priority)
|
||||
# - Old system for backward compatibility
|
||||
# - Vulnerable to addon updates
|
||||
# - Will be automatically migrated to persistent storage
|
||||
# 2. BLEND FILE STORAGE (Optional)
|
||||
# - Presets travel with the .blend file
|
||||
# - Perfect for project-specific presets
|
||||
# - Stored in scene custom properties
|
||||
# - Used when "Save with .blend file" checkbox is checked
|
||||
#
|
||||
# PRIORITY SYSTEM:
|
||||
# - Blend file presets ALWAYS take priority over persistent ones
|
||||
# - Name conflicts show only the blend file version
|
||||
#
|
||||
# MIGRATION SYSTEM:
|
||||
# - Automatically detects addon version changes
|
||||
# - Migrates legacy presets to persistent storage
|
||||
# - Automatically migrates LOCAL_FILE presets to PERSISTENT_FILE storage
|
||||
# - Creates backups before migration
|
||||
# - Provides detailed migration reports
|
||||
#
|
||||
# IMPORT/EXPORT SYSTEM:
|
||||
# - Export all presets for manual backup
|
||||
# - Import presets with conflict resolution
|
||||
# - Supports cross-machine preset sharing
|
||||
# - One-time process with safety checks
|
||||
#
|
||||
# ============================================================================
|
||||
|
||||
@@ -298,8 +292,157 @@ def delete_blend_file_preset(preset_name):
|
||||
print(f"Error deleting preset from blend file: {e}")
|
||||
return False
|
||||
|
||||
def migrate_from_legacy_system():
|
||||
"""
|
||||
One-time migration from old three-tier system to simplified two-tier system.
|
||||
Moves LOCAL_FILE presets to PERSISTENT_FILE and creates backup.
|
||||
"""
|
||||
try:
|
||||
legacy_dir = get_preset_path()
|
||||
persistent_dir = get_persistent_preset_path()
|
||||
|
||||
# Check if legacy directory exists and is different from persistent
|
||||
if not os.path.exists(legacy_dir) or legacy_dir == persistent_dir:
|
||||
print("[TTG] No separate legacy presets directory found, migration not needed")
|
||||
return True
|
||||
|
||||
# Check for migration marker file to avoid duplicate migrations
|
||||
migration_marker = os.path.join(persistent_dir, ".migration_complete")
|
||||
if os.path.exists(migration_marker):
|
||||
print("[TTG] Migration already completed previously")
|
||||
return True
|
||||
|
||||
# Find legacy preset files
|
||||
legacy_files = []
|
||||
for filename in os.listdir(legacy_dir):
|
||||
if filename.endswith('.json'):
|
||||
legacy_files.append(filename)
|
||||
|
||||
if not legacy_files:
|
||||
print("[TTG] No legacy presets to migrate")
|
||||
# Create marker even if no files to migrate
|
||||
with open(migration_marker, 'w') as f:
|
||||
f.write("Migration completed - no legacy presets found")
|
||||
return True
|
||||
|
||||
print(f"[TTG] Found {len(legacy_files)} legacy presets to migrate")
|
||||
|
||||
# Create backup directory in persistent location
|
||||
backup_dir = os.path.join(persistent_dir, "legacy_backup")
|
||||
os.makedirs(backup_dir, exist_ok=True)
|
||||
|
||||
# Load existing persistent presets to avoid conflicts
|
||||
existing_persistent = set()
|
||||
if os.path.exists(persistent_dir):
|
||||
for filename in os.listdir(persistent_dir):
|
||||
if filename.endswith('.json'):
|
||||
existing_persistent.add(filename)
|
||||
|
||||
migrated_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
# Migrate each legacy preset
|
||||
for filename in legacy_files:
|
||||
preset_name = os.path.splitext(filename)[0]
|
||||
legacy_file = os.path.join(legacy_dir, filename)
|
||||
persistent_file = os.path.join(persistent_dir, filename)
|
||||
backup_file = os.path.join(backup_dir, filename)
|
||||
|
||||
try:
|
||||
# Create backup copy first
|
||||
import shutil
|
||||
shutil.copy2(legacy_file, backup_file)
|
||||
|
||||
# If preset doesn't exist in persistent storage, migrate it
|
||||
if filename not in existing_persistent:
|
||||
shutil.copy2(legacy_file, persistent_file)
|
||||
migrated_count += 1
|
||||
print(f"[TTG] Migrated preset '{preset_name}' to persistent storage")
|
||||
else:
|
||||
skipped_count += 1
|
||||
print(f"[TTG] Skipped preset '{preset_name}' (already exists in persistent storage)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[TTG] Error migrating preset '{preset_name}': {e}")
|
||||
|
||||
# Create migration completion marker
|
||||
with open(migration_marker, 'w') as f:
|
||||
migration_info = {
|
||||
"migration_date": time.time(),
|
||||
"migrated_count": migrated_count,
|
||||
"skipped_count": skipped_count,
|
||||
"backup_location": backup_dir
|
||||
}
|
||||
import json
|
||||
json.dump(migration_info, f, indent=2)
|
||||
|
||||
print(f"[TTG] ✅ Migration completed: {migrated_count} migrated, {skipped_count} skipped")
|
||||
print(f"[TTG] Backup created at: {backup_dir}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"[TTG] ❌ Error during migration: {e}")
|
||||
return False
|
||||
|
||||
def get_unified_preset_list():
|
||||
"""
|
||||
Get unified preset list with two-tier loading and priority rules.
|
||||
Returns dict with preset names as keys and (preset_data, source) as values.
|
||||
|
||||
Priority order: BLEND_FILE > PERSISTENT_FILE
|
||||
Blend file presets always take priority over persistent ones.
|
||||
"""
|
||||
all_presets = {}
|
||||
|
||||
try:
|
||||
# Load persistent presets first (lower priority)
|
||||
persistent_dir = get_persistent_preset_path()
|
||||
if os.path.exists(persistent_dir):
|
||||
for filename in os.listdir(persistent_dir):
|
||||
if filename.endswith('.json') and not filename.startswith('.'):
|
||||
preset_name = os.path.splitext(filename)[0]
|
||||
try:
|
||||
with open(os.path.join(persistent_dir, filename), 'r') as f:
|
||||
preset_data = json.load(f)
|
||||
all_presets[preset_name] = (preset_data, 'PERSISTENT_FILE')
|
||||
except (json.JSONDecodeError, OSError) as e:
|
||||
print(f"[TTG] Error reading persistent preset {preset_name}: {e}")
|
||||
|
||||
# Load blend file presets and override any conflicts (higher priority)
|
||||
blend_presets = get_blend_file_presets()
|
||||
for name, data in blend_presets.items():
|
||||
all_presets[name] = (data, 'BLEND_FILE')
|
||||
|
||||
except Exception as e:
|
||||
print(f"[TTG] Error in get_unified_preset_list: {e}")
|
||||
|
||||
return all_presets
|
||||
|
||||
def save_preset_unified(preset_data, name, save_to_blend_file=False):
|
||||
"""
|
||||
Save a preset to either persistent file or blend file based on user choice.
|
||||
Default behavior saves to persistent file.
|
||||
"""
|
||||
if save_to_blend_file:
|
||||
return save_blend_file_preset(name, preset_data)
|
||||
else:
|
||||
# Save to persistent file
|
||||
try:
|
||||
persistent_dir = get_persistent_preset_path()
|
||||
persistent_file = os.path.join(persistent_dir, f"{name}.json")
|
||||
|
||||
with open(persistent_file, 'w') as f:
|
||||
json.dump(preset_data, f, indent=2)
|
||||
|
||||
print(f"[TTG] Saved preset '{name}' to persistent storage")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"[TTG] Error saving preset to persistent storage: {e}")
|
||||
return False
|
||||
|
||||
def initialize_presets():
|
||||
"""Initialize presets with simplified, reliable synchronization"""
|
||||
"""Initialize the simplified preset system and run migration if needed."""
|
||||
try:
|
||||
import bpy
|
||||
if not hasattr(bpy.context, 'scene') or not bpy.context.scene:
|
||||
@@ -311,80 +454,26 @@ def initialize_presets():
|
||||
|
||||
print(f"[TTG] Starting preset initialization...")
|
||||
|
||||
# Run one-time migration from old system
|
||||
migrate_from_legacy_system()
|
||||
|
||||
# Clear existing presets to avoid duplicates
|
||||
props.presets.clear()
|
||||
|
||||
# Collect all presets from all sources
|
||||
all_presets = {}
|
||||
|
||||
# 1. Load from blend file (highest priority - travels with file)
|
||||
try:
|
||||
blend_presets = get_blend_file_presets()
|
||||
for name, data in blend_presets.items():
|
||||
all_presets[name] = {
|
||||
'data': data,
|
||||
'source': 'BLEND_FILE'
|
||||
}
|
||||
print(f"[TTG] Found {len(blend_presets)} presets in blend file")
|
||||
except Exception as e:
|
||||
print(f"[TTG] Error loading blend file presets: {e}")
|
||||
|
||||
# 2. Load from persistent storage (survives addon updates)
|
||||
try:
|
||||
persistent_dir = get_persistent_preset_path()
|
||||
if os.path.exists(persistent_dir):
|
||||
for filename in os.listdir(persistent_dir):
|
||||
if filename.endswith('.json'):
|
||||
preset_name = os.path.splitext(filename)[0]
|
||||
# Only add if not already in blend file (blend file has priority)
|
||||
if preset_name not in all_presets:
|
||||
try:
|
||||
with open(os.path.join(persistent_dir, filename), 'r') as f:
|
||||
preset_data = json.load(f)
|
||||
all_presets[preset_name] = {
|
||||
'data': preset_data,
|
||||
'source': 'PERSISTENT_FILE'
|
||||
}
|
||||
except (json.JSONDecodeError, OSError) as e:
|
||||
print(f"[TTG] Error reading persistent preset {preset_name}: {e}")
|
||||
print(f"[TTG] Found {len([p for p in all_presets.values() if p['source'] == 'PERSISTENT_FILE'])} persistent presets")
|
||||
except Exception as e:
|
||||
print(f"[TTG] Error loading persistent presets: {e}")
|
||||
|
||||
# 3. Load from legacy storage (backward compatibility)
|
||||
try:
|
||||
legacy_dir = get_preset_path()
|
||||
if os.path.exists(legacy_dir) and legacy_dir != get_persistent_preset_path():
|
||||
for filename in os.listdir(legacy_dir):
|
||||
if filename.endswith('.json'):
|
||||
preset_name = os.path.splitext(filename)[0]
|
||||
# Only add if not already found in higher priority sources
|
||||
if preset_name not in all_presets:
|
||||
try:
|
||||
with open(os.path.join(legacy_dir, filename), 'r') as f:
|
||||
preset_data = json.load(f)
|
||||
all_presets[preset_name] = {
|
||||
'data': preset_data,
|
||||
'source': 'LOCAL_FILE'
|
||||
}
|
||||
except (json.JSONDecodeError, OSError) as e:
|
||||
print(f"[TTG] Error reading legacy preset {preset_name}: {e}")
|
||||
print(f"[TTG] Found {len([p for p in all_presets.values() if p['source'] == 'LOCAL_FILE'])} legacy presets")
|
||||
except Exception as e:
|
||||
print(f"[TTG] Error loading legacy presets: {e}")
|
||||
# Get unified preset list
|
||||
all_presets = get_unified_preset_list()
|
||||
|
||||
# Add all presets to UI list
|
||||
for preset_name, preset_info in all_presets.items():
|
||||
for preset_name, (preset_data, source) in all_presets.items():
|
||||
preset = props.presets.add()
|
||||
preset.name = preset_name
|
||||
preset.source = preset_info['source']
|
||||
preset.source = source
|
||||
|
||||
# Report results
|
||||
blend_count = len([p for p in props.presets if p.source == 'BLEND_FILE'])
|
||||
persistent_count = len([p for p in props.presets if p.source == 'PERSISTENT_FILE'])
|
||||
legacy_count = len([p for p in props.presets if p.source == 'LOCAL_FILE'])
|
||||
|
||||
print(f"[TTG] ✅ Initialized {len(props.presets)} presets ({blend_count} blend file, {persistent_count} persistent, {legacy_count} legacy)")
|
||||
print(f"[TTG] ✅ Initialized {len(props.presets)} presets ({blend_count} blend file, {persistent_count} persistent)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[TTG] Critical error in initialize_presets: {e}")
|
||||
|
||||
Binary file not shown.
@@ -180,10 +180,9 @@ class TEXT_TEXTURE_Preset(PropertyGroup):
|
||||
description="Where this preset is stored",
|
||||
items=[
|
||||
('BLEND_FILE', 'Blend File', 'Preset stored in the blend file (travels with the file)'),
|
||||
('PERSISTENT_FILE', 'Persistent File', 'Preset stored in persistent location (survives addon updates)'),
|
||||
('LOCAL_FILE', 'Local File', 'Preset stored locally (legacy system)')
|
||||
('PERSISTENT_FILE', 'Persistent File', 'Preset stored in persistent location (survives addon updates)')
|
||||
],
|
||||
default='BLEND_FILE'
|
||||
default='PERSISTENT_FILE'
|
||||
)
|
||||
|
||||
class TEXT_TEXTURE_Properties(PropertyGroup):
|
||||
@@ -628,6 +627,13 @@ class TEXT_TEXTURE_Properties(PropertyGroup):
|
||||
default=False
|
||||
)
|
||||
|
||||
# Save with blend file checkbox
|
||||
save_with_blend_file: BoolProperty(
|
||||
name="Save with .blend file",
|
||||
description="Save this preset with the current .blend file instead of persistent storage",
|
||||
default=False
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
# SHADER GENERATION PROPERTIES
|
||||
# ============================================================================
|
||||
|
||||
Binary file not shown.
100
src/ui/panels.py
100
src/ui/panels.py
@@ -242,12 +242,15 @@ def draw_preview_options_section(layout, props):
|
||||
layout.prop(props, "preview_bg_color2", text="Color 2")
|
||||
|
||||
def draw_presets_section(layout, props):
|
||||
"""Draw presets save/load controls"""
|
||||
"""Draw unified presets save/load controls"""
|
||||
# Save preset section
|
||||
save_row = layout.row(align=True)
|
||||
save_row.prop(props, "new_preset_name", text="", placeholder="Preset Name")
|
||||
save_row.operator("text_texture.save_preset", text="Save", icon='FILE_NEW')
|
||||
|
||||
# Save with blend file checkbox
|
||||
layout.prop(props, "save_with_blend_file")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Import/Export and refresh buttons
|
||||
@@ -261,76 +264,51 @@ def draw_presets_section(layout, props):
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Load presets section
|
||||
# Load presets section - unified list
|
||||
if props.presets:
|
||||
layout.label(text=f"📁 Saved Presets ({len(props.presets)}):", icon='PRESET')
|
||||
layout.label(text=f"📁 Available Presets ({len(props.presets)}):", icon='PRESET')
|
||||
|
||||
# Separate presets by source
|
||||
blend_presets = [p for p in props.presets if p.source == 'BLEND_FILE']
|
||||
persistent_presets = [p for p in props.presets if p.source == 'PERSISTENT_FILE']
|
||||
local_presets = [p for p in props.presets if p.source == 'LOCAL_FILE']
|
||||
# Sort presets alphabetically for consistent display
|
||||
sorted_presets = sorted(props.presets, key=lambda p: p.name.lower())
|
||||
|
||||
# Show blend file presets first
|
||||
if blend_presets:
|
||||
layout.label(text="🎯 Blend File Presets (travel with file):", icon='FILE_BLEND')
|
||||
for preset in blend_presets:
|
||||
row = layout.row()
|
||||
load_btn = row.operator("text_texture.load_preset", text=f"📋 {preset.name}")
|
||||
load_btn.preset_name = preset.name
|
||||
|
||||
# Quick overwrite button
|
||||
overwrite_btn = row.operator("text_texture.save_preset", text="", icon='FILE_REFRESH')
|
||||
overwrite_btn.overwrite = True
|
||||
# Set the preset name so it can be overwritten
|
||||
overwrite_btn.preset_name = preset.name
|
||||
|
||||
delete_btn = row.operator("text_texture.delete_preset", text="", icon='TRASH')
|
||||
delete_btn.preset_name = preset.name
|
||||
for preset in sorted_presets:
|
||||
row = layout.row(align=True)
|
||||
row.scale_y = 0.9
|
||||
|
||||
# Storage indicator icon
|
||||
if preset.source == 'BLEND_FILE':
|
||||
icon = '📄' # Blend file indicator
|
||||
else:
|
||||
icon = '🏠' # Persistent storage indicator
|
||||
|
||||
# Load button with indicator
|
||||
load_btn = row.operator("text_texture.load_preset", text=f"{icon} {preset.name}")
|
||||
load_btn.preset_name = preset.name
|
||||
|
||||
# Quick overwrite button
|
||||
overwrite_btn = row.operator("text_texture.save_preset", text="", icon='FILE_REFRESH')
|
||||
overwrite_btn.overwrite = True
|
||||
overwrite_btn.preset_name = preset.name
|
||||
|
||||
# Delete button
|
||||
delete_btn = row.operator("text_texture.delete_preset", text="", icon='TRASH')
|
||||
delete_btn.preset_name = preset.name
|
||||
|
||||
# Show persistent presets second
|
||||
if persistent_presets:
|
||||
if blend_presets:
|
||||
layout.separator()
|
||||
layout.label(text="🛡️ Persistent Presets (survive addon updates):", icon='PREFERENCES')
|
||||
for preset in persistent_presets:
|
||||
row = layout.row()
|
||||
load_btn = row.operator("text_texture.load_preset", text=f"📋 {preset.name}")
|
||||
load_btn.preset_name = preset.name
|
||||
|
||||
# Quick overwrite button
|
||||
overwrite_btn = row.operator("text_texture.save_preset", text="", icon='FILE_REFRESH')
|
||||
overwrite_btn.overwrite = True
|
||||
# Set the preset name so it can be overwritten
|
||||
overwrite_btn.preset_name = preset.name
|
||||
|
||||
delete_btn = row.operator("text_texture.delete_preset", text="", icon='TRASH')
|
||||
delete_btn.preset_name = preset.name
|
||||
# Legend for storage indicators
|
||||
layout.separator()
|
||||
legend_box = layout.box()
|
||||
legend_box.scale_y = 0.8
|
||||
legend_box.label(text="Storage Indicators:", icon='INFO')
|
||||
legend_box.label(text="🏠 Persistent (survives addon updates)")
|
||||
legend_box.label(text="📄 Blend file (travels with .blend file)")
|
||||
|
||||
# Show local presets third
|
||||
if local_presets:
|
||||
if blend_presets or persistent_presets:
|
||||
layout.separator()
|
||||
layout.label(text="💻 Local Presets (this machine only):", icon='DISK_DRIVE')
|
||||
for preset in local_presets:
|
||||
row = layout.row()
|
||||
load_btn = row.operator("text_texture.load_preset", text=f"📋 {preset.name}")
|
||||
load_btn.preset_name = preset.name
|
||||
|
||||
# Quick overwrite button
|
||||
overwrite_btn = row.operator("text_texture.save_preset", text="", icon='FILE_REFRESH')
|
||||
overwrite_btn.overwrite = True
|
||||
# Set the preset name so it can be overwritten
|
||||
overwrite_btn.preset_name = preset.name
|
||||
|
||||
delete_btn = row.operator("text_texture.delete_preset", text="", icon='TRASH')
|
||||
delete_btn.preset_name = preset.name
|
||||
else:
|
||||
layout.label(text="📂 No presets saved yet", icon='INFO')
|
||||
layout.label(text="💡 Save your first preset above!", icon='LIGHT_DATA')
|
||||
layout.separator()
|
||||
info_box = layout.box()
|
||||
info_box.label(text="ℹ️ Presets are now saved in the blend file", icon='INFO')
|
||||
info_box.label(text="They will travel with your .blend file!")
|
||||
info_box.label(text="ℹ️ Presets: Persistent by default, blend file optional", icon='INFO')
|
||||
info_box.label(text="Check the box to save with your .blend file!")
|
||||
|
||||
def draw_shader_section(layout, props):
|
||||
"""Draw shader generation controls"""
|
||||
|
||||
Reference in New Issue
Block a user