Today, I created a simple clothing addon with a two-mesh coat. The addon adds everything needed for the simulation including material types for the clothes.

Is a blog about python programming language. You can see my work with python programming language, tutorials and news.
import sys
import os
import shutil
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QFileDialog, QMessageBox
from PyQt6.QtCore import QDateTime
class FileRenamer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Redenumire fișiere cu dată și index")
self.setGeometry(100, 100, 400, 150)
layout = QVBoxLayout()
self.button = QPushButton("Selectează folderul și redenumește fișierele")
self.button.clicked.connect(self.rename_files)
layout.addWidget(self.button)
self.setLayout(layout)
def rename_files(self):
folder = QFileDialog.getExistingDirectory(self, "Selectează folderul")
if not folder:
return
files = [f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f))]
files.sort() # Sortează pentru consistență
for index, filename in enumerate(files, start=1):
old_path = os.path.join(folder, filename)
try:
creation_time = os.path.getctime(old_path)
dt = QDateTime.fromSecsSinceEpoch(int(creation_time))
date_str = dt.toString("yyyyMMdd_HHmmss")
ext = os.path.splitext(filename)[1]
new_name = f"{date_str}_{index:03d}{ext}"
new_path = os.path.join(folder, new_name)
# Evită suprascrierea fișierelor existente
if not os.path.exists(new_path):
shutil.move(old_path, new_path)
except Exception as e:
QMessageBox.critical(self, "Eroare", f"Eroare la fișierul {filename}:\n{str(e)}")
continue
QMessageBox.information(self, "Succes", "Fișierele au fost redenumite cu succes!")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = FileRenamer()
window.show()
sys.exit(app.exec())
%pip install segment-geospatial
%pip install leafmap
%pip install samgeo
%pip install localtileserver
%pip install fiona
Versiunea de Python: 3.8.5 (default, Jul 20 2020, 23:11:29)
[GCC 9.3.0]
Module instalate:
- webencodings (0.5.1)
- urllib3 (1.25.9)
- toml (0.10.1)
- six (1.15.0)
- setuptools (47.0.0)
- retrying (1.3.3)
- requests (2.23.0)
- pytz (2020.1)
- pytoml (0.1.21)
- python-dateutil (2.8.1)
- pyparsing (2.4.7)
- progress (1.5)
- pip (20.1.1)
- pep517 (0.8.2)
- pandas (1.1.0)
- packaging (20.4)
- ordered-set (4.0.1)
- numpy (1.19.1)
- msgpack (1.0.0)
- lockfile (0.12.2)
- idna (2.9)
- html5lib (1.0.1)
- distro (1.5.0)
- distlib (0.3.0)
- contextlib2 (0.6.0)
- colorama (0.4.3)
- chardet (3.0.4)
- certifi (2020.4.5.1)
- CacheControl (0.12.6)
- appdirs (1.4.4)
** Process exited - Return Code: 0 **
from krita import *
from PyQt5.QtWidgets import QAction, QMessageBox
import os
class ExportGodotPNG(Extension):
def __init__(self, parent):
super().__init__(parent)
def setup(self):
pass
def export_png(self):
# Get the active document
doc = Krita.instance().activeDocument()
if not doc:
QMessageBox.warning(None, "Error", "No document open! Please open a document and try again.")
return
# Create an InfoObject for PNG export
info = InfoObject()
info.setProperty("alpha", True) # Keep alpha channel for transparency
info.setProperty("compression", 0) # No compression for maximum quality
info.setProperty("interlaced", False) # Disable interlacing
info.setProperty("forceSRGB", True) # Force sRGB for Godot compatibility
# Build the output file path
if doc.fileName():
base_path = os.path.splitext(doc.fileName())[0]
else:
base_path = os.path.join(os.path.expanduser("~"), "export_godot")
output_file = base_path + "_godot.png"
# Export the document as PNG
try:
doc.exportImage(output_file, info)
# Show success message with brief usage info
QMessageBox.information(None, "Success",
f"Successfully exported as PNG for Godot: {output_file}\n\n"
"This PNG has no compression, alpha channel support, and sRGB for Godot compatibility. "
"To use in Godot, import the PNG and adjust texture settings as needed."
)
except Exception as e:
QMessageBox.critical(None, "Error", f"Export failed: {str(e)}")
def createActions(self, window):
# Create only the export action in Tools > Scripts
action_export = window.createAction("export_godot_png", "Export Godot PNG", "tools/scripts")
action_export.triggered.connect(self.export_png)
# Register the plugin
Krita.instance().addExtension(ExportGodotPNG(Krita.instance()))
bl_info = {
"name": "Append Materials from Folder",
"author": "Grok",
"version": (1, 2),
"blender": (3, 0, 0),
"location": "View3D > Sidebar > Append Materials",
"description": "Select a folder and append all materials from .blend files recursively",
"category": "Import-Export",
}
import bpy
import os
from bpy.types import Operator, Panel, PropertyGroup
from bpy.props import StringProperty, PointerProperty
class AppendMaterialsProperties(PropertyGroup):
folder_path: StringProperty(
name="Folder Path",
description="Path to the folder containing .blend files",
default="",
maxlen=1024,
subtype='DIR_PATH'
)
class APPEND_OT_materials_from_folder(Operator):
bl_idname = "append.materials_from_folder"
bl_label = "Append Materials from Folder"
bl_options = {'REGISTER', 'UNDO'}
bl_description = "Append all materials from .blend files in the selected folder and subfolders"
def execute(self, context):
props = context.scene.append_materials_props
folder_path = props.folder_path
# Normalize path to avoid issues with slashes
folder_path = os.path.normpath(bpy.path.abspath(folder_path))
if not folder_path or not os.path.isdir(folder_path):
self.report({'ERROR'}, f"Invalid or no folder selected: {folder_path}")
return {'CANCELLED'}
self.report({'INFO'}, f"Scanning folder: {folder_path}")
blend_files_found = 0
materials_appended = 0
errors = []
# Walk recursively through the folder
for root, dirs, files in os.walk(folder_path):
self.report({'INFO'}, f"Checking folder: {root}")
for file in files:
if file.lower().endswith('.blend'):
blend_files_found += 1
blend_path = os.path.join(root, file)
self.report({'INFO'}, f"Found .blend file: {blend_path}")
try:
# Open the .blend file to inspect materials
with bpy.data.libraries.load(blend_path, link=False) as (data_from, data_to):
if data_from.materials:
data_to.materials = data_from.materials
materials_appended += len(data_from.materials)
self.report({'INFO'}, f"Appended {len(data_from.materials)} materials from: {blend_path}")
else:
self.report({'WARNING'}, f"No materials found in: {blend_path}")
except Exception as e:
errors.append(f"Failed to process {blend_path}: {str(e)}")
self.report({'WARNING'}, f"Error in {blend_path}: {str(e)}")
# Final report
if blend_files_found == 0:
self.report({'WARNING'}, f"No .blend files found in {folder_path} or its subfolders!")
else:
self.report({'INFO'}, f"Found {blend_files_found} .blend files, appended {materials_appended} materials.")
if errors:
self.report({'WARNING'}, f"Encountered {len(errors)} errors: {'; '.join(errors)}")
return {'FINISHED'}
class VIEW3D_PT_append_materials(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "Append Materials"
bl_label = "Append Materials from Folder"
def draw(self, context):
layout = self.layout
props = context.scene.append_materials_props
layout.prop(props, "folder_path")
layout.operator("append.materials_from_folder", text="Append Materials")
def register():
bpy.utils.register_class(AppendMaterialsProperties)
bpy.utils.register_class(APPEND_OT_materials_from_folder)
bpy.utils.register_class(VIEW3D_PT_append_materials)
bpy.types.Scene.append_materials_props = PointerProperty(type=AppendMaterialsProperties)
def unregister():
bpy.utils.unregister_class(VIEW3D_PT_append_materials)
bpy.utils.unregister_class(APPEND_OT_materials_from_folder)
bpy.utils.unregister_class(AppendMaterialsProperties)
del bpy.types.Scene.append_materials_props
if __name__ == "__main__":
register()