Compare commits
3 Commits
fd22216d91
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c3b78075b | |||
| 2f8e5f472f | |||
| b401eb4bcf |
+10
-10
@@ -10,13 +10,13 @@ D:\Work\9 iClone\Amazon\
|
|||||||
D:\Amazon\00_external-files\
|
D:\Amazon\00_external-files\
|
||||||
N:\1. CHARACTERS\remapping\
|
N:\1. CHARACTERS\remapping\
|
||||||
[Recent]
|
[Recent]
|
||||||
D:\2026-04-14 BCONNA2026_MARI\
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Deliverable\Stills\
|
||||||
G:\Flamenco\renders\
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\
|
||||||
C:\Users\Nathan\Downloads\
|
A:\1 Amazon_Active_Projects\260513_FSAF_edits_2026\Blends\stills\
|
||||||
D:\portfolio\
|
N:\1. CHARACTERS\remapping\
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\Watering Ground\
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\
|
||||||
P:\250827_FestivalTurf\Assets\Blends\
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\img-BG\
|
||||||
T:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\
|
T:\1 BlenderAssets\
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\img-BG\
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Assets\Blends\
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"flamenco_version": {
|
"flamenco_version": {
|
||||||
"version": "3.8.2",
|
"version": "3.10-alpha0 (0c2ec48d)",
|
||||||
"shortversion": "3.8.2",
|
"shortversion": "3.10-alpha0",
|
||||||
"name": "Flamenco",
|
"name": "Flamenco",
|
||||||
"git": "51a41a19"
|
"git": "0c2ec48d"
|
||||||
},
|
},
|
||||||
"shared_storage": {
|
"shared_storage": {
|
||||||
"location": "R:\\mnt\\user\\Cerberus Max\\Flamenco",
|
"location": "F:\\jobs",
|
||||||
"audience": "users",
|
"audience": "users",
|
||||||
"platform": "windows",
|
"platform": "windows",
|
||||||
"shaman_enabled": false
|
"shaman_enabled": true
|
||||||
},
|
},
|
||||||
"job_types": {
|
"job_types": {
|
||||||
"job_types": [
|
"job_types": [
|
||||||
@@ -283,197 +283,6 @@
|
|||||||
"etag": "fe38e5ae9b3e640119d0d55fc7cbf4f8f15f2982",
|
"etag": "fe38e5ae9b3e640119d0d55fc7cbf4f8f15f2982",
|
||||||
"description": "Create a viewport preview/playblast using Cycles OPTIX GPU rendering and generate a video file"
|
"description": "Create a viewport preview/playblast using Cycles OPTIX GPU rendering and generate a video file"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "HoloMARI",
|
|
||||||
"label": "HoloMARI (MARI render_one)",
|
|
||||||
"settings": [
|
|
||||||
{
|
|
||||||
"key": "mari_jobs_json",
|
|
||||||
"type": "string",
|
|
||||||
"description": "JSON object with a \"jobs\" array: {\"jobs\":[{\"cam_name\":...,\"H\":...,\"V\":...}, ...]}. Optional \"frame\" per job for ANIM.",
|
|
||||||
"eval": "__import__('json').dumps({'jobs':[{'cam_name':o.name,'H':int(o['H']),'V':int(o['V'])} for o in C.scene.objects if getattr(o,'type',None)=='CAMERA' and o.name.startswith('MARI_CAMERA') and 'H' in o.keys() and 'V' in o.keys()]})",
|
|
||||||
"eval_info": {
|
|
||||||
"show_link_button": true,
|
|
||||||
"description": "Auto-collect MARI cameras (name MARI_CAMERA*, custom props H,V). Matches MARI Advanced / HoloMARI job JSON."
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "mari_action",
|
|
||||||
"type": "string",
|
|
||||||
"choices": [
|
|
||||||
"STILL",
|
|
||||||
"ANIM"
|
|
||||||
],
|
|
||||||
"default": "STILL",
|
|
||||||
"description": "MARI action passed to render_one / export_mari: STILL or ANIM",
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "mari_mode",
|
|
||||||
"type": "string",
|
|
||||||
"choices": [
|
|
||||||
"CIRCLE",
|
|
||||||
"FRAME"
|
|
||||||
],
|
|
||||||
"default": "CIRCLE",
|
|
||||||
"description": "MARI layout mode for export_mari type=FRAME|CIRCLE",
|
|
||||||
"eval": "(lambda m: 'FRAME' if str(m) == 'FRAME' else 'CIRCLE')(str(getattr(getattr(C.scene, 'mari_props', None), 'frame', 'CIRCLE') or 'CIRCLE'))",
|
|
||||||
"eval_info": {
|
|
||||||
"show_link_button": true,
|
|
||||||
"description": "FRAME vs CIRCLE from scene mari_props.frame"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chunk_size",
|
|
||||||
"type": "int32",
|
|
||||||
"default": 1.0,
|
|
||||||
"description": "Number of MARI render_one units (cameras/frames) per Blender task",
|
|
||||||
"propargs": {
|
|
||||||
"max": 4096.0,
|
|
||||||
"min": 1.0
|
|
||||||
},
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "frames",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Frame range for ANIM expansion. Examples: '47', '1-30'",
|
|
||||||
"eval": "f'{C.scene.frame_start}-{C.scene.frame_end}'",
|
|
||||||
"eval_info": {
|
|
||||||
"show_link_button": true,
|
|
||||||
"description": "Scene frame range (used when expanding ANIM image sequences)"
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "frame_start",
|
|
||||||
"type": "int32",
|
|
||||||
"eval": "C.scene.frame_start",
|
|
||||||
"visible": "hidden"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "frame_end",
|
|
||||||
"type": "int32",
|
|
||||||
"eval": "C.scene.frame_end",
|
|
||||||
"visible": "hidden"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "frame_step",
|
|
||||||
"type": "int32",
|
|
||||||
"eval": "max(1, C.scene.frame_step)",
|
|
||||||
"visible": "hidden"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "render_output_root",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Root folder for MARI output; images go under <root>/<mari_props.render_settings_name> (name comes from the scene, not this field).",
|
|
||||||
"required": true,
|
|
||||||
"subtype": "dir_path",
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "add_path_components",
|
|
||||||
"type": "int32",
|
|
||||||
"default": 0.0,
|
|
||||||
"description": "Number of path components of the current blend file to append under the render root",
|
|
||||||
"propargs": {
|
|
||||||
"max": 32.0,
|
|
||||||
"min": 0.0
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "render_output_path",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Job artifact path (mari_job.txt). MARI JPEG/output folder = render_output_root + MARI folder name.",
|
|
||||||
"editable": false,
|
|
||||||
"eval": "str(Path(abspath(settings.render_output_root), last_n_dir_parts(settings.add_path_components), jobname, '{timestamp}', 'mari_job.txt'))",
|
|
||||||
"subtype": "file_path"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "mari_output_dir_abs",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Absolute MARI output folder (render root + scene folder name); used by the zip step.",
|
|
||||||
"editable": false,
|
|
||||||
"eval": "str(Path(abspath(settings.render_output_root)) / str(getattr(getattr(C.scene, 'mari_props', None), 'render_settings_name', '') or '').strip())",
|
|
||||||
"visible": "hidden"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "mari_output_zip_abs",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Absolute path for the final .zip next to the output folder.",
|
|
||||||
"editable": false,
|
|
||||||
"eval": "str(Path(abspath(settings.render_output_root)) / (str(getattr(getattr(C.scene, 'mari_props', None), 'render_settings_name', '') or '').strip() + '.zip'))",
|
|
||||||
"visible": "hidden"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "zip_render_output",
|
|
||||||
"type": "bool",
|
|
||||||
"default": true,
|
|
||||||
"description": "After all MARI chunk tasks finish, create a .zip of the output folder (requires a worker that runs misc tasks; uses tar).",
|
|
||||||
"required": false,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "use_cycles_optix",
|
|
||||||
"type": "bool",
|
|
||||||
"default": false,
|
|
||||||
"description": "When enabled, sets Cycles preferences to OPTIX and scene Cycles device to GPU (same idea as cycles_optix_gpu.js).",
|
|
||||||
"label": "Cycles: OPTIX + GPU device",
|
|
||||||
"required": false,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "experimental_gp3",
|
|
||||||
"type": "bool",
|
|
||||||
"description": "Experimental Flag: Grease Pencil 3",
|
|
||||||
"label": "Experimental: GPv3",
|
|
||||||
"required": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "experimental_new_anim",
|
|
||||||
"type": "bool",
|
|
||||||
"description": "Experimental Flag: New Animation Data-block",
|
|
||||||
"label": "Experimental: Baklava",
|
|
||||||
"required": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "blender_args_before",
|
|
||||||
"type": "string",
|
|
||||||
"description": "CLI arguments for Blender, placed before the .blend filename",
|
|
||||||
"label": "Blender CLI args: Before",
|
|
||||||
"required": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "blender_args_after",
|
|
||||||
"type": "string",
|
|
||||||
"description": "CLI arguments for Blender, placed after the .blend filename",
|
|
||||||
"label": "After",
|
|
||||||
"required": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "blendfile",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path of the Blend file",
|
|
||||||
"required": true,
|
|
||||||
"visible": "web"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "format",
|
|
||||||
"type": "string",
|
|
||||||
"eval": "C.scene.render.image_settings.file_format",
|
|
||||||
"required": true,
|
|
||||||
"visible": "web"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"etag": "d19240e637ce81fab40f8e4218ce0249db67d95e",
|
|
||||||
"description": "MARI Advanced render_one batches (export .mari3d prep + per-camera jobs). Optional Cycles OPTIX+GPU setup (off by default)."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TalkingHeads Custom Render",
|
"name": "TalkingHeads Custom Render",
|
||||||
"label": "TalkingHeads Custom Render",
|
"label": "TalkingHeads Custom Render",
|
||||||
@@ -517,18 +326,6 @@
|
|||||||
"subtype": "dir_path",
|
"subtype": "dir_path",
|
||||||
"visible": "submission"
|
"visible": "submission"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "daily_path",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Daily folder name under the render root, e.g. 'daily_250813'. If empty, auto-fills to today's date.",
|
|
||||||
"eval": "__import__('datetime').datetime.now().strftime('daily_%y%m%d')",
|
|
||||||
"eval_info": {
|
|
||||||
"show_link_button": true,
|
|
||||||
"description": "Auto-fill with today's daily folder name"
|
|
||||||
},
|
|
||||||
"required": false,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "use_submodule",
|
"key": "use_submodule",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
@@ -555,7 +352,7 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Final file path of where render output will be saved",
|
"description": "Final file path of where render output will be saved",
|
||||||
"editable": false,
|
"editable": false,
|
||||||
"eval": "str(Path(abspath(settings.render_output_root or '//'), ((str(settings.submodule or '').strip()) if (settings.use_submodule and str(settings.submodule or '').strip()) else ((__import__('os').path.basename(__import__('os').path.dirname(bpy.data.filepath))) if settings.use_submodule else '')), (settings.daily_path or __import__('datetime').datetime.now().strftime('daily_%y%m%d')), jobname, jobname + '_######'))",
|
"eval": "((lambda Path, abspath, os_path, settings_obj, jobname: str(Path(abspath(settings_obj.render_output_root or '//')) / (((str(settings_obj.submodule or '').strip()) if (settings_obj.use_submodule and str(settings_obj.submodule or '').strip()) else ((os_path.basename(os_path.dirname(bpy.data.filepath))) if settings_obj.use_submodule else ''))) / jobname / (jobname + '_######')))(__import__('pathlib').Path, __import__('os').path.abspath, __import__('os').path, settings, (job.name if 'job' in dir() and job and job.name else __import__('os').path.splitext(__import__('os').path.basename(bpy.data.filepath))[0])))",
|
||||||
"subtype": "file_path"
|
"subtype": "file_path"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -596,7 +393,7 @@
|
|||||||
"visible": "web"
|
"visible": "web"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"etag": "7773b03fd0d493d6d823d7d45bb3ef7f987384f3",
|
"etag": "5f716e7195e55712daee20c237d95f748e2c3d1e",
|
||||||
"description": "Render a sequence of frames, and create a preview video file"
|
"description": "Render a sequence of frames, and create a preview video file"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -634,18 +431,6 @@
|
|||||||
"subtype": "dir_path",
|
"subtype": "dir_path",
|
||||||
"visible": "submission"
|
"visible": "submission"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "daily_path",
|
|
||||||
"type": "string",
|
|
||||||
"description": "Daily folder name under the render root, e.g. 'daily_250813'. If empty, auto-fills to today's date.",
|
|
||||||
"eval": "__import__('datetime').datetime.now().strftime('daily_%y%m%d')",
|
|
||||||
"eval_info": {
|
|
||||||
"show_link_button": true,
|
|
||||||
"description": "Auto-fill with today's daily folder name"
|
|
||||||
},
|
|
||||||
"required": false,
|
|
||||||
"visible": "submission"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "use_submodule",
|
"key": "use_submodule",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
@@ -672,7 +457,7 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Final file path of where render output will be saved",
|
"description": "Final file path of where render output will be saved",
|
||||||
"editable": false,
|
"editable": false,
|
||||||
"eval": "str(Path(abspath(settings.render_output_root or '//'), ((str(settings.submodule or '').strip()) if (settings.use_submodule and str(settings.submodule or '').strip()) else ((__import__('os').path.basename(__import__('os').path.dirname(bpy.data.filepath))) if settings.use_submodule else '')), (settings.daily_path or __import__('datetime').datetime.now().strftime('daily_%y%m%d')), jobname, jobname + '_######'))",
|
"eval": "((lambda Path, abspath, os_path, settings_obj, jobname: str(Path(abspath(settings_obj.render_output_root or '//')) / (((str(settings_obj.submodule or '').strip()) if (settings_obj.use_submodule and str(settings_obj.submodule or '').strip()) else ((os_path.basename(os_path.dirname(bpy.data.filepath))) if settings_obj.use_submodule else ''))) / jobname / (jobname + '_######')))(__import__('pathlib').Path, __import__('os').path.abspath, __import__('os').path, settings, (job.name if 'job' in dir() and job and job.name else __import__('os').path.splitext(__import__('os').path.basename(bpy.data.filepath))[0])))",
|
||||||
"subtype": "file_path"
|
"subtype": "file_path"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -741,7 +526,7 @@
|
|||||||
"visible": "hidden"
|
"visible": "hidden"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"etag": "5e49db0874b8ee1211f6dbc0a59d66137b6996b2",
|
"etag": "758c56b672b0970896f30b85ee5165a5c096aec4",
|
||||||
"description": "OPTIX GPU rendering + extra checkboxes for some experimental features + extra CLI args for Blender"
|
"description": "OPTIX GPU rendering + extra checkboxes for some experimental features + extra CLI args for Blender"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,3 +17,5 @@
|
|||||||
{NVIDIA Corporation/NVIDIA GeForce RTX 3090/NVIDIA 595.79}=SUPPORTED
|
{NVIDIA Corporation/NVIDIA GeForce RTX 3090/NVIDIA 595.79}=SUPPORTED
|
||||||
{NVIDIA Corporation/NVIDIA GeForce GTX 1060 with Max-Q Design/NVIDIA 582.28}=SUPPORTED
|
{NVIDIA Corporation/NVIDIA GeForce GTX 1060 with Max-Q Design/NVIDIA 582.28}=SUPPORTED
|
||||||
{Intel/Intel(R) HD Graphics 630/4.6.0 - Build 27.20.100.9664}=SUPPORTED
|
{Intel/Intel(R) HD Graphics 630/4.6.0 - Build 27.20.100.9664}=SUPPORTED
|
||||||
|
{NVIDIA Corporation/NVIDIA GeForce RTX 4080 SUPER/NVIDIA 596.36}=SUPPORTED
|
||||||
|
{NVIDIA Corporation/NVIDIA GeForce RTX 4080 SUPER/NVIDIA 610.47}=SUPPORTED
|
||||||
|
|||||||
+198
-198
@@ -1,200 +1,200 @@
|
|||||||
D:\2026-04-14 BCONNA2026_MARI\Sample Stanford Bunny2.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1aC.blend
|
||||||
D:\2026-04-14 BCONNA2026_MARI\Sample Stanford Bunny1.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_4b.blend
|
||||||
C:\Users\Nathan\Downloads\Sample Stanford Bunny1.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_4a.blend
|
||||||
C:\Users\Nathan\Downloads\Sample Stanford Bunny.blend
|
A:\1 Amazon_Active_Projects\260513_FSAF_edits_2026\Blends\stills\iAmbassadorM2_3.blend
|
||||||
D:\portfolio\demo.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1aB.blend
|
||||||
D:\2025-12-28 ytshorts gigaproj\Blends\animations\FreddyEpstein\FreddyEpstein.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_3b.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\06_Watering.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_3a.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\06_Watering.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_3.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2B_SPA.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\FT-lipsync_SPA.blend
|
A:\1 Amazon_Active_Projects\260528_NonConSplitPickcart\Blends\stills\iNonConSplitPickcart_1.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2D_SPA.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Assets\Blends\City_Sidewalk_1.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2B.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_CORTEX_1d.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2C.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_1.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2D.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 3.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_23.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_LOADOUT_1.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\01 Develop Your Turf Plan\SPA\FT-lipsync.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 4D.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\01 Develop Your Turf Plan\SPA\01_Blueprint_SPA.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 4C.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\04 Securing Your Seam\SPA\06_FT_Hammering_insert_SPA.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 4B.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\SPA\Visual_0_opening.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 4a.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3B.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 2A.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\SPA\Visual 3B_SPA.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 2A_old.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\SPA\04_stretching pattern.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 2B.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\SPA\Visual 6_INSERT.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_17.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\SPA\Visual 8 insert.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_16.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\SPA\03_FT Shuffle.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_11.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\SPA\Visual 8 insert2.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_7.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\SPA\01_intro_SPA.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Assets\Blends\Traffic-Post.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\BD2\P&S_BD2_animation 12b.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_9.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\BD2\P&S_BD2_animation 12a.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_15.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\07_compacting.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_12.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\03_dirt to gravel.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_13.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\09_level ground.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_14.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\05_raking.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_10.blend
|
||||||
P:\250827_FestivalTurf\Assets\Blends\Props\Tools.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 1.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\01 Develop Your Turf Plan\01_Blueprint.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 1A.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 6defgh.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\animations\Walker_AP_animation 1B.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 6bc.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Assets\Blends\Delivery_Truck_Openable_v1.1.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 6a.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Assets\Blends\Delivery_Truck_Openable.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\04_Rock Yard.blend
|
A:\1 Amazon_Active_Projects\260526_Walker_Leader\Blends\stills\iWalker_AP_4.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 6I.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1aA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\02 Preparing the Base\01_intro.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Assets\Blends\lipsync.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_new_final.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1a.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_8.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_5c.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_7.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_17bA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_7_phone_insert.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13aB.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_7_reframe.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Assets\Blends\lipsync.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_7_phone_insert_alt.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_16d.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_5_heat_damage_insert_1.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13a.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_5.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13a_CM.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_4_leaf_blower_insert.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_5b.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_4_leaf_blower.blend
|
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Kyle_v1.2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_3_PE_spread.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_4c.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_2_push_broom.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Assets\Blends\lanyard_rigged.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_2_power_broom.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_4d.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_3b.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_16c_vertical.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_5b.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_16c.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_5aA.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_16e.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_4bC.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_6a.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_4bB.blend
|
T:\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13a.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_4bA.blend
|
F:\jobs\SS_2026_animation_16d-vs40\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\Regina_v4.4.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_4aB.blend
|
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Props\Tote_v2.0.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_4aA_part2.blend
|
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Set-Dressing\P2B_filler.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_4aA.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_3c.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_3a_insert2.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_3a_insert1.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_3a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_2c.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_2b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_SHORT_2a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 4.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 3A.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 5a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 5d.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 5bc.blend
|
|
||||||
F:\jobs\RSR_fluid_unload_animation 5a\RSR_fluid_unload_animation 5a.flamenco.blend
|
|
||||||
A:\@GMT-2026.04.02-18.00.00\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 5a.blend
|
|
||||||
A:\@GMT-2026.04.02-17.00.00\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 5a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 4b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 3C.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 2.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1D.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1c.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1b_c.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1b_b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1b_a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\animations\RSR_fluid_unload_animation 1b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260225_Problem-Solve_2026\Blends\animations\PS_2026_animation short 1b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_7d.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_7c.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_24c.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_25b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_25a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_24d.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_24e.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_animation 1_CYCLES.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_16e.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_24a.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_4b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_24b.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_16o.blend
|
|
||||||
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Props\Pallete_Broken_Planks.blend
|
|
||||||
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Props\Pallete_Broken.blend
|
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_24b_.blend
|
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-04-02_13-44_iRSR_fluid_unload_24b.blend
|
|
||||||
T:\1 BlenderAssets\Amazon\Props\Pallete_Broken.blend
|
|
||||||
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\amazon-3Dworld-assets_v4.0.blend
|
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\amazon-3Dworld-assets_v4.0.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-04-02_12-09_RSR_fluid_unload_SHORT_3a.blend
|
C:\Users\Nathan\AppData\Local\Temp\2026-05-21_11-46_SS_2026_animation_16d.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-04-02_12-11_RSR_fluid_unload_SHORT_3a.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_12A.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-04-02_12-13_RSR_fluid_unload_SHORT_3a.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13bB.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_19c.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_4b.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_23b.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13bA.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_23a.blend
|
F:\jobs\SS_2026_animation_13bA\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Ren_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Props\Long-Pallete.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_13b.blend
|
||||||
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Props\Shuttle_v2.0.blend
|
F:\jobs\SS_2026_animation_13a\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Ren_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_19d.blend
|
A:\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Ren_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_7.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_8cB.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\i_noncon_OOG_2c.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_15bB.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Blends\stills\iRSR_fluid_unload_19e.blend
|
A:\1 Amazon_Active_Projects\260506_Safety_School_Transformation_2026\Blends\animations\SS_2026_animation_8cB_vertical.blend
|
||||||
A:\1 Amazon_Active_Projects\260206_Dock_Unified\Blends\animations\Dock\DOCK_shrinkwrap_s3.blend
|
P:\260423_MukBuddy\Blends\animations\Pak Buddy Animation_v2_vert.blend
|
||||||
A:\1 Amazon_Active_Projects\260206_Dock_Unified\Blends\animations\Dock\DOCK_shrinkwrap_s4.blend
|
C:\Users\Nathan\AppData\Local\Temp\bat-ss2026-2b-pack\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon1\Martha_v4.4.blend
|
||||||
A:\1 Amazon_Active_Projects\260206_Dock_Unified\Blends\animations\Dock\DOCK_shrinkwrap_s2.blend
|
F:\jobs\FlowCSA_360_1bD-7c6o\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260206_Dock_Unified\Blends\animations\Dock\DOCK_shrinkwrap_s1.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1bD.blend
|
||||||
A:\1 Amazon_Active_Projects\260326_RSR-Fluid-Unload\Assets\Blends\PAM.blend
|
F:\jobs\FlowCSA_360_1bD-to93\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_2_broom.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1b_ADTA_D.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_1_respray_insert.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_D-ao45\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_1_respray.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_D-n9z0\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_0_5_sheering_insert.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_D\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_0_5_talking.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_D-jyur\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 5B_insert.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1b_ADTA_B.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 5.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1bB.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S_safety_refresher_1d_rev2.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1b_ADTA_A.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S_safety_refresher_1c_rev2.blend
|
C:\Users\Nathan\AppData\Local\Temp\2026-05-13_13-27_FlowCSA_360_1b_ADTA_A.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S_safety_refresher_1c.blend
|
C:\Users\Nathan\AppData\Local\Temp\2026-05-13_12-55_FlowCSA_360_1b_ADTA_A.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\SPA_noncon_OOG_short_animation 9a.blend
|
C:\Users\Nathan\AppData\Local\Temp\2026-05-13_13-03_FlowCSA_360_1b_ADTA_A.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_short_animation 9a_v3.blend
|
C:\Users\Nathan\AppData\Local\Temp\2026-05-13_13-11_FlowCSA_360_1b_ADTA_A.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_short_animation 9a.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1bA.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_short_animation 3a.blend
|
C:\Users\Nathan\AppData\Local\Temp\2026-05-12_17-26_FlowCSA_360_1b_ADTA_B.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Assets\Blends\lipsync.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_C-jh9z\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_short_animation 1b.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_C\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2026_new\P&S_2026_animation short 1c.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1b_ADTA_C.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_2a.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_C-sgxq\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_2b.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_C-n6rw\FlowCSA_360_1b_ADTA_C.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_2c.blend
|
F:\jobs\FlowCSA_360_1b_ADTA_C-n6rw\_outside_project\A\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\iP&S_2026_2b.blend
|
C:\Users\Nathan\AppData\Local\Temp\bat-flow-not-relative-only\_outside_project\a\1 Amazon_Active_Projects\1 BlenderAssets\Amazon\Char\Cartoon3\Bebe_v1.2.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\iP&S_2026_2a.blend
|
A:\1 Amazon_Active_Projects\260420_FLOW_2026\Blends\animations\FlowCSA_360_1bC.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\iP&S_2026_1b.blend
|
A:\1 Amazon_Active_Projects\260512_Agile_Gemba\Assets\Blends\Marker.blend
|
||||||
T:\260127_Pick-and-Stage_2026_edits\Blends\stills\iP&S_2026_2b.blend
|
C:\Users\Nathan\Downloads\SS_2026_animation_2b.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2026_new\iP&S_2026_2b.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\stills\iUP_M6_13.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2026_new\iP&S_2026_2a.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\stills\iUP_M6_12.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-03-27_15-23_2026-03-27_15-13_P&S2025_anim_2a.blend
|
F:\jobs\Pak Buddy Animation_v2\Pak Buddy Animation_v2.flamenco.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-03-27_15-13_P&S2025_anim_2a.blend
|
C:\Users\Nathan\Downloads\House.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-03-27_15-19_P&S2025_anim_2a.blend
|
C:\Users\Nathan\Downloads\UP_M5_3.blend
|
||||||
C:\Users\Nathan\AppData\Local\Temp\2026-03-27_15-21_P&S2025_anim_2a.blend
|
C:\Users\Nathan\Downloads\UP_M2_animation_d.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_3a.blend
|
G:\Amazon\2024\240402_Amazon_Coaching&Upstream\Upstream\blends\mod 2\animation 1\iUP_M2_6.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_3b.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\stills\iUP_M5_6.blend
|
||||||
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_1a.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\stills\iUP_M2_5.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 6.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\stills\iUP_M5_13.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 6.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\comp_RR\Visual 2B_SPA_comp_RR.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 5B_alt_vo.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2B_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 5B.blend
|
C:\Users\Nathan\Downloads\Visual 2B_SPA\Visual 2B_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 4B.blend
|
F:\jobs\Visual 2B_SPA-393g\Visual 2B_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 4A.blend
|
F:\jobs\Visual_5_SPA-ii75\Visual_5_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 4A_2.blend
|
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_5_SPA.blend
|
||||||
|
F:\jobs\Visual_5_SPA-ki6s\Visual_5_SPA.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_5_SPA.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_5_SPA_106-109.blend
|
||||||
|
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_2_broom_SPA.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_new_final_SPA\Visual_new_final_SPA.blend
|
||||||
|
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_new_final_SPA.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_new_final\Visual_new_final.blend
|
||||||
|
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_new_final.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_new_final.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_new_final_lady_dancer\Visual_new_final_lady_dancer.blend
|
||||||
|
C:\Users\Nathan\Downloads\Visual_new_final_kid_and_dog\Visual_new_final_kid_and_dog.blend
|
||||||
|
T:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_new_final_alt_shots.blend
|
||||||
|
F:\jobs\Visual_5_SPA-x1ig\Visual_5_SPA.blend
|
||||||
|
F:\jobs\Visual 3A-fec4\Visual 3A.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3A.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3A.blend
|
||||||
E:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3A.blend
|
C:\Users\Nathan\Downloads\Visual_new_final_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3A_.blend
|
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_0_5_talking_SPA.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3A.blend
|
P:\250827_FestivalTurf\Blends\animations\07 Final Touches And Maintenance\Visual_0_opening_SPA.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3B.blend
|
C:\Users\Nathan\Downloads\Visual 6_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\01_opening.blend
|
C:\Users\Nathan\Downloads\Visual 5B_alt_vo_SPA.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2D.blend
|
C:\Users\Nathan\Downloads\Visual 4A_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2A.blend
|
C:\Users\Nathan\Downloads\Visual 3B_SPA.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2C.blend
|
C:\Users\Nathan\Downloads\Visual 2D_SPA.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 2B.blend
|
F:\jobs\Visual 5_strech_SPA\Visual 5_strech_SPA.blend
|
||||||
P:\250827_FestivalTurf\Assets\Blends\Char\FT-rig_moustache.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 5_strech_SPA.blend
|
||||||
P:\250827_FestivalTurf\Assets\Blends\Char\FT-rig_moustache_fixed.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 4A_SPA.blend
|
||||||
T:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 11.blend
|
F:\jobs\Visual 3A-snms\Visual 3A.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 11.blend
|
C:\Users\Nathan\Downloads\01_opening_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 10.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\01_opening_SPA.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 9.blend
|
F:\jobs\Visual 5_strech_SPA\Visual 5_strech_SPA.flamenco.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 8.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 5B.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 8 insert2.blend
|
F:\jobs\Visual 3A-q4ro\Visual 3A.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 8 insert.blend
|
F:\jobs\Visual 3A\Visual 3A.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\01_intro.blend
|
P:\250827_FestivalTurf\Blends\animations\06 Infill And Powerbrooming\Visual 3B.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 7.blend
|
A:\1 Amazon_Active_Projects\260225_Problem-Solve_2026\Assets\Blends\AMZ-warehouse_v6.0_small.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\Visual 6_INSERT.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\0TEST.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\04_talking.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\UP_M1_animation1C.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\04_stretching pattern.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\0TEMP.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\03_FT Shuffle_Intro.blend
|
A:\1 Amazon_Active_Projects\260225_Problem-Solve_2026\Blends\animations\PS_2026_animation 1CD.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\03_FT Shuffle.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\UP_M1_animation1D.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\02_talking.blend
|
C:\Users\Nathan\Downloads\Upstream_LL_animation_new_C.blend
|
||||||
P:\250827_FestivalTurf\Blends\animations\05 Stretch Cut Nail\02_kicker insert.blend
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\Upstream_LL_animation_new_C.blend
|
||||||
P:\260217_Jarvis-Defense\Blends\animations\Shot_Q.blend
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_5D.blend
|
||||||
F:\jobs\Shot_5c\Shot_Q.flamenco.blend
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\P&S2025_anim_3c.blend
|
||||||
F:\jobs\Shot5c-e3zp\Shot_Q.flamenco.blend
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2024_old\P&S_safety_refresher_3b.blend
|
||||||
P:\260217_Jarvis-Defense\Blends\animations\Shot_4.blend
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2024_old\P&S_safety_refresher_3a.blend
|
||||||
P:\260217_Jarvis-Defense\Blends\animations\comp_RR\Shot_4a_holdout.blend
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\SOM\SOM_i_noncon_OOG_7b.blend
|
||||||
P:\260217_Jarvis-Defense\Blends\animations\comp_RR\Shot_4_comp.blend
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\i_noncon_OOG_7b.blend
|
||||||
F:\jobs\Shot_1b-qrzg\Shot_1.flamenco.blend
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\SPA\SPA_i_noncon_OOG_7b.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\SOM_noncon_OOG_short_animation 13a.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_short_animation 13a.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\HAT_noncon_OOG_short_animation 13a.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\animations\noncon_OOG_animation 1_CYCLES.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\SOM\SOM_i_noncon_OOG_9k.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\i_noncon_OOG_9k.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\HAT\HAT_i_noncon_OOG_9k.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\SOM\SOM_i_noncon_OOG_9m.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\i_noncon_OOG_9m.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\i_noncon_OOG_9l.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\HAT\HAT_i_noncon_OOG_9m.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\SOM\SOM_i_noncon_OOG_9l.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260317_NONCON_2026\Blends\stills\HAT\HAT_i_noncon_OOG_9l.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\UP_M4_S01_b.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\UP_M4_S01_c.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_30b.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_31a.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_26.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_22b.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_21.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_22_a.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\iP&S2025_19.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\stills\2025_old\i22.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\Ambassador_M3_A4_picker_s1.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\Ambassador_M3_A4_picker_s3.blend
|
||||||
|
C:\Users\Nathan\Downloads\Ambassador_M3_A4_picker_s3.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\Ambassador_M3_A4_coach-s2.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260127_Pick-and-Stage_2026_edits\Blends\animations\2025_old\Ambassador_M3_A4_coach-s1.blend
|
||||||
|
A:\1 Amazon_Active_Projects\260422_Upstream_edits_2026\Blends\animations\M4\UP_M4_S01_2hands.blend
|
||||||
|
G:\Amazon\2024\240402_Amazon_Coaching&Upstream\Upstream\blends\mod 4\UP_M4_S01.blend
|
||||||
|
G:\Amazon\2024\240402_Amazon_Coaching&Upstream\Upstream\blends\mod 4\UP_M4_S01_2hands.blend
|
||||||
|
|||||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
|||||||
schema_version = "1.0.0"
|
schema_version = "1.0.0"
|
||||||
|
|
||||||
id = "simple_renaming_panel"
|
id = "simple_renaming_panel"
|
||||||
version = "2.1.5"
|
version = "2.1.6"
|
||||||
name = "Simple Renaming"
|
name = "Simple Renaming"
|
||||||
tagline = "Effortlessly rename multiple objects with this simple addon"
|
tagline = "Effortlessly rename multiple objects with this simple addon"
|
||||||
maintainer = "Matthias Patscheider <patscheider.matthias@gmail.com>"
|
maintainer = "Matthias Patscheider <patscheider.matthias@gmail.com>"
|
||||||
|
|||||||
@@ -150,12 +150,20 @@ def register():
|
|||||||
default='X', # Set a default value
|
default='X', # Set a default value
|
||||||
)
|
)
|
||||||
|
|
||||||
id_store.renaming_new_name = StringProperty(name="New Name", default='')
|
id_store.renaming_new_name = StringProperty(
|
||||||
|
name="New Name",
|
||||||
|
description="Name pattern for renaming. Use @n for a numbered variable (configure its digits in Preferences). Use # in the Numerate field (right) to set the auto-suffix digit count",
|
||||||
|
default='',
|
||||||
|
)
|
||||||
id_store.renaming_search = StringProperty(name='Search', default='')
|
id_store.renaming_search = StringProperty(name='Search', default='')
|
||||||
id_store.renaming_replace = StringProperty(name='Replace', default='')
|
id_store.renaming_replace = StringProperty(name='Replace', default='')
|
||||||
id_store.renaming_suffix = StringProperty(name="Suffix", default='')
|
id_store.renaming_suffix = StringProperty(name="Suffix", default='')
|
||||||
id_store.renaming_prefix = StringProperty(name="Prefix", default='')
|
id_store.renaming_prefix = StringProperty(name="Prefix", default='')
|
||||||
id_store.renaming_numerate = StringProperty(name="Numerate", default='###')
|
id_store.renaming_numerate = StringProperty(
|
||||||
|
name="Numerate Pattern",
|
||||||
|
description="Pattern for the auto-numeration suffix appended when Numerate is enabled. Each # represents one digit (e.g. ### → 001, 002, …). This does not affect the @n variable",
|
||||||
|
default='###',
|
||||||
|
)
|
||||||
|
|
||||||
id_store.renaming_sorting = bpy.props.BoolProperty(
|
id_store.renaming_sorting = bpy.props.BoolProperty(
|
||||||
name="Sort Target Objects",
|
name="Sort Target Objects",
|
||||||
@@ -169,10 +177,9 @@ def register():
|
|||||||
|
|
||||||
id_store.renaming_matchcase = BoolProperty(name="Match Case", description="", default=True)
|
id_store.renaming_matchcase = BoolProperty(name="Match Case", description="", default=True)
|
||||||
id_store.renaming_useRegex = BoolProperty(name="Use Regex", description="", default=False)
|
id_store.renaming_useRegex = BoolProperty(name="Use Regex", description="", default=False)
|
||||||
id_store.renaming_use_enumerate = BoolProperty(name="Numerate",
|
id_store.renaming_use_enumerate = BoolProperty(
|
||||||
description="Enable and Disable the numeration of objects. This can "
|
name="Numerate",
|
||||||
"be especially useful in combination with the numeration "
|
description="Automatically appends an incrementing numeric suffix to each renamed object. Configure the suffix format with # in the Numerate field, and the digit count for the @n variable in Preferences",
|
||||||
"variable @n",
|
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
id_store.renaming_base_numerate = IntProperty(name="Step Size", default=1)
|
id_store.renaming_base_numerate = IntProperty(name="Step Size", default=1)
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ class BUTTON_OT_change_key(bpy.types.Operator):
|
|||||||
|
|
||||||
|
|
||||||
def add_keymap():
|
def add_keymap():
|
||||||
km = bpy.context.window_manager.keyconfigs.active.keymaps.new(name="Window")
|
wm = bpy.context.window_manager
|
||||||
|
kc = wm.keyconfigs.addon
|
||||||
|
if kc is None:
|
||||||
|
return
|
||||||
|
km = kc.keymaps.new(name="Window")
|
||||||
prefs = bpy.context.preferences.addons[base_package].preferences
|
prefs = bpy.context.preferences.addons[base_package].preferences
|
||||||
|
|
||||||
kmi = km.keymap_items.new(idname='wm.call_panel', type=prefs.renaming_panel_type, value='PRESS',
|
kmi = km.keymap_items.new(idname='wm.call_panel', type=prefs.renaming_panel_type, value='PRESS',
|
||||||
@@ -76,22 +80,33 @@ def add_key_to_keymap(idname, kmi, km, active=True):
|
|||||||
def remove_key(context, idname, properties_name):
|
def remove_key(context, idname, properties_name):
|
||||||
"""Removes addon hotkeys from the keymap"""
|
"""Removes addon hotkeys from the keymap"""
|
||||||
wm = bpy.context.window_manager
|
wm = bpy.context.window_manager
|
||||||
km = wm.keyconfigs.active.keymaps['Window']
|
kc = wm.keyconfigs.addon
|
||||||
|
if kc is None:
|
||||||
|
return
|
||||||
|
km = kc.keymaps.get('Window')
|
||||||
|
if km is None:
|
||||||
|
return
|
||||||
|
|
||||||
for kmi in km.keymap_items:
|
items_to_remove = [kmi for kmi in km.keymap_items
|
||||||
if kmi.idname == idname and kmi.properties.name == properties_name:
|
if kmi.idname == idname and kmi.properties.name == properties_name]
|
||||||
|
for kmi in items_to_remove:
|
||||||
km.keymap_items.remove(kmi)
|
km.keymap_items.remove(kmi)
|
||||||
|
|
||||||
|
|
||||||
def remove_keymap():
|
def remove_keymap():
|
||||||
"""Removes keys from the keymap. Currently, this is only called when unregistering the addon. """
|
"""Removes keys from the keymap. Currently, this is only called when unregistering the addon. """
|
||||||
# only works for menus and pie menus
|
|
||||||
wm = bpy.context.window_manager
|
wm = bpy.context.window_manager
|
||||||
km = wm.keyconfigs.active.keymaps['Window']
|
kc = wm.keyconfigs.addon
|
||||||
|
if kc is None:
|
||||||
|
return
|
||||||
|
km = kc.keymaps.get('Window')
|
||||||
|
if km is None:
|
||||||
|
return
|
||||||
|
|
||||||
for kmi in km.keymap_items:
|
items_to_remove = [kmi for kmi in km.keymap_items
|
||||||
if hasattr(kmi.properties, 'name') and kmi.properties.name in ['VIEW3D_PT_tools_renaming_panel',
|
if hasattr(kmi.properties, 'name') and kmi.properties.name in
|
||||||
'VIEW3D_PT_tools_type_suffix']:
|
{'VIEW3D_PT_tools_renaming_panel', 'VIEW3D_PT_tools_type_suffix'}]
|
||||||
|
for kmi in items_to_remove:
|
||||||
km.keymap_items.remove(kmi)
|
km.keymap_items.remove(kmi)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ def add_key(km, idname, properties_name, button_assignment_type, button_assignme
|
|||||||
def update_key(context, operation, operator_name, property_prefix):
|
def update_key(context, operation, operator_name, property_prefix):
|
||||||
# This functions gets called when the hotkey assignment is updated in the preferences
|
# This functions gets called when the hotkey assignment is updated in the preferences
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
km = wm.keyconfigs.active.keymaps["Window"]
|
kc = wm.keyconfigs.addon
|
||||||
|
if kc is None:
|
||||||
|
return
|
||||||
|
km = kc.keymaps.get("Window")
|
||||||
|
if km is None:
|
||||||
|
return
|
||||||
|
|
||||||
prefs = context.preferences.addons[base_package].preferences
|
prefs = context.preferences.addons[base_package].preferences
|
||||||
|
|
||||||
@@ -129,7 +134,7 @@ class VIEW3D_OT_renaming_preferences(bpy.types.AddonPreferences):
|
|||||||
|
|
||||||
numerate_digits: bpy.props.IntProperty(
|
numerate_digits: bpy.props.IntProperty(
|
||||||
name="Digits",
|
name="Digits",
|
||||||
description="Defines digits used for numerating. Number 1 with digits 3 would result in 001",
|
description="Number of digits used for the @n variable in the New Name field (e.g. @n with 3 digits: 001). To configure the auto-suffix digit count, use # characters in the Numerate field instead",
|
||||||
default=3,
|
default=3,
|
||||||
)
|
)
|
||||||
numerate_step: bpy.props.IntProperty(
|
numerate_step: bpy.props.IntProperty(
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
"id": "atomic_data_manager",
|
"id": "atomic_data_manager",
|
||||||
"name": "Atomic Data Manager",
|
"name": "Atomic Data Manager",
|
||||||
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
"version": "2.6.2",
|
"version": "2.6.3",
|
||||||
"type": "add-on",
|
"type": "add-on",
|
||||||
"maintainer": "RaincloudTheDragon",
|
"maintainer": "RaincloudTheDragon",
|
||||||
"license": [
|
"license": [
|
||||||
@@ -70,9 +70,9 @@
|
|||||||
"management",
|
"management",
|
||||||
"cleanup"
|
"cleanup"
|
||||||
],
|
],
|
||||||
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.2/Atomic_Data_Manager.v2.6.2.zip",
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
"archive_size": 121191,
|
"archive_size": 122700,
|
||||||
"archive_hash": "sha256:1f4af882cdf73d3bb0b8cf1badc094b179bf9e982486ee516c45a6a2d478c05d"
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"schema_version": "1.0.0",
|
"schema_version": "1.0.0",
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"version": "v1",
|
||||||
|
"blocklist": [],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "basedplayblast",
|
||||||
|
"name": "BasedPlayblast",
|
||||||
|
"tagline": "Easily create playblasts from Blender and Flamenco",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/BasedPlayblast",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Import/export files and data"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Animation",
|
||||||
|
"Render",
|
||||||
|
"Workflow",
|
||||||
|
"Video"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/BasedPlayblast/releases/download/v2.6.3/BasedPlayblast.v2.6.3.zip",
|
||||||
|
"archive_size": 49732,
|
||||||
|
"archive_hash": "sha256:078b406105ce6f4802e75233569841e2f73d082e09cd1d954696681ebf72b627"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "rainclouds_bulk_scene_tools",
|
||||||
|
"name": "Raincloud's Bulk Scene Tools",
|
||||||
|
"tagline": "Bulk utilities for optimizing scene data",
|
||||||
|
"version": "0.17.0",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon <raincloudthedragon@gmail.com>",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"website": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools",
|
||||||
|
"permissions": {
|
||||||
|
"files": "Read and write external resources referenced by scenes"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Scene",
|
||||||
|
"Workflow",
|
||||||
|
"Materials"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/Rainys-Bulk-Scene-Tools/releases/download/v0.17.0/Rainys_Bulk_Scene_Tools.v0.17.0.zip",
|
||||||
|
"archive_size": 80981,
|
||||||
|
"archive_hash": "sha256:419433069465b45ea903bd7bb46d89aa28b9c96c541d587d5f3be651a762811f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "atomic_data_manager",
|
||||||
|
"name": "Atomic Data Manager",
|
||||||
|
"tagline": "Smart cleanup and inspection of Blender data-blocks",
|
||||||
|
"version": "2.6.3",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "4.2.0",
|
||||||
|
"tags": [
|
||||||
|
"utility",
|
||||||
|
"management",
|
||||||
|
"cleanup"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/atomic-data-manager/releases/download/v2.6.3/Atomic_Data_Manager.v2.6.3.zip",
|
||||||
|
"archive_size": 122700,
|
||||||
|
"archive_hash": "sha256:b444463a0443864077abcfe97332406e606a697d3567ac32f85843760da11372"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"schema_version": "1.0.0",
|
||||||
|
"id": "sheepit_project_submitter",
|
||||||
|
"name": "SheepIt Project Submitter",
|
||||||
|
"tagline": "Submit projects to SheepIt render farm",
|
||||||
|
"version": "0.0.8",
|
||||||
|
"type": "add-on",
|
||||||
|
"maintainer": "RaincloudTheDragon",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"blender_version_min": "3.0.0",
|
||||||
|
"tags": [
|
||||||
|
"render",
|
||||||
|
"farm",
|
||||||
|
"submission",
|
||||||
|
"utility"
|
||||||
|
],
|
||||||
|
"archive_url": "https://github.com/RaincloudTheDragon/sheepit_project_submitter/releases/download/v0.0.8/SheepIt_Project_Submitter.v0.0.8.zip",
|
||||||
|
"archive_size": 47667,
|
||||||
|
"archive_hash": "sha256:93cd8f18456079130c48c66cfd40235f7fe6414f929f59f90670e7a864821110"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
## [v2.6.3] - 2026-04-22
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- **CC3 / iClone import caches**: `Scene['CC3ImportProps']` (e.g. `pbr_material_cache`) no longer blocks unused detection—when `material_all()` is empty, cache-only refs (including Blender’s 2× `users` per cell) are ignored for clean and RNA material scans (`stats/ghost_users.py`).
|
||||||
|
|
||||||
## [v2.6.2] - 2026-04-06
|
## [v2.6.2] - 2026-04-06
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ schema_version = "1.0.0"
|
|||||||
|
|
||||||
id = "atomic_data_manager"
|
id = "atomic_data_manager"
|
||||||
name = "Atomic Data Manager"
|
name = "Atomic Data Manager"
|
||||||
version = "2.6.2"
|
version = "2.6.3"
|
||||||
type = "add-on"
|
type = "add-on"
|
||||||
author = "RaincloudTheDragon"
|
author = "RaincloudTheDragon"
|
||||||
maintainer = "RaincloudTheDragon"
|
maintainer = "RaincloudTheDragon"
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
"""
|
||||||
|
Detect 'ghost' ID references (e.g. Reallusion CC / iClone import caches on Scene)
|
||||||
|
that keep bpy.users > 0 but are not real scene usage. Used by materials_deep and
|
||||||
|
any future cleanup paths.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from .. import config
|
||||||
|
|
||||||
|
|
||||||
|
def _idprop_count_material(p, mat, seen):
|
||||||
|
"""Recursively count pointers equal to `mat` under an ID property value."""
|
||||||
|
if p is None or id(p) in seen:
|
||||||
|
return 0
|
||||||
|
if isinstance(p, (str, int, float, bool)):
|
||||||
|
return 0
|
||||||
|
seen = seen | {id(p)}
|
||||||
|
if isinstance(p, bpy.types.Material) and p == mat:
|
||||||
|
return 1
|
||||||
|
n = 0
|
||||||
|
t = type(p).__name__
|
||||||
|
if isinstance(p, (list, tuple)):
|
||||||
|
for x in p:
|
||||||
|
n += _idprop_count_material(x, mat, seen)
|
||||||
|
elif isinstance(p, dict):
|
||||||
|
for v in p.values():
|
||||||
|
n += _idprop_count_material(v, mat, seen)
|
||||||
|
elif t == "IDPropertyGroup" or (hasattr(p, "keys") and hasattr(p, "values") and t != "dict"):
|
||||||
|
try:
|
||||||
|
for k in p.keys():
|
||||||
|
try:
|
||||||
|
v = p[k]
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
n += _idprop_count_material(v, mat, seen)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
def count_cc3_import_cache_references(material):
|
||||||
|
"""
|
||||||
|
Count Material pointers stored in Scene ID property group CC3ImportProps
|
||||||
|
(Character Creator 3 / iClone pipeline). These are import-cache ghosts and
|
||||||
|
are not object/world/brush use.
|
||||||
|
"""
|
||||||
|
m = 0
|
||||||
|
for scene in bpy.data.scenes:
|
||||||
|
try:
|
||||||
|
if "CC3ImportProps" not in scene:
|
||||||
|
continue
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
cc3 = scene["CC3ImportProps"]
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
m += _idprop_count_material(cc3, material, set())
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
def material_blender_users_fully_cc3_ghosts(material):
|
||||||
|
"""
|
||||||
|
True if every material.user can be explained by CC3 import_cache pointers.
|
||||||
|
|
||||||
|
Blender often reports *two* users per pbr cache slot: the Scene and the
|
||||||
|
pbr_material_cache cell both contribute to bpy.types.Material.users, while
|
||||||
|
our walk only counts Material pointers in the idprop tree (one per cell).
|
||||||
|
So u == 2 * cc3 is normal; u == cc3 can occur when the count already matches
|
||||||
|
1:1 in some file versions.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
u = material.users
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
if u == 0:
|
||||||
|
return True
|
||||||
|
cc3 = count_cc3_import_cache_references(material)
|
||||||
|
if cc3 == 0:
|
||||||
|
return False
|
||||||
|
if cc3 == u or u == 2 * cc3:
|
||||||
|
return True
|
||||||
|
if config.enable_debug_prints:
|
||||||
|
config.debug_print(
|
||||||
|
f"[Atomic Debug] ghost_users: material '{material.name}' users={u} "
|
||||||
|
f"cc3_count={cc3} (not fully explained by CC3; keep conservative block)"
|
||||||
|
)
|
||||||
|
return False
|
||||||
@@ -28,6 +28,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
from .. import config
|
from .. import config
|
||||||
from ..utils import compat
|
from ..utils import compat
|
||||||
|
from . import ghost_users
|
||||||
|
|
||||||
|
|
||||||
# Data-block types we care about for dependency analysis
|
# Data-block types we care about for dependency analysis
|
||||||
@@ -1197,6 +1198,8 @@ def analyze_unused_from_graph(graph, category, include_fake_users=None):
|
|||||||
if category == 'materials':
|
if category == 'materials':
|
||||||
try:
|
try:
|
||||||
if datablock.users > 0 and not datablock.use_fake_user:
|
if datablock.users > 0 and not datablock.use_fake_user:
|
||||||
|
if not ghost_users.material_blender_users_fully_cc3_ghosts(
|
||||||
|
datablock):
|
||||||
continue
|
continue
|
||||||
except (AttributeError, RuntimeError, ReferenceError):
|
except (AttributeError, RuntimeError, ReferenceError):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from .. import config
|
|||||||
from ..utils import compat
|
from ..utils import compat
|
||||||
from ..utils import version
|
from ..utils import version
|
||||||
from . import users
|
from . import users
|
||||||
|
from . import ghost_users
|
||||||
|
|
||||||
|
|
||||||
def shallow(data):
|
def shallow(data):
|
||||||
@@ -223,9 +224,9 @@ def materials_deep():
|
|||||||
# check if material has a fake user or if ignore fake users
|
# check if material has a fake user or if ignore fake users
|
||||||
# is enabled
|
# is enabled
|
||||||
if not material.use_fake_user or config.include_fake_users:
|
if not material.use_fake_user or config.include_fake_users:
|
||||||
# If Blender still counts users but we found none, don't flag (name collisions
|
|
||||||
# with linked IDs, drivers, or refs we don't traverse). Fake-user purge unchanged.
|
|
||||||
if material.users > 0 and not material.use_fake_user:
|
if material.users > 0 and not material.use_fake_user:
|
||||||
|
# CC3 / iClone import_cache ID props keep bpy.users>0 with no object/world use.
|
||||||
|
if not ghost_users.material_blender_users_fully_cc3_ghosts(material):
|
||||||
continue
|
continue
|
||||||
unused.append(material.name)
|
unused.append(material.name)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..stats import unused
|
from ..stats import unused
|
||||||
from ..stats import users
|
from ..stats import users
|
||||||
|
from . import ghost_users
|
||||||
from .. import config
|
from .. import config
|
||||||
from ..utils import compat
|
from ..utils import compat
|
||||||
|
|
||||||
@@ -128,6 +129,7 @@ def _has_any_unused_materials():
|
|||||||
if not users.material_all(material.name):
|
if not users.material_all(material.name):
|
||||||
if not material.use_fake_user or config.include_fake_users:
|
if not material.use_fake_user or config.include_fake_users:
|
||||||
if material.users > 0 and not material.use_fake_user:
|
if material.users > 0 and not material.use_fake_user:
|
||||||
|
if not ghost_users.material_blender_users_fully_cc3_ghosts(material):
|
||||||
continue
|
continue
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -20,7 +20,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Animation Layers",
|
"name": "Animation Layers",
|
||||||
"author": "Tal Hershkovich",
|
"author": "Tal Hershkovich",
|
||||||
"version" : (2, 3, 8),
|
"version" : (2, 4, 1),
|
||||||
"blender" : (3, 2, 0),
|
"blender" : (3, 2, 0),
|
||||||
"location": "View3D - Properties - Animation Panel",
|
"location": "View3D - Properties - Animation Panel",
|
||||||
"description": "Simplifying the NLA editor into an animation layers UI and workflow",
|
"description": "Simplifying the NLA editor into an animation layers UI and workflow",
|
||||||
@@ -73,7 +73,10 @@ class AnimLayersSceneSettings(bpy.types.PropertyGroup):
|
|||||||
|
|
||||||
class AnimLayersSettings(bpy.types.PropertyGroup):
|
class AnimLayersSettings(bpy.types.PropertyGroup):
|
||||||
turn_on: bpy.props.BoolProperty(name="Turn Animation Layers On", description="Turn on and start Animation Layers", default=False, options={'HIDDEN'}, update = anim_layers.turn_animlayers_on, override = {'LIBRARY_OVERRIDABLE'})
|
turn_on: bpy.props.BoolProperty(name="Turn Animation Layers On", description="Turn on and start Animation Layers", default=False, options={'HIDDEN'}, update = anim_layers.turn_animlayers_on, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
# Active row in obj.Anim_Layers. Post-migration, 1:1 with NLA-track index.
|
||||||
layer_index: bpy.props.IntProperty(update = anim_layers.update_layer_index, options={'LIBRARY_EDITABLE'}, default = 0, override = {'LIBRARY_OVERRIDABLE'})
|
layer_index: bpy.props.IntProperty(update = anim_layers.update_layer_index, options={'LIBRARY_EDITABLE'}, default = 0, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
# Schema version. 0 = pre-hierarchical (legacy GROUP rows); 1 = hierarchical (parent_layer refs).
|
||||||
|
schema_version: bpy.props.IntProperty(name="Schema Version", default=0, options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
linked: bpy.props.BoolProperty(name="Linked", description="Duplicate a layer with a linked action", default=False, options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
linked: bpy.props.BoolProperty(name="Linked", description="Duplicate a layer with a linked action", default=False, options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
|
||||||
#Bake settings
|
#Bake settings
|
||||||
@@ -132,6 +135,24 @@ class AnimLayersItems(bpy.types.PropertyGroup):
|
|||||||
offset: bpy.props.FloatProperty(name='Offset when the action starts', description="Offseting the whole layer animation", default = 0, precision = 2, override = {'LIBRARY_OVERRIDABLE'}, update = anim_layers.layer_offset)
|
offset: bpy.props.FloatProperty(name='Offset when the action starts', description="Offseting the whole layer animation", default = 0, precision = 2, override = {'LIBRARY_OVERRIDABLE'}, update = anim_layers.layer_offset)
|
||||||
repeat: bpy.props.FloatProperty(name="Repeat", description="Repeat the action", min = 0.1, default = 1, options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'}, update = anim_layers.layer_repeat)
|
repeat: bpy.props.FloatProperty(name="Repeat", description="Repeat the action", min = 0.1, default = 1, options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'}, update = anim_layers.layer_repeat)
|
||||||
|
|
||||||
|
# Hierarchical layer fields. Every layer is NLA-backed; a layer is a
|
||||||
|
# "group" iff something else points to it via parent_layer.
|
||||||
|
expanded: bpy.props.BoolProperty(name="Expanded", description="Show this layer's children in the UI list", default=True, options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
parent_layer: bpy.props.StringProperty(name="Parent Layer", description="Name of this layer's parent (empty = root)", default="", options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
group_color: bpy.props.FloatVectorProperty(name="Group Color", subtype='COLOR', size=4, min=0.0, max=1.0, default=(0.3, 0.5, 0.8, 1.0), options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
# Dynamic-enum dropdown for picking parent_layer in the UI. The setter
|
||||||
|
# refuses cycles (self + descendants are excluded from the options).
|
||||||
|
assigned_group: bpy.props.EnumProperty(name='Parent', description='Set this layer\'s parent (None = root)',
|
||||||
|
items=anim_layers.layer_group_enum_items, get=anim_layers.layer_group_get, set=anim_layers.layer_group_set,
|
||||||
|
options={'HIDDEN'})
|
||||||
|
# Legacy field for pre-migration data. Read by migrate_object_to_hierarchical
|
||||||
|
# and ignored thereafter. Schema retained so old .blend files load cleanly.
|
||||||
|
type: bpy.props.EnumProperty(name="Item Type (legacy)", default='LAYER',
|
||||||
|
items=[('LAYER', 'Layer', 'NLA-backed layer'),
|
||||||
|
('GROUP', 'Group', 'Legacy phantom group row')],
|
||||||
|
options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
parent_group: bpy.props.StringProperty(name="Parent Group (legacy)", description="Pre-migration field. Read once by the schema-v1 migration, then unused.", default="", options={'HIDDEN'}, override = {'LIBRARY_OVERRIDABLE'})
|
||||||
|
|
||||||
|
|
||||||
class AnimLayersObjects(bpy.types.PropertyGroup):
|
class AnimLayersObjects(bpy.types.PropertyGroup):
|
||||||
|
|
||||||
@@ -153,7 +174,6 @@ def update_panel(self, context):
|
|||||||
bpy.utils.unregister_class(panel)
|
bpy.utils.unregister_class(panel)
|
||||||
|
|
||||||
for panel in panels:
|
for panel in panels:
|
||||||
#print (panel.bl_category)
|
|
||||||
panel.bl_category = context.preferences.addons[__name__].preferences.category
|
panel.bl_category = context.preferences.addons[__name__].preferences.category
|
||||||
bpy.utils.register_class(panel)
|
bpy.utils.register_class(panel)
|
||||||
|
|
||||||
@@ -176,7 +196,8 @@ class AnimLayersAddonPreferences(bpy.types.AddonPreferences):
|
|||||||
items = [('ANIMLAYERS', 'Anim Layers Settings', 'Use Anim Layers properties to adjust custom frame range'),
|
items = [('ANIMLAYERS', 'Anim Layers Settings', 'Use Anim Layers properties to adjust custom frame range'),
|
||||||
('NLA', 'NLA Settings', 'Use the nla properties to adjust custom frame range')])
|
('NLA', 'NLA Settings', 'Use the nla properties to adjust custom frame range')])
|
||||||
|
|
||||||
lock_nlatracks: bpy.props.BoolProperty(name="Automatically lock the nla tracks for safety measures", description="Automatically lock nla tracks when creating layers for safety", default = True)
|
lock_nlatracks: bpy.props.BoolProperty(name="Automatically lock the NLA tracks", description="Automatically lock nla tracks when creating layers for safety", default = True)
|
||||||
|
auto_custom_range: bpy.props.BoolProperty(name="Switch automatically to custom frame range when editing NLA Strips", description="Automatically use custom frame range when adjusting NLA Strips manually", default = False)
|
||||||
|
|
||||||
#Property for ClearActiveAction
|
#Property for ClearActiveAction
|
||||||
proceed: bpy.props.EnumProperty(name="Choose how to proceed", description="Select an option how to proceed with Anim Layers", override = {'LIBRARY_OVERRIDABLE'},
|
proceed: bpy.props.EnumProperty(name="Choose how to proceed", description="Select an option how to proceed with Anim Layers", override = {'LIBRARY_OVERRIDABLE'},
|
||||||
@@ -260,8 +281,9 @@ class AnimLayersAddonPreferences(bpy.types.AddonPreferences):
|
|||||||
row.label(text = "Custom Frame Range Settings")
|
row.label(text = "Custom Frame Range Settings")
|
||||||
row.prop(self, "frame_range_settings", text = '')
|
row.prop(self, "frame_range_settings", text = '')
|
||||||
|
|
||||||
col.prop(self, "lock_nlatracks")
|
row = col.row()
|
||||||
|
row.prop(self, "auto_custom_range")
|
||||||
|
row.prop(self, "lock_nlatracks")
|
||||||
|
|
||||||
classes = (AnimLayersSettings, AnimLayersSceneSettings, AnimLayersItems, AnimLayersObjects)
|
classes = (AnimLayersSettings, AnimLayersSceneSettings, AnimLayersItems, AnimLayersObjects)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"last_check": "2026-04-06 14:46:59.741334",
|
"last_check": "2026-05-27 14:41:11.263249",
|
||||||
"backup_date": "March-27-2026",
|
"backup_date": "May-27-2026",
|
||||||
"update_ready": false,
|
"update_ready": false,
|
||||||
"ignore": false,
|
"ignore": false,
|
||||||
"just_restored": false,
|
"just_restored": false,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Animation Layers",
|
"name": "Animation Layers",
|
||||||
"author": "Tal Hershkovich",
|
"author": "Tal Hershkovich",
|
||||||
"version" : (2, 3, 7),
|
"version" : (2, 4, 0),
|
||||||
"blender" : (3, 2, 0),
|
"blender" : (3, 2, 0),
|
||||||
"location": "View3D - Properties - Animation Panel",
|
"location": "View3D - Properties - Animation Panel",
|
||||||
"description": "Simplifying the NLA editor into an animation layers UI and workflow",
|
"description": "Simplifying the NLA editor into an animation layers UI and workflow",
|
||||||
@@ -153,7 +153,6 @@ def update_panel(self, context):
|
|||||||
bpy.utils.unregister_class(panel)
|
bpy.utils.unregister_class(panel)
|
||||||
|
|
||||||
for panel in panels:
|
for panel in panels:
|
||||||
#print (panel.bl_category)
|
|
||||||
panel.bl_category = context.preferences.addons[__name__].preferences.category
|
panel.bl_category = context.preferences.addons[__name__].preferences.category
|
||||||
bpy.utils.register_class(panel)
|
bpy.utils.register_class(panel)
|
||||||
|
|
||||||
@@ -176,7 +175,8 @@ class AnimLayersAddonPreferences(bpy.types.AddonPreferences):
|
|||||||
items = [('ANIMLAYERS', 'Anim Layers Settings', 'Use Anim Layers properties to adjust custom frame range'),
|
items = [('ANIMLAYERS', 'Anim Layers Settings', 'Use Anim Layers properties to adjust custom frame range'),
|
||||||
('NLA', 'NLA Settings', 'Use the nla properties to adjust custom frame range')])
|
('NLA', 'NLA Settings', 'Use the nla properties to adjust custom frame range')])
|
||||||
|
|
||||||
lock_nlatracks: bpy.props.BoolProperty(name="Automatically lock the nla tracks for safety measures", description="Automatically lock nla tracks when creating layers for safety", default = True)
|
lock_nlatracks: bpy.props.BoolProperty(name="Automatically lock the NLA tracks", description="Automatically lock nla tracks when creating layers for safety", default = True)
|
||||||
|
auto_custom_range: bpy.props.BoolProperty(name="Switch automatically to custom frame range when editing NLA Strips", description="Automatically use custom frame range when adjusting NLA Strips manually", default = False)
|
||||||
|
|
||||||
#Property for ClearActiveAction
|
#Property for ClearActiveAction
|
||||||
proceed: bpy.props.EnumProperty(name="Choose how to proceed", description="Select an option how to proceed with Anim Layers", override = {'LIBRARY_OVERRIDABLE'},
|
proceed: bpy.props.EnumProperty(name="Choose how to proceed", description="Select an option how to proceed with Anim Layers", override = {'LIBRARY_OVERRIDABLE'},
|
||||||
@@ -260,8 +260,9 @@ class AnimLayersAddonPreferences(bpy.types.AddonPreferences):
|
|||||||
row.label(text = "Custom Frame Range Settings")
|
row.label(text = "Custom Frame Range Settings")
|
||||||
row.prop(self, "frame_range_settings", text = '')
|
row.prop(self, "frame_range_settings", text = '')
|
||||||
|
|
||||||
col.prop(self, "lock_nlatracks")
|
row = col.row()
|
||||||
|
row.prop(self, "auto_custom_range")
|
||||||
|
row.prop(self, "lock_nlatracks")
|
||||||
|
|
||||||
classes = (AnimLayersSettings, AnimLayersSceneSettings, AnimLayersItems, AnimLayersObjects)
|
classes = (AnimLayersSettings, AnimLayersSceneSettings, AnimLayersItems, AnimLayersObjects)
|
||||||
|
|
||||||
|
|||||||
@@ -271,7 +271,6 @@ def register_layers(obj, nla_tracks):
|
|||||||
continue
|
continue
|
||||||
strip = track.strips[0]
|
strip = track.strips[0]
|
||||||
use_animated_influence(strip)
|
use_animated_influence(strip)
|
||||||
strip.influence = 1
|
|
||||||
|
|
||||||
#updating the ui list with the nla track names
|
#updating the ui list with the nla track names
|
||||||
def visible_layers(obj, nla_tracks):
|
def visible_layers(obj, nla_tracks):
|
||||||
@@ -400,7 +399,7 @@ def get_fcu_layer_keyframes(obj, context, track):
|
|||||||
keyframes = []
|
keyframes = []
|
||||||
# fcurves = get_fcurves(track.strips[0].action)
|
# fcurves = get_fcurves(track.strips[0].action)
|
||||||
# fcurves = track.strips[0].action.fcurves
|
# fcurves = track.strips[0].action.fcurves
|
||||||
fcurves = get_fcurves(obj, track.strips[0].action)
|
fcurves = get_fcurves(obj, track.strips[0].action, obj.als.data_type)
|
||||||
#store all the keyframe locations from the fcurves of the layer
|
#store all the keyframe locations from the fcurves of the layer
|
||||||
for fcu in fcurves:
|
for fcu in fcurves:
|
||||||
if fcu.group is not None:
|
if fcu.group is not None:
|
||||||
@@ -1298,7 +1297,6 @@ def load_action(self, context):
|
|||||||
subscriptions.frameend_update_callback()
|
subscriptions.frameend_update_callback()
|
||||||
strip.use_sync_length = False
|
strip.use_sync_length = False
|
||||||
use_animated_influence(strip)
|
use_animated_influence(strip)
|
||||||
strip.influence = 1
|
|
||||||
return
|
return
|
||||||
subscriptions.subscriptions_remove()
|
subscriptions.subscriptions_remove()
|
||||||
strip = track.strips[0]
|
strip = track.strips[0]
|
||||||
@@ -1548,6 +1546,8 @@ def strip_action_recalc(self, strip):
|
|||||||
|
|
||||||
###################################################### HELPER FUNCTIONS ################################################
|
###################################################### HELPER FUNCTIONS ################################################
|
||||||
def redraw_areas(areas):
|
def redraw_areas(areas):
|
||||||
|
if not len(bpy.context.window_manager.windows):
|
||||||
|
return
|
||||||
for area in bpy.context.window_manager.windows[0].screen.areas:
|
for area in bpy.context.window_manager.windows[0].screen.areas:
|
||||||
if area.type in areas:
|
if area.type in areas:
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
@@ -1623,7 +1623,7 @@ def select_layer_bones(self, context):
|
|||||||
|
|
||||||
###################################################### CLASSES ###########################################################
|
###################################################### CLASSES ###########################################################
|
||||||
class SelectBonesInLayer(bpy.types.Operator):
|
class SelectBonesInLayer(bpy.types.Operator):
|
||||||
"""Select bones with keyframes in the current layer"""
|
"""Select bones with keyframes in the current layer, use shift to add to the current selection"""
|
||||||
bl_idname = "anim.bones_in_layer"
|
bl_idname = "anim.bones_in_layer"
|
||||||
bl_label = "Select layer bones"
|
bl_label = "Select layer bones"
|
||||||
bl_icon = "BONE_DATA"
|
bl_icon = "BONE_DATA"
|
||||||
@@ -1866,18 +1866,9 @@ class AutoCustomFrameRange(bpy.types.Operator):
|
|||||||
# return {'CANCELLED'}
|
# return {'CANCELLED'}
|
||||||
|
|
||||||
def restore(self, context):
|
def restore(self, context):
|
||||||
if hasattr(subscriptions, 'frame_range'):
|
print('restore')
|
||||||
frame_start, frame_end = subscriptions.frame_range
|
subscriptions.frameend_update_callback()
|
||||||
|
|
||||||
else:
|
|
||||||
frame_start, frame_end = subscriptions.get_frame_range(context.scene)
|
|
||||||
|
|
||||||
self.strip.repeat = 1 #change strip repeat but keep self.repeat value stored
|
|
||||||
self.strip.use_reverse = False
|
|
||||||
self.strip.frame_start = frame_start
|
|
||||||
self.strip.scale = self.layer.speed
|
|
||||||
self.strip.frame_end = frame_end
|
|
||||||
# update_action_frame_range(frame_start, frame_end, layer, strip)
|
|
||||||
subscriptions.subscriptions_add(context.scene)
|
subscriptions.subscriptions_add(context.scene)
|
||||||
|
|
||||||
def update_action_list(scene):
|
def update_action_list(scene):
|
||||||
@@ -1949,7 +1940,6 @@ def add_animlayer(layer_name = 'Anim_Layer' , duplicate = False, index = 1, blen
|
|||||||
new_strip.blend_type = blend_type
|
new_strip.blend_type = blend_type
|
||||||
new_strip.use_sync_length = False
|
new_strip.use_sync_length = False
|
||||||
use_animated_influence(new_strip)
|
use_animated_influence(new_strip)
|
||||||
new_strip.influence = 1
|
|
||||||
|
|
||||||
return new_track
|
return new_track
|
||||||
|
|
||||||
@@ -2599,9 +2589,7 @@ class RemoveFcurves(bpy.types.Operator):
|
|||||||
if mod.type == 'CYCLES':
|
if mod.type == 'CYCLES':
|
||||||
fcu.modifiers.remove(mod)
|
fcu.modifiers.remove(mod)
|
||||||
fcu.update()
|
fcu.update()
|
||||||
for area in context.window_manager.windows[0].screen.areas:
|
redraw_areas(['GRAPH_EDITOR', 'VIEW_3D'])
|
||||||
if area.type == 'GRAPH_EDITOR' or area.type == 'VIEW_3D':
|
|
||||||
area.tag_redraw()
|
|
||||||
break
|
break
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@@ -3304,25 +3292,36 @@ def copy_action(action):
|
|||||||
|
|
||||||
return new_action
|
return new_action
|
||||||
|
|
||||||
def get_obj_slot(obj, action, data_type = 'OBJECT'):
|
def get_obj_slot(obj, action, data_type = None):
|
||||||
'''Get the slot in the action that this object is using either it's object, or shapekeys'''
|
'''Get the slot in the action that this object is using either it's object, or shapekeys'''
|
||||||
|
|
||||||
|
if data_type is None:
|
||||||
|
data_type = obj.als.data_type
|
||||||
|
|
||||||
if not hasattr(action, 'slots'):
|
if not hasattr(action, 'slots'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not len(action.slots):
|
||||||
|
# If no slots exist, create one for the object and return it
|
||||||
|
slot = add_action_slot(obj, action)
|
||||||
|
return slot
|
||||||
|
|
||||||
|
# data_type = obj.als.data_type
|
||||||
for slot in action.slots:
|
for slot in action.slots:
|
||||||
if slot.target_id_type != data_type:
|
if slot.target_id_type != data_type:
|
||||||
continue
|
continue
|
||||||
# if obj.als.data_type == 'OBJECT' and obj in slot.users():
|
|
||||||
# return slot
|
|
||||||
if data_type == 'KEY' and obj.data.shape_keys in slot.users():
|
if data_type == 'KEY' and obj.data.shape_keys in slot.users():
|
||||||
return slot
|
return slot
|
||||||
elif obj in slot.users():
|
elif obj in slot.users():
|
||||||
return slot
|
return slot
|
||||||
|
|
||||||
return None
|
return add_action_slot(obj, action)
|
||||||
|
|
||||||
def get_fcurves(obj: bpy.types.Object, action: bpy.types.Action, data_type = 'OBJECT'):
|
def get_fcurves(obj: bpy.types.Object, action: bpy.types.Action, data_type = None):
|
||||||
|
|
||||||
|
if data_type is None:
|
||||||
|
data_type = obj.als.data_type
|
||||||
|
|
||||||
if hasattr(action, 'layers'):
|
if hasattr(action, 'layers'):
|
||||||
slot = get_obj_slot(obj, action, data_type)
|
slot = get_obj_slot(obj, action, data_type)
|
||||||
@@ -3338,10 +3337,13 @@ def get_fcurves(obj: bpy.types.Object, action: bpy.types.Action, data_type = 'OB
|
|||||||
return action.fcurves
|
return action.fcurves
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_channelbag(obj: bpy.types.Object, action: bpy.types.Action, data_type = 'OBJECT'):
|
def get_channelbag(obj: bpy.types.Object, action: bpy.types.Action, data_type = None):
|
||||||
'''Getting the container of the fcurves, either the action or channelbag
|
'''Getting the container of the fcurves, either the action or channelbag
|
||||||
Using this when adding a new group to the action'''
|
Using this when adding a new group to the action'''
|
||||||
|
|
||||||
|
if data_type is None:
|
||||||
|
data_type = obj.als.data_type
|
||||||
|
|
||||||
if hasattr(action, 'layers'):
|
if hasattr(action, 'layers'):
|
||||||
slot = get_obj_slot(obj, action, data_type)
|
slot = get_obj_slot(obj, action, data_type)
|
||||||
channelbag = None
|
channelbag = None
|
||||||
|
|||||||
+5
-5
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"last_check": "2026-03-27 11:33:07.238724",
|
"last_check": "2026-05-27 14:41:11.263249",
|
||||||
"backup_date": "March-20-2026",
|
"backup_date": "April-21-2026",
|
||||||
"update_ready": true,
|
"update_ready": true,
|
||||||
"ignore": false,
|
"ignore": false,
|
||||||
"just_restored": false,
|
"just_restored": false,
|
||||||
"just_updated": false,
|
"just_updated": false,
|
||||||
"version_text": {
|
"version_text": {
|
||||||
"link": "https://gitlab.com/api/v4/projects/22294607/repository/archive.zip?sha=eef950c6d5e620a8240db5c2a7b20955fe31df6f",
|
"link": "https://gitlab.com/api/v4/projects/22294607/repository/archive.zip?sha=321d411a449bc9acee2a759e30cd3d0f36bbd2ab",
|
||||||
"version": [
|
"version": [
|
||||||
2,
|
2,
|
||||||
3,
|
4,
|
||||||
8
|
1
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -645,6 +645,7 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
|
|||||||
baked_action = track.strips[0].action
|
baked_action = track.strips[0].action
|
||||||
clean_no_user_slots(baked_action)
|
clean_no_user_slots(baked_action)
|
||||||
#create the baked fcurve
|
#create the baked fcurve
|
||||||
|
# baked_channelbag = anim_layers.get_channelbag(obj, baked_action, obj.als.data_type)
|
||||||
baked_channelbag = anim_layers.get_channelbag(obj, baked_action)
|
baked_channelbag = anim_layers.get_channelbag(obj, baked_action)
|
||||||
baked_fcurves = baked_channelbag.fcurves
|
baked_fcurves = baked_channelbag.fcurves
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ def animlayers_frame(scene, context):
|
|||||||
scene['framerange_preview'] = scene.use_preview_range
|
scene['framerange_preview'] = scene.use_preview_range
|
||||||
frameend_update_callback()
|
frameend_update_callback()
|
||||||
return
|
return
|
||||||
|
|
||||||
frame_start, frame_end = bake_ops.frame_start_end(scene)
|
frame_start, frame_end = bake_ops.frame_start_end(scene)
|
||||||
# frame_start, frame_end = get_frame_range(scene)
|
# frame_start, frame_end = get_frame_range(scene)
|
||||||
reset_subscription = False
|
reset_subscription = False
|
||||||
@@ -106,7 +105,6 @@ def animlayers_frame(scene, context):
|
|||||||
for i, track in enumerate(nla_tracks):
|
for i, track in enumerate(nla_tracks):
|
||||||
if len(track.strips) != 1:
|
if len(track.strips) != 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#checks if the layer has a custom frame range
|
#checks if the layer has a custom frame range
|
||||||
layer = obj.Anim_Layers[i]
|
layer = obj.Anim_Layers[i]
|
||||||
if layer.custom_frame_range:
|
if layer.custom_frame_range:
|
||||||
@@ -127,6 +125,7 @@ def animlayers_frame(scene, context):
|
|||||||
if strip.frame_start < 0:
|
if strip.frame_start < 0:
|
||||||
strip.frame_start = 0
|
strip.frame_start = 0
|
||||||
anim_layers.update_action_frame_range(0, frame_end, layer, strip)
|
anim_layers.update_action_frame_range(0, frame_end, layer, strip)
|
||||||
|
return
|
||||||
anim_layers.update_action_frame_range(strip.frame_start, current + 10.0, layer, strip)
|
anim_layers.update_action_frame_range(strip.frame_start, current + 10.0, layer, strip)
|
||||||
strip.frame_end = current + 10.0
|
strip.frame_end = current + 10.0
|
||||||
|
|
||||||
@@ -231,6 +230,9 @@ def track_layer_synchronization(obj, nla_tracks):
|
|||||||
if obj.als.layer_index > len(obj.Anim_Layers)-1:
|
if obj.als.layer_index > len(obj.Anim_Layers)-1:
|
||||||
obj.als.layer_index = len(obj.Anim_Layers)-1
|
obj.als.layer_index = len(obj.Anim_Layers)-1
|
||||||
|
|
||||||
|
if not bpy.context.preferences.addons[__package__].preferences.auto_custom_range:
|
||||||
|
return
|
||||||
|
|
||||||
#update new layer with strip settings
|
#update new layer with strip settings
|
||||||
frame_start, frame_end = get_frame_range(bpy.context.scene)
|
frame_start, frame_end = get_frame_range(bpy.context.scene)
|
||||||
|
|
||||||
@@ -243,7 +245,6 @@ def track_layer_synchronization(obj, nla_tracks):
|
|||||||
continue
|
continue
|
||||||
if (strip.frame_start, strip.frame_end) != (frame_start, frame_end):
|
if (strip.frame_start, strip.frame_end) != (frame_start, frame_end):
|
||||||
subscriptions_remove()
|
subscriptions_remove()
|
||||||
# print(f'strip.frame_start {strip.frame_start} strip.frame_end {strip.frame_end} frame_start {frame_start} frame_end {frame_end}')
|
|
||||||
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -311,11 +312,16 @@ def sync_frame_range(scene, track, layer):
|
|||||||
return
|
return
|
||||||
|
|
||||||
#Turn on custom frame range if the current strip is not following the scene frame range
|
#Turn on custom frame range if the current strip is not following the scene frame range
|
||||||
|
# Should be activated when nla strips are edited manually in the nla editor, only when auto custom range is turned on, otherwise just update the strip frame range to the scene frame range
|
||||||
if (round(strip.frame_start, 2), round(strip.frame_end, 2)) != (round(frame_start, 2), round(frame_end, 2)):
|
if (round(strip.frame_start, 2), round(strip.frame_end, 2)) != (round(frame_start, 2), round(frame_end, 2)):
|
||||||
|
if bpy.context.preferences.addons[__package__].preferences.auto_custom_range:
|
||||||
subscriptions_remove()
|
subscriptions_remove()
|
||||||
# print('315 custom frame range')
|
# print('321 custom frame range')
|
||||||
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
frameend_update_callback()
|
||||||
|
return
|
||||||
|
|
||||||
def sync_strip_range(scene):
|
def sync_strip_range(scene):
|
||||||
'''Checking all the strips if a value was changed in the nla (not including UI changes)
|
'''Checking all the strips if a value was changed in the nla (not including UI changes)
|
||||||
@@ -356,7 +362,6 @@ def sync_strip_range(scene):
|
|||||||
if (strip_frame_start, round(strip_frame_end, 2)) != (frame_start, float(frame_end)):
|
if (strip_frame_start, round(strip_frame_end, 2)) != (frame_start, float(frame_end)):
|
||||||
subscriptions_remove()
|
subscriptions_remove()
|
||||||
# print('357 custom_frame_range_warning ')
|
# print('357 custom_frame_range_warning ')
|
||||||
# print(f'strip_frame_start {strip_frame_start} strip_frame_end {round(strip_frame_end, 2)} frame_start {frame_start} frame_end {float(frame_end)}')
|
|
||||||
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -567,7 +572,6 @@ def subscribe_to_preview_frame_end(scene):
|
|||||||
# Subscribing to preview frame end since it's not registering in the depsgraph
|
# Subscribing to preview frame end since it's not registering in the depsgraph
|
||||||
subscribe_preview_end = scene.path_resolve("frame_preview_end", False)
|
subscribe_preview_end = scene.path_resolve("frame_preview_end", False)
|
||||||
subscribe_use_preview = scene.path_resolve("use_preview_range", False)
|
subscribe_use_preview = scene.path_resolve("use_preview_range", False)
|
||||||
# print('subscribe_to_preview_frame_end')
|
|
||||||
for subscribe in [subscribe_preview_end, subscribe_use_preview]:
|
for subscribe in [subscribe_preview_end, subscribe_use_preview]:
|
||||||
|
|
||||||
bpy.msgbus.subscribe_rna(
|
bpy.msgbus.subscribe_rna(
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -183,7 +183,8 @@ def smart_bake(context):
|
|||||||
wm.progress_begin(0, total_iterations)
|
wm.progress_begin(0, total_iterations)
|
||||||
processed = 0
|
processed = 0
|
||||||
|
|
||||||
for layer, track in zip(obj.Anim_Layers, anim_data.nla_tracks):
|
layer_items = [l for l in obj.Anim_Layers if l.type == 'LAYER']
|
||||||
|
for layer, track in zip(layer_items, anim_data.nla_tracks):
|
||||||
if track.mute:
|
if track.mute:
|
||||||
continue
|
continue
|
||||||
if len(track.strips) != 1 or track.strips[0].action is None:
|
if len(track.strips) != 1 or track.strips[0].action is None:
|
||||||
@@ -244,7 +245,7 @@ def smart_bake(context):
|
|||||||
|
|
||||||
#if the strip is cutting with a different strip, then add keyframes in the cut
|
#if the strip is cutting with a different strip, then add keyframes in the cut
|
||||||
for layercut in obj.Anim_Layers:
|
for layercut in obj.Anim_Layers:
|
||||||
if layercut.mute or not layercut.custom_frame_range or layercut == layer:
|
if layercut.type == 'GROUP' or layercut.mute or not layercut.custom_frame_range or layercut == layer:
|
||||||
continue
|
continue
|
||||||
if strip_start < layercut.frame_start < strip_end:
|
if strip_start < layercut.frame_start < strip_end:
|
||||||
smartkeys = smart_start_end(smartkeys, (layercut.frame_start-1), strip.frame_end-1)
|
smartkeys = smart_start_end(smartkeys, (layercut.frame_start-1), strip.frame_end-1)
|
||||||
@@ -407,7 +408,7 @@ def unmute_modifiers(obj, nla_tracks, modifier_rec):
|
|||||||
for mod in fcu.modifiers:
|
for mod in fcu.modifiers:
|
||||||
if mod in modifier_rec:
|
if mod in modifier_rec:
|
||||||
mod.mute = False
|
mod.mute = False
|
||||||
elif obj.als.mergefcurves and track == nla_tracks[obj.als.layer_index]:
|
elif obj.als.mergefcurves and track == nla_tracks[anim_layers.nla_idx(obj)]:
|
||||||
mod.mute = True
|
mod.mute = True
|
||||||
|
|
||||||
def invisible_layers(b_layers):
|
def invisible_layers(b_layers):
|
||||||
@@ -426,7 +427,14 @@ def select_keyframed_bones(self, context, obj):
|
|||||||
if obj.mode != 'POSE':
|
if obj.mode != 'POSE':
|
||||||
bpy.ops.object.posemode_toggle()
|
bpy.ops.object.posemode_toggle()
|
||||||
bpy.ops.pose.select_all(action='DESELECT')
|
bpy.ops.pose.select_all(action='DESELECT')
|
||||||
for i in range(0, obj.als.layer_index+1):
|
# Iterate over LAYER rows up to (and including) the active row, skipping
|
||||||
|
# group headers (they have no NLA track and no bones to select).
|
||||||
|
current_row = obj.als.layer_index
|
||||||
|
for i, it in enumerate(obj.Anim_Layers):
|
||||||
|
if i > current_row:
|
||||||
|
break
|
||||||
|
if it.type != 'LAYER':
|
||||||
|
continue
|
||||||
obj.als['layer_index'] = i
|
obj.als['layer_index'] = i
|
||||||
anim_layers.select_layer_bones(self, context)
|
anim_layers.select_layer_bones(self, context)
|
||||||
|
|
||||||
@@ -446,7 +454,7 @@ def smartbake_apply(obj, nla_tracks, fcu_keys, extrapolations):
|
|||||||
#apply smartbake for blenders bake
|
#apply smartbake for blenders bake
|
||||||
#smart bake - delete unnecessery keyframes:
|
#smart bake - delete unnecessery keyframes:
|
||||||
# transform_types = ['location', 'rotation_euler', 'rotation_quaternion', 'scale']
|
# transform_types = ['location', 'rotation_euler', 'rotation_quaternion', 'scale']
|
||||||
strip = nla_tracks[obj.als.layer_index].strips[0]
|
strip = nla_tracks[anim_layers.nla_idx(obj)].strips[0]
|
||||||
# if strip.action is None:
|
# if strip.action is None:
|
||||||
# return
|
# return
|
||||||
|
|
||||||
@@ -641,10 +649,11 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
|
|||||||
return
|
return
|
||||||
anim_data = anim_layers.anim_data_type(obj)
|
anim_data = anim_layers.anim_data_type(obj)
|
||||||
# baked_action = anim_data.action
|
# baked_action = anim_data.action
|
||||||
track = nla_tracks[obj.als.layer_index]
|
track = nla_tracks[anim_layers.nla_idx(obj)]
|
||||||
baked_action = track.strips[0].action
|
baked_action = track.strips[0].action
|
||||||
clean_no_user_slots(baked_action)
|
clean_no_user_slots(baked_action)
|
||||||
#create the baked fcurve
|
#create the baked fcurve
|
||||||
|
# baked_channelbag = anim_layers.get_channelbag(obj, baked_action, obj.als.data_type)
|
||||||
baked_channelbag = anim_layers.get_channelbag(obj, baked_action)
|
baked_channelbag = anim_layers.get_channelbag(obj, baked_action)
|
||||||
baked_fcurves = baked_channelbag.fcurves
|
baked_fcurves = baked_channelbag.fcurves
|
||||||
|
|
||||||
@@ -1068,6 +1077,14 @@ class MergeAnimLayerDown(bpy.types.Operator):
|
|||||||
step: bpy.props.IntProperty(name='Step', description='Bake every number of frame steps', default=1)
|
step: bpy.props.IntProperty(name='Step', description='Bake every number of frame steps', default=1)
|
||||||
actioncopy: bpy.props.BoolProperty(name='Copy original merged action', description='Create a copy of the original action that is being overwritten', default = False)
|
actioncopy: bpy.props.BoolProperty(name='Copy original merged action', description='Create a copy of the original action that is being overwritten', default = False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
obj = context.object
|
||||||
|
if obj is None:
|
||||||
|
return False
|
||||||
|
# Disable when active row is a group header — merge only applies to NLA-backed layers.
|
||||||
|
return anim_layers.is_layer_row_active(obj)
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
obj = context.object
|
obj = context.object
|
||||||
bake_range_type(context.scene.als, context)
|
bake_range_type(context.scene.als, context)
|
||||||
@@ -1142,7 +1159,8 @@ class MergeAnimLayerDown(bpy.types.Operator):
|
|||||||
|
|
||||||
# Incase the strips are shorter then the keyframe range (because scene is shorter)
|
# Incase the strips are shorter then the keyframe range (because scene is shorter)
|
||||||
# Then updating the strips length
|
# Then updating the strips length
|
||||||
for layer, track in zip(obj.Anim_Layers, anim_data.nla_tracks):
|
layer_items = [l for l in obj.Anim_Layers if l.type == 'LAYER']
|
||||||
|
for layer, track in zip(layer_items, anim_data.nla_tracks):
|
||||||
if layer.custom_frame_range:
|
if layer.custom_frame_range:
|
||||||
continue
|
continue
|
||||||
if len(track.strips) != 1:
|
if len(track.strips) != 1:
|
||||||
@@ -1180,7 +1198,7 @@ class MergeAnimLayerDown(bpy.types.Operator):
|
|||||||
if obj.als.direction == 'DOWN':
|
if obj.als.direction == 'DOWN':
|
||||||
obj.als.layer_index = 0
|
obj.als.layer_index = 0
|
||||||
baked_layer = None
|
baked_layer = None
|
||||||
strip = anim_data.nla_tracks[obj.als.layer_index].strips[0]
|
strip = anim_data.nla_tracks[anim_layers.nla_idx(obj)].strips[0]
|
||||||
action = strip.action
|
action = strip.action
|
||||||
if hasattr(strip, 'action_slot'):
|
if hasattr(strip, 'action_slot'):
|
||||||
action_slot = strip.action_slot
|
action_slot = strip.action_slot
|
||||||
@@ -1189,21 +1207,29 @@ class MergeAnimLayerDown(bpy.types.Operator):
|
|||||||
#if baking to a new layer then setup the new index and layer
|
#if baking to a new layer then setup the new index and layer
|
||||||
elif obj.als.operator == 'NEW':
|
elif obj.als.operator == 'NEW':
|
||||||
self.actioncopy = False
|
self.actioncopy = False
|
||||||
|
# `add_at_nla` is the NLA-track index passed to add_animlayer.
|
||||||
if obj.als.direction == 'UP' and additive and 'REPLACE' in blendings:
|
if obj.als.direction == 'UP' and additive and 'REPLACE' in blendings:
|
||||||
obj.als.layer_index = layer_index + blendings.index('REPLACE') - 1
|
add_at_nla = layer_index + blendings.index('REPLACE') - 1
|
||||||
elif obj.als.direction == 'UP' or obj.als.direction == 'ALL':
|
elif obj.als.direction == 'UP' or obj.als.direction == 'ALL':
|
||||||
obj.als.layer_index = len(obj.Anim_Layers)-1
|
add_at_nla = anim_layers.nla_layer_count(obj) - 1
|
||||||
|
else:
|
||||||
|
add_at_nla = anim_layers.nla_idx(obj)
|
||||||
|
|
||||||
layer_names = [layer.name for layer in obj.Anim_Layers]
|
layer_names = [layer.name for layer in obj.Anim_Layers if layer.type == 'LAYER']
|
||||||
baked_layer = anim_layers.add_animlayer(layer_name = anim_layers.unique_name(layer_names, 'Baked_Layer') , duplicate = False, index = obj.als.layer_index, blend_type = blend)
|
baked_layer = anim_layers.add_animlayer(layer_name = anim_layers.unique_name(layer_names, 'Baked_Layer') , duplicate = False, index = add_at_nla, blend_type = blend)
|
||||||
anim_layers.register_layers(obj, nla_tracks)
|
anim_layers.register_layers(obj, nla_tracks)
|
||||||
|
|
||||||
obj.als.layer_index += 1
|
# Point layer_index at the newly-added baked layer's collection row.
|
||||||
|
if baked_layer is not None:
|
||||||
|
for ridx, it in enumerate(obj.Anim_Layers):
|
||||||
|
if it.type == 'LAYER' and it.name == baked_layer.name:
|
||||||
|
obj.als.layer_index = ridx
|
||||||
|
break
|
||||||
|
|
||||||
#remove subsciption again after adding a layer there was new subsciption applied
|
#remove subsciption again after adding a layer there was new subsciption applied
|
||||||
subscriptions.subscriptions_remove()
|
subscriptions.subscriptions_remove()
|
||||||
|
|
||||||
track = nla_tracks[obj.als.layer_index]
|
track = nla_tracks[anim_layers.nla_idx(obj)]
|
||||||
#use internal bake
|
#use internal bake
|
||||||
if obj.als.baketype =='NLA':
|
if obj.als.baketype =='NLA':
|
||||||
modifier_rec, extrapolations = mute_modifiers(obj, nla_tracks)
|
modifier_rec, extrapolations = mute_modifiers(obj, nla_tracks)
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ def animlayers_frame(scene, context):
|
|||||||
scene['framerange_preview'] = scene.use_preview_range
|
scene['framerange_preview'] = scene.use_preview_range
|
||||||
frameend_update_callback()
|
frameend_update_callback()
|
||||||
return
|
return
|
||||||
|
|
||||||
frame_start, frame_end = bake_ops.frame_start_end(scene)
|
frame_start, frame_end = bake_ops.frame_start_end(scene)
|
||||||
# frame_start, frame_end = get_frame_range(scene)
|
# frame_start, frame_end = get_frame_range(scene)
|
||||||
reset_subscription = False
|
reset_subscription = False
|
||||||
@@ -106,9 +105,11 @@ def animlayers_frame(scene, context):
|
|||||||
for i, track in enumerate(nla_tracks):
|
for i, track in enumerate(nla_tracks):
|
||||||
if len(track.strips) != 1:
|
if len(track.strips) != 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#checks if the layer has a custom frame range
|
#checks if the layer has a custom frame range
|
||||||
layer = obj.Anim_Layers[i]
|
row_idx = anim_layers.layer_to_row_index(obj, i)
|
||||||
|
if row_idx < 0 or row_idx >= len(obj.Anim_Layers):
|
||||||
|
continue
|
||||||
|
layer = obj.Anim_Layers[row_idx]
|
||||||
if layer.custom_frame_range:
|
if layer.custom_frame_range:
|
||||||
continue
|
continue
|
||||||
if not reset_subscription:
|
if not reset_subscription:
|
||||||
@@ -127,6 +128,7 @@ def animlayers_frame(scene, context):
|
|||||||
if strip.frame_start < 0:
|
if strip.frame_start < 0:
|
||||||
strip.frame_start = 0
|
strip.frame_start = 0
|
||||||
anim_layers.update_action_frame_range(0, frame_end, layer, strip)
|
anim_layers.update_action_frame_range(0, frame_end, layer, strip)
|
||||||
|
return
|
||||||
anim_layers.update_action_frame_range(strip.frame_start, current + 10.0, layer, strip)
|
anim_layers.update_action_frame_range(strip.frame_start, current + 10.0, layer, strip)
|
||||||
strip.frame_end = current + 10.0
|
strip.frame_end = current + 10.0
|
||||||
|
|
||||||
@@ -170,6 +172,10 @@ def check_handler(scene):
|
|||||||
return
|
return
|
||||||
anim_layers.add_obj_to_animlayers(obj, [item.object for item in scene.AL_objects])
|
anim_layers.add_obj_to_animlayers(obj, [item.object for item in scene.AL_objects])
|
||||||
nla_tracks = anim_data.nla_tracks
|
nla_tracks = anim_data.nla_tracks
|
||||||
|
# When the active UIList row is a group header (no NLA track of its own),
|
||||||
|
# skip the LAYER-specific syncs below — they assume a real layer.
|
||||||
|
if not anim_layers.is_layer_row_active(obj):
|
||||||
|
return
|
||||||
layer = obj.Anim_Layers[obj.als.layer_index]
|
layer = obj.Anim_Layers[obj.als.layer_index]
|
||||||
active_action_update(obj, anim_data, nla_tracks)
|
active_action_update(obj, anim_data, nla_tracks)
|
||||||
#check if a keyframe was removed
|
#check if a keyframe was removed
|
||||||
@@ -190,7 +196,7 @@ def check_handler(scene):
|
|||||||
if track_layer_synchronization(obj, nla_tracks):
|
if track_layer_synchronization(obj, nla_tracks):
|
||||||
return
|
return
|
||||||
|
|
||||||
track = nla_tracks[obj.als.layer_index]
|
track = nla_tracks[anim_layers.nla_idx(obj)]
|
||||||
|
|
||||||
sync_frame_range(scene, track, layer)
|
sync_frame_range(scene, track, layer)
|
||||||
# sync_strip_range(scene)
|
# sync_strip_range(scene)
|
||||||
@@ -218,18 +224,23 @@ def check_handler(scene):
|
|||||||
anim_layers.hide_view_all_keyframes(obj, anim_data)
|
anim_layers.hide_view_all_keyframes(obj, anim_data)
|
||||||
check_selected_bones(obj)
|
check_selected_bones(obj)
|
||||||
|
|
||||||
influence_check(nla_tracks[obj.als.layer_index])
|
influence_check(nla_tracks[anim_layers.nla_idx(obj)])
|
||||||
|
|
||||||
def track_layer_synchronization(obj, nla_tracks):
|
def track_layer_synchronization(obj, nla_tracks):
|
||||||
'''check if track and layers are synchronized, running only when adding/removing tracks via the nla'''
|
'''check if track and layers are synchronized, running only when adding/removing tracks via the nla'''
|
||||||
|
|
||||||
if len(nla_tracks) == len(obj.Anim_Layers):
|
if len(nla_tracks) == anim_layers.nla_layer_count(obj):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
new_layers_names = set(track.name for track in nla_tracks).difference(set(layer.name for layer in obj.Anim_Layers))
|
layer_items = [layer for layer in obj.Anim_Layers if layer.type == 'LAYER']
|
||||||
|
new_layers_names = set(track.name for track in nla_tracks).difference(set(layer.name for layer in layer_items))
|
||||||
anim_layers.visible_layers(obj, nla_tracks)
|
anim_layers.visible_layers(obj, nla_tracks)
|
||||||
if obj.als.layer_index > len(obj.Anim_Layers)-1:
|
row_count = len(obj.Anim_Layers)
|
||||||
obj.als.layer_index = len(obj.Anim_Layers)-1
|
if row_count and obj.als.layer_index > row_count - 1:
|
||||||
|
obj.als.layer_index = row_count - 1
|
||||||
|
|
||||||
|
if not bpy.context.preferences.addons[__package__].preferences.auto_custom_range:
|
||||||
|
return
|
||||||
|
|
||||||
#update new layer with strip settings
|
#update new layer with strip settings
|
||||||
frame_start, frame_end = get_frame_range(bpy.context.scene)
|
frame_start, frame_end = get_frame_range(bpy.context.scene)
|
||||||
@@ -243,7 +254,6 @@ def track_layer_synchronization(obj, nla_tracks):
|
|||||||
continue
|
continue
|
||||||
if (strip.frame_start, strip.frame_end) != (frame_start, frame_end):
|
if (strip.frame_start, strip.frame_end) != (frame_start, frame_end):
|
||||||
subscriptions_remove()
|
subscriptions_remove()
|
||||||
# print(f'strip.frame_start {strip.frame_start} strip.frame_end {strip.frame_end} frame_start {frame_start} frame_end {frame_end}')
|
|
||||||
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -260,9 +270,9 @@ def active_action_update(obj, anim_data, nla_tracks):
|
|||||||
anim_data.action = None
|
anim_data.action = None
|
||||||
subscriptions_add(bpy.context.scene)
|
subscriptions_add(bpy.context.scene)
|
||||||
return
|
return
|
||||||
if anim_data.action == nla_tracks[obj.als.layer_index].strips[0].action:
|
if anim_data.action == nla_tracks[anim_layers.nla_idx(obj)].strips[0].action:
|
||||||
return
|
return
|
||||||
if not len(nla_tracks[obj.als.layer_index].strips):
|
if not len(nla_tracks[anim_layers.nla_idx(obj)].strips):
|
||||||
return
|
return
|
||||||
if not anim_data.action or anim_data.is_property_readonly('action'):
|
if not anim_data.action or anim_data.is_property_readonly('action'):
|
||||||
return
|
return
|
||||||
@@ -311,11 +321,16 @@ def sync_frame_range(scene, track, layer):
|
|||||||
return
|
return
|
||||||
|
|
||||||
#Turn on custom frame range if the current strip is not following the scene frame range
|
#Turn on custom frame range if the current strip is not following the scene frame range
|
||||||
|
# Should be activated when nla strips are edited manually in the nla editor, only when auto custom range is turned on, otherwise just update the strip frame range to the scene frame range
|
||||||
if (round(strip.frame_start, 2), round(strip.frame_end, 2)) != (round(frame_start, 2), round(frame_end, 2)):
|
if (round(strip.frame_start, 2), round(strip.frame_end, 2)) != (round(frame_start, 2), round(frame_end, 2)):
|
||||||
|
if bpy.context.preferences.addons[__package__].preferences.auto_custom_range:
|
||||||
subscriptions_remove()
|
subscriptions_remove()
|
||||||
# print('315 custom frame range')
|
# print('321 custom frame range')
|
||||||
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
frameend_update_callback()
|
||||||
|
return
|
||||||
|
|
||||||
def sync_strip_range(scene):
|
def sync_strip_range(scene):
|
||||||
'''Checking all the strips if a value was changed in the nla (not including UI changes)
|
'''Checking all the strips if a value was changed in the nla (not including UI changes)
|
||||||
@@ -356,7 +371,6 @@ def sync_strip_range(scene):
|
|||||||
if (strip_frame_start, round(strip_frame_end, 2)) != (frame_start, float(frame_end)):
|
if (strip_frame_start, round(strip_frame_end, 2)) != (frame_start, float(frame_end)):
|
||||||
subscriptions_remove()
|
subscriptions_remove()
|
||||||
# print('357 custom_frame_range_warning ')
|
# print('357 custom_frame_range_warning ')
|
||||||
# print(f'strip_frame_start {strip_frame_start} strip_frame_end {round(strip_frame_end, 2)} frame_start {frame_start} frame_end {float(frame_end)}')
|
|
||||||
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -429,7 +443,7 @@ def influence_sync(scene, obj, nla_tracks):
|
|||||||
if action.name == scene.name + 'Action' and not len(scene.animation_data.nla_tracks) and not len(fcurves):
|
if action.name == scene.name + 'Action' and not len(scene.animation_data.nla_tracks) and not len(fcurves):
|
||||||
bpy.data.actions.remove(action)
|
bpy.data.actions.remove(action)
|
||||||
|
|
||||||
strip = nla_tracks[obj.als.layer_index].strips[0]
|
strip = nla_tracks[anim_layers.nla_idx(obj)].strips[0]
|
||||||
if strip.fcurves[0].mute:
|
if strip.fcurves[0].mute:
|
||||||
return
|
return
|
||||||
strip.fcurves[0].lock = False
|
strip.fcurves[0].lock = False
|
||||||
@@ -541,9 +555,10 @@ def frameend_update_callback():
|
|||||||
for anim_data in anim_datas:
|
for anim_data in anim_datas:
|
||||||
if anim_data is None:
|
if anim_data is None:
|
||||||
continue
|
continue
|
||||||
if len(anim_data.nla_tracks) != len(obj.Anim_Layers):
|
if len(anim_data.nla_tracks) != anim_layers.nla_layer_count(obj):
|
||||||
continue
|
continue
|
||||||
for layer, track in zip(obj.Anim_Layers, anim_data.nla_tracks):
|
layer_items = [l for l in obj.Anim_Layers if l.type == 'LAYER']
|
||||||
|
for layer, track in zip(layer_items, anim_data.nla_tracks):
|
||||||
if layer.custom_frame_range:
|
if layer.custom_frame_range:
|
||||||
continue
|
continue
|
||||||
if len(track.strips) != 1:
|
if len(track.strips) != 1:
|
||||||
@@ -567,7 +582,6 @@ def subscribe_to_preview_frame_end(scene):
|
|||||||
# Subscribing to preview frame end since it's not registering in the depsgraph
|
# Subscribing to preview frame end since it's not registering in the depsgraph
|
||||||
subscribe_preview_end = scene.path_resolve("frame_preview_end", False)
|
subscribe_preview_end = scene.path_resolve("frame_preview_end", False)
|
||||||
subscribe_use_preview = scene.path_resolve("use_preview_range", False)
|
subscribe_use_preview = scene.path_resolve("use_preview_range", False)
|
||||||
# print('subscribe_to_preview_frame_end')
|
|
||||||
for subscribe in [subscribe_preview_end, subscribe_use_preview]:
|
for subscribe in [subscribe_preview_end, subscribe_use_preview]:
|
||||||
|
|
||||||
bpy.msgbus.subscribe_rna(
|
bpy.msgbus.subscribe_rna(
|
||||||
@@ -649,10 +663,12 @@ def action_name_callback():
|
|||||||
nla_tracks = anim_data.nla_tracks
|
nla_tracks = anim_data.nla_tracks
|
||||||
if not len(nla_tracks):
|
if not len(nla_tracks):
|
||||||
return
|
return
|
||||||
layer = obj.Anim_Layers[obj.als.layer_index]
|
if not anim_layers.is_layer_row_active(obj):
|
||||||
if not len(nla_tracks[obj.als.layer_index].strips):
|
|
||||||
return
|
return
|
||||||
action = nla_tracks[obj.als.layer_index].strips[0].action
|
layer = obj.Anim_Layers[obj.als.layer_index]
|
||||||
|
if not len(nla_tracks[anim_layers.nla_idx(obj)].strips):
|
||||||
|
return
|
||||||
|
action = nla_tracks[anim_layers.nla_idx(obj)].strips[0].action
|
||||||
if action is None:
|
if action is None:
|
||||||
return
|
return
|
||||||
if not obj.als.auto_rename or layer.name == action.name:
|
if not obj.als.auto_rename or layer.name == action.name:
|
||||||
@@ -770,10 +786,10 @@ def slot_update_callback():
|
|||||||
if not len(obj.Anim_Layers):
|
if not len(obj.Anim_Layers):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not len(anim_data.nla_tracks[obj.als.layer_index].strips):
|
if not len(anim_data.nla_tracks[anim_layers.nla_idx(obj)].strips):
|
||||||
return
|
return
|
||||||
|
|
||||||
strip = anim_data.nla_tracks[obj.als.layer_index].strips[0]
|
strip = anim_data.nla_tracks[anim_layers.nla_idx(obj)].strips[0]
|
||||||
anim_data.action_slot = strip.action_slot
|
anim_data.action_slot = strip.action_slot
|
||||||
|
|
||||||
|
|
||||||
@@ -844,9 +860,11 @@ def strip_settings_callback():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# sync_strip_range()
|
# sync_strip_range()
|
||||||
if not len(anim_data.nla_tracks[obj.als.layer_index].strips):
|
if not anim_layers.is_layer_row_active(obj):
|
||||||
return
|
return
|
||||||
strip = anim_data.nla_tracks[obj.als.layer_index].strips[0]
|
if not len(anim_data.nla_tracks[anim_layers.nla_idx(obj)].strips):
|
||||||
|
return
|
||||||
|
strip = anim_data.nla_tracks[anim_layers.nla_idx(obj)].strips[0]
|
||||||
layer = obj.Anim_Layers[obj.als.layer_index]
|
layer = obj.Anim_Layers[obj.als.layer_index]
|
||||||
|
|
||||||
update_strip_layer_settings(strip, layer)
|
update_strip_layer_settings(strip, layer)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ def draw_wgt(scale, bone, shape = 'sphere'):
|
|||||||
shape = shape.lower()
|
shape = shape.lower()
|
||||||
|
|
||||||
mesh.from_pydata(np.array(shapes[shape]['vertices'])*scale , shapes[shape]['edges'], shapes[shape]['faces'])
|
mesh.from_pydata(np.array(shapes[shape]['vertices'])*scale , shapes[shape]['edges'], shapes[shape]['faces'])
|
||||||
|
# print('draw shape scale ', scale)
|
||||||
shape_obj['WGT_TempCtrl'] = True
|
shape_obj['WGT_TempCtrl'] = True
|
||||||
return shape_obj
|
return shape_obj
|
||||||
|
|
||||||
@@ -205,27 +206,26 @@ def tempctrl_shape_type(self, context):
|
|||||||
ctrl.custom_shape_rotation_euler = (0, 0, 0)
|
ctrl.custom_shape_rotation_euler = (0, 0, 0)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if org_bone.custom_shape_transform is not None:# and ctrl.custom_shape_transform is None:
|
if org_bone.custom_shape_transform is not None and ctrl.custom_shape_transform is None:
|
||||||
#check if the transform bone shape already exists
|
#check if the transform bone shape already exists
|
||||||
transform_bonename = org_bone.custom_shape_transform.name
|
transform_bonename = org_bone.custom_shape_transform.name
|
||||||
if transform_bonename in ctrl.id_data.pose.bones:
|
if transform_bonename in ctrl.id_data.pose.bones:
|
||||||
# If it already exists then find it
|
|
||||||
ctrl.custom_shape_transform = ctrl.id_data.pose.bones[transform_bonename]
|
ctrl.custom_shape_transform = ctrl.id_data.pose.bones[transform_bonename]
|
||||||
else:
|
continue
|
||||||
#add an extra transform bone, if it doesnt exist
|
#add an extra transform bone, if it doesnt exist
|
||||||
|
rig = ctrl.id_data
|
||||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
bpy.ops.object.mode_set(mode = 'EDIT')
|
||||||
boneshape = add_ctrl_bone(rig, org_bone.custom_shape_transform, rig.data.edit_bones[ctrl.name].parent, '')
|
boneshape = add_ctrl_bone(rig, org_bone.custom_shape_transform, rig.data.edit_bones[ctrl.name].parent, '')
|
||||||
transform_bonename = boneshape.name
|
bone_name = boneshape.name
|
||||||
add_bone_to_collection(rig, boneshape)
|
add_bone_to_collection(rig, boneshape)
|
||||||
bpy.ops.object.mode_set(mode = 'POSE')
|
bpy.ops.object.mode_set(mode = 'POSE')
|
||||||
|
posebone = rig.pose.bones[bone_name]
|
||||||
rig = ctrl.id_data
|
|
||||||
posebone = rig.pose.bones[transform_bonename]
|
|
||||||
constraint_add(posebone, org_bone.custom_shape_transform, 'COPY_TRANSFORMS')
|
constraint_add(posebone, org_bone.custom_shape_transform, 'COPY_TRANSFORMS')
|
||||||
ctrl.custom_shape_transform = posebone
|
ctrl.custom_shape_transform = posebone
|
||||||
else:
|
else:
|
||||||
# scale = (length_avg / ctrl.length)*0.4 + 0.4
|
# scale = (length_avg / ctrl.length)*0.4 + 0.4
|
||||||
scale = 1
|
scale = 1
|
||||||
|
# print('drawing shape in scale of ', scale)
|
||||||
ctrl.custom_shape = draw_wgt(scale, ctrl, shape = self.shape_type)
|
ctrl.custom_shape = draw_wgt(scale, ctrl, shape = self.shape_type)
|
||||||
ctrl.custom_shape_scale_xyz = tuple([self.shape_size]*3)
|
ctrl.custom_shape_scale_xyz = tuple([self.shape_size]*3)
|
||||||
ctrl.custom_shape_transform = None
|
ctrl.custom_shape_transform = None
|
||||||
@@ -1466,11 +1466,6 @@ def smartbake_to_ik(context, posebones, chain, sb):
|
|||||||
|
|
||||||
#create the fcurves and add them to smartfcurves
|
#create the fcurves and add them to smartfcurves
|
||||||
for ctrl in ctrls:
|
for ctrl in ctrls:
|
||||||
if ctrl == chain.ik_tip and ctrl != chain.ik_ctrl:
|
|
||||||
continue
|
|
||||||
# if chain.pole_bone and ctrl == chain.base_bone:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
ctrl_action = ctrl.id_data.animation_data.action
|
ctrl_action = ctrl.id_data.animation_data.action
|
||||||
path = ctrl.path_from_id()
|
path = ctrl.path_from_id()
|
||||||
rot = Tools.rot_mode_to_channel(ctrl.rotation_mode)
|
rot = Tools.rot_mode_to_channel(ctrl.rotation_mode)
|
||||||
@@ -1909,7 +1904,7 @@ def smartbake_write_keyframes(scene, smartframes, smartfcus, chain = None, bake_
|
|||||||
#Store the influence and set them to 0 before calculating the matrix without the constraint (to get the offset)
|
#Store the influence and set them to 0 before calculating the matrix without the constraint (to get the offset)
|
||||||
con_influence = get_con_influence(constrained)
|
con_influence = get_con_influence(constrained)
|
||||||
|
|
||||||
if chain and chain.pole_bone is not None:
|
if chain:
|
||||||
# Adding the pole bone to the end of the list
|
# Adding the pole bone to the end of the list
|
||||||
bones_matrices.update({chain.pole_bone : None})
|
bones_matrices.update({chain.pole_bone : None})
|
||||||
bones_matrices[chain.pole_bone] = bones_matrices.pop(chain.pole_bone)
|
bones_matrices[chain.pole_bone] = bones_matrices.pop(chain.pole_bone)
|
||||||
@@ -1932,20 +1927,8 @@ def smartbake_write_keyframes(scene, smartframes, smartfcus, chain = None, bake_
|
|||||||
|
|
||||||
# Calculating pole target matrix after other bones were calcluated
|
# Calculating pole target matrix after other bones were calcluated
|
||||||
if chain and bone == chain.pole_bone:
|
if chain and bone == chain.pole_bone:
|
||||||
base_bone = chain.base_bone
|
|
||||||
ik_tip = chain.ik_tip
|
|
||||||
angle = chain.base_bone.vector.angle(chain.ik_tip.vector)
|
|
||||||
|
|
||||||
if not round(angle):
|
|
||||||
# continue
|
|
||||||
# If the angle is flat then use the position of the pole relative to the rest position base bone
|
|
||||||
relative_matrix = base_bone.bone.matrix_local.inverted() @ chain.pole_bone.bone.matrix_local
|
|
||||||
matrix = base_bone.matrix @ relative_matrix
|
|
||||||
# print(frame, 'angle is 0 using base bone matrix')
|
|
||||||
|
|
||||||
else:
|
|
||||||
bpy.context.view_layer.update()
|
bpy.context.view_layer.update()
|
||||||
matrix = find_pole_vector(base_bone, ik_tip, chain.pole_bone, chain.step)
|
matrix = find_pole_vector(chain.base_bone, chain.ik_tip, chain.pole_bone, chain.step)
|
||||||
|
|
||||||
Tools.paste_bone_matrix(bone, matrix, constrained, bones, x_filter = False)
|
Tools.paste_bone_matrix(bone, matrix, constrained, bones, x_filter = False)
|
||||||
pasted_bones.add(bone)
|
pasted_bones.add(bone)
|
||||||
@@ -4193,7 +4176,6 @@ def assign_setup_ids(self, context, ctrls, selected, child_ctrls, setup, setup_i
|
|||||||
|
|
||||||
#get custom shape and assign the matrix
|
#get custom shape and assign the matrix
|
||||||
if bone.custom_shape_transform and self.shape_type == 'ORIGINAL':
|
if bone.custom_shape_transform and self.shape_type == 'ORIGINAL':
|
||||||
obj_mat = bone.id_data.matrix_world
|
|
||||||
ot_bone = bone.custom_shape_transform.name
|
ot_bone = bone.custom_shape_transform.name
|
||||||
#Get the original override transform bone
|
#Get the original override transform bone
|
||||||
target = bone.id_data.pose.bones[ot_bone]
|
target = bone.id_data.pose.bones[ot_bone]
|
||||||
@@ -5328,16 +5310,14 @@ def pole_prop_edit(self, context):
|
|||||||
else:
|
else:
|
||||||
add_bone_to_collection(rig, rig.data.edit_bones[chain.base_bone.name], col_name = 'IK Ctrls', visible = True)
|
add_bone_to_collection(rig, rig.data.edit_bones[chain.base_bone.name], col_name = 'IK Ctrls', visible = True)
|
||||||
#remove the pole bone and switch to base bone
|
#remove the pole bone and switch to base bone
|
||||||
if chain.pole_bone is None:
|
if not hasattr(chain, 'pole_bone'):
|
||||||
continue
|
continue
|
||||||
rig.data.edit_bones.remove(rig.data.edit_bones[chain.pole_bone_name])
|
rig.data.edit_bones.remove(rig.data.edit_bones[chain.pole_bone_name])
|
||||||
#remove from ctrls and append base bone instead
|
#remove from ctrls and append base bone instead
|
||||||
if chain.pole_bone in ctrls:
|
if chain.pole_bone in ctrls:
|
||||||
ctrls.remove(chain.pole_bone)
|
ctrls.remove(chain.pole_bone)
|
||||||
ctrls.append(chain.base_bone)
|
ctrls.append(chain.base_bone)
|
||||||
|
del chain.pole_bone, chain.pole_bone_name
|
||||||
chain.pole_bone = chain.pole_bone_name = None
|
|
||||||
# del chain.pole_bone, chain.pole_bone_name
|
|
||||||
|
|
||||||
#Remove child ctrls
|
#Remove child ctrls
|
||||||
if btc.child:
|
if btc.child:
|
||||||
@@ -5350,17 +5330,13 @@ def pole_prop_pose(self, context):
|
|||||||
if not btc.pole_target:
|
if not btc.pole_target:
|
||||||
chain.base_bone.btc.org = 'CTRL'
|
chain.base_bone.btc.org = 'CTRL'
|
||||||
|
|
||||||
# if not hasattr(chain, 'pole_bone'):
|
if not hasattr(chain, 'pole_bone'):
|
||||||
# continue
|
|
||||||
if not chain.pole_bone:
|
|
||||||
continue
|
continue
|
||||||
if not chain.pole_bone_name:
|
|
||||||
|
del chain.pole_bone
|
||||||
|
if hasattr(chain,'pole_bone_name'):
|
||||||
|
chain.pole_bone_name
|
||||||
continue
|
continue
|
||||||
chain.pole_bone = chain.pole_bone_name = None
|
|
||||||
# del chain.pole_bone
|
|
||||||
# if hasattr(chain,'pole_bone_name'):
|
|
||||||
# chain.pole_bone_name
|
|
||||||
# continue
|
|
||||||
|
|
||||||
pole_posebone_update(chain, ctrls)
|
pole_posebone_update(chain, ctrls)
|
||||||
if chain.base_bone in ctrls:
|
if chain.base_bone in ctrls:
|
||||||
@@ -5437,9 +5413,7 @@ def ik_ctrl_orientation(self, context):
|
|||||||
|
|
||||||
def pole_posebone_update(chain, ctrls):
|
def pole_posebone_update(chain, ctrls):
|
||||||
'''update pole bone properties in the pole prop and add ik prop'''
|
'''update pole bone properties in the pole prop and add ik prop'''
|
||||||
# if not hasattr(chain, 'pole_bone_name'):
|
if not hasattr(chain, 'pole_bone_name'):
|
||||||
# return
|
|
||||||
if not chain.pole_bone_name:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
chain.pole_bone = rig.pose.bones[chain.pole_bone_name]
|
chain.pole_bone = rig.pose.bones[chain.pole_bone_name]
|
||||||
@@ -5473,8 +5447,6 @@ def update_axis_prop(self, context):
|
|||||||
|
|
||||||
if not hasattr(chain, 'pole_bone_name'):
|
if not hasattr(chain, 'pole_bone_name'):
|
||||||
continue
|
continue
|
||||||
if not chain.pole_bone_name:
|
|
||||||
continue
|
|
||||||
pole_matrix = find_pole_vector(base_bone, ik_tip, ik_tip, chain.step)
|
pole_matrix = find_pole_vector(base_bone, ik_tip, ik_tip, chain.step)
|
||||||
|
|
||||||
#pole matrix orientation to world by default
|
#pole matrix orientation to world by default
|
||||||
@@ -5579,6 +5551,15 @@ def add_pole_bone(self, context, rig, chain):
|
|||||||
new_rot = mathutils.Euler((0, 0, 0), 'XYZ')
|
new_rot = mathutils.Euler((0, 0, 0), 'XYZ')
|
||||||
pole_matrix = Matrix.LocRotScale(loc, new_rot, scale)
|
pole_matrix = Matrix.LocRotScale(loc, new_rot, scale)
|
||||||
|
|
||||||
|
#In case of a flat IK skip adding a pole bone and use base bone instead
|
||||||
|
# if pole_matrix.translation == chain.ik_tip.matrix.translation:
|
||||||
|
# print('no pole bone')
|
||||||
|
# self.report({'ERROR'}, "Can't add Pole Ctrl because of a flat IK chain")
|
||||||
|
# chain.pole_bone = None
|
||||||
|
# add_bone_to_collection(rig, chain.base_bone, col_name = 'IK Ctrls', visible = True)
|
||||||
|
# btc['pole_target'] = False
|
||||||
|
# return
|
||||||
|
|
||||||
pole_bone_name = chain.org_bones[-2].name + '_Pole' if len(chain.org_bones) > 1 else chain.org_bones[0].name + '_Pole'
|
pole_bone_name = chain.org_bones[-2].name + '_Pole' if len(chain.org_bones) > 1 else chain.org_bones[0].name + '_Pole'
|
||||||
chain.pole_bone = rig.data.edit_bones.new(pole_bone_name)
|
chain.pole_bone = rig.data.edit_bones.new(pole_bone_name)
|
||||||
|
|
||||||
@@ -5601,9 +5582,7 @@ def pole_offset(self, context):
|
|||||||
global ik_chains, ctrls, child_names
|
global ik_chains, ctrls, child_names
|
||||||
|
|
||||||
for chain in ik_chains:
|
for chain in ik_chains:
|
||||||
# if not hasattr(chain, 'pole_bone_name'):
|
if not hasattr(chain, 'pole_bone_name'):
|
||||||
# continue
|
|
||||||
if not chain.pole_bone_name:
|
|
||||||
continue
|
continue
|
||||||
chain.pole_bone = rig.pose.bones[chain.pole_bone_name]
|
chain.pole_bone = rig.pose.bones[chain.pole_bone_name]
|
||||||
|
|
||||||
@@ -5642,7 +5621,7 @@ def add_ik_prop_edit(self, context):
|
|||||||
chain.ik_tip_name = chain.ik_tip.name
|
chain.ik_tip_name = chain.ik_tip.name
|
||||||
|
|
||||||
#remove the pole bone
|
#remove the pole bone
|
||||||
if btc.pole_target and chain.pole_bone_name:
|
if btc.pole_target and hasattr(chain, 'pole_bone_name'):
|
||||||
#removing and adding the pole_target without calling the whole pole prop update
|
#removing and adding the pole_target without calling the whole pole prop update
|
||||||
ctrls.remove(chain.pole_bone)
|
ctrls.remove(chain.pole_bone)
|
||||||
rig.data.edit_bones.remove(rig.data.edit_bones[chain.pole_bone_name])
|
rig.data.edit_bones.remove(rig.data.edit_bones[chain.pole_bone_name])
|
||||||
@@ -5675,7 +5654,7 @@ def add_ik_prop_pose(self, context):
|
|||||||
chain.ik_ctrl.btc.org = 'CTRL'
|
chain.ik_ctrl.btc.org = 'CTRL'
|
||||||
|
|
||||||
chain.ik_ctrl.color.palette = context.scene.btc.color_set
|
chain.ik_ctrl.color.palette = context.scene.btc.color_set
|
||||||
if btc.pole_target and chain.pole_bone_name: #hasattr(chain, 'pole_bone_name'):
|
if btc.pole_target and hasattr(chain, 'pole_bone_name'):
|
||||||
pole_posebone_update(chain, ctrls)
|
pole_posebone_update(chain, ctrls)
|
||||||
|
|
||||||
add_bone_to_collection(rig, chain.ik_ctrl, col_name = 'IK Ctrls', visible = True)
|
add_bone_to_collection(rig, chain.ik_ctrl, col_name = 'IK Ctrls', visible = True)
|
||||||
@@ -5812,7 +5791,7 @@ class TempIK(bpy.types.Operator):
|
|||||||
for i, ctrl in enumerate(ctrls[:-1]):
|
for i, ctrl in enumerate(ctrls[:-1]):
|
||||||
ctrls[i+1].tail = ctrl.head
|
ctrls[i+1].tail = ctrl.head
|
||||||
context.view_layer.update()
|
context.view_layer.update()
|
||||||
# return {'FINISHED'}
|
|
||||||
switch_layers(rig, chain.ik_tip, [31])
|
switch_layers(rig, chain.ik_tip, [31])
|
||||||
add_bone_to_collection(rig, chain.ik_tip)
|
add_bone_to_collection(rig, chain.ik_tip)
|
||||||
add_bone_to_collection(rig, chain.ik_ctrl, col_name = 'IK Ctrls', visible = True)
|
add_bone_to_collection(rig, chain.ik_ctrl, col_name = 'IK Ctrls', visible = True)
|
||||||
@@ -5846,6 +5825,7 @@ class TempIK(bpy.types.Operator):
|
|||||||
####################################################################
|
####################################################################
|
||||||
bpy.ops.object.mode_set(mode = 'POSE')
|
bpy.ops.object.mode_set(mode = 'POSE')
|
||||||
|
|
||||||
|
|
||||||
setup_ids = set()
|
setup_ids = set()
|
||||||
|
|
||||||
if btc.root:
|
if btc.root:
|
||||||
@@ -5878,22 +5858,20 @@ class TempIK(bpy.types.Operator):
|
|||||||
# #assign the matrix
|
# #assign the matrix
|
||||||
distance = (bone.id_data.matrix_world @ bone.bone.matrix_local).inverted() @ ctrl.bone.matrix_local.copy()
|
distance = (bone.id_data.matrix_world @ bone.bone.matrix_local).inverted() @ ctrl.bone.matrix_local.copy()
|
||||||
ctrl.matrix = bone.id_data.matrix_world @ bone.matrix @ distance
|
ctrl.matrix = bone.id_data.matrix_world @ bone.matrix @ distance
|
||||||
# context.view_layer.update()
|
|
||||||
ctrl.color.palette = btc.color_set
|
ctrl.color.palette = btc.color_set
|
||||||
|
|
||||||
add_bone_setup_id(chain.ik_ctrl, False, setup, 'CTRL', setup_id, org_id = chain.ik_ctrl.btc.org_id)
|
add_bone_setup_id(chain.ik_ctrl, False, setup, 'CTRL', setup_id, org_id = chain.ik_ctrl.btc.org_id)
|
||||||
|
|
||||||
|
|
||||||
if add_ik_ctrl:
|
if add_ik_ctrl:
|
||||||
add_ik_prop_pose(self, context)
|
add_ik_prop_pose(self, context)
|
||||||
|
|
||||||
context.view_layer.update()
|
context.view_layer.update()
|
||||||
pole_prop_pose(self, context)
|
pole_prop_pose(self, context)
|
||||||
|
|
||||||
# child_prop_pose(context)
|
# child_prop_pose(context)
|
||||||
if context.scene.btc.child:
|
if context.scene.btc.child:
|
||||||
child_prop(context.scene.btc, context)
|
child_prop(context.scene.btc, context)
|
||||||
|
# return {'FINISHED'}
|
||||||
self.ik_chains = ik_chains
|
self.ik_chains = ik_chains
|
||||||
tempctrl_shape_type(self, context)
|
tempctrl_shape_type(self, context)
|
||||||
|
|
||||||
@@ -5974,7 +5952,7 @@ class TempIK(bpy.types.Operator):
|
|||||||
rig.data.edit_bones[ctrl.name].parent = rig.data.edit_bones[chain.ctrls[i+1].name]
|
rig.data.edit_bones[ctrl.name].parent = rig.data.edit_bones[chain.ctrls[i+1].name]
|
||||||
|
|
||||||
#updating the polebone position with the offset
|
#updating the polebone position with the offset
|
||||||
if btc.pole_target and chain.pole_bone_name: #hasattr(chain, 'pole_bone_name'):
|
if btc.pole_target and hasattr(chain, 'pole_bone_name'):
|
||||||
pole_bone = rig.data.edit_bones[chain.pole_bone_name]
|
pole_bone = rig.data.edit_bones[chain.pole_bone_name]
|
||||||
base_bone = rig.data.edit_bones[chain.base_bone_name]
|
base_bone = rig.data.edit_bones[chain.base_bone_name]
|
||||||
ik_tip = rig.data.edit_bones[chain.ik_tip_name]
|
ik_tip = rig.data.edit_bones[chain.ik_tip_name]
|
||||||
@@ -6103,7 +6081,6 @@ class TempIK(bpy.types.Operator):
|
|||||||
#add the ik constraint to the ctrls
|
#add the ik constraint to the ctrls
|
||||||
ik_con = constraint_add(chain.ik_tip, chain.ik_ctrl if not btc.child else chain.ik_child_ctrl, 'IK')
|
ik_con = constraint_add(chain.ik_tip, chain.ik_ctrl if not btc.child else chain.ik_child_ctrl, 'IK')
|
||||||
|
|
||||||
if chain.pole_bone:
|
|
||||||
chain.pole_angle = get_pole_angle(chain.base_bone, chain.ik_tip, chain.pole_bone.matrix.translation)
|
chain.pole_angle = get_pole_angle(chain.base_bone, chain.ik_tip, chain.pole_bone.matrix.translation)
|
||||||
|
|
||||||
ik_con.chain_count = chain.length(btc.add_ik_ctrl)
|
ik_con.chain_count = chain.length(btc.add_ik_ctrl)
|
||||||
@@ -6339,8 +6316,6 @@ class IK_Chain:
|
|||||||
self.ik_ctrl_name = self.ik_ctrl.name
|
self.ik_ctrl_name = self.ik_ctrl.name
|
||||||
self.base_bone_name = self.base_bone.name
|
self.base_bone_name = self.base_bone.name
|
||||||
self.ik_tip_name = self.ik_tip.name
|
self.ik_tip_name = self.ik_tip.name
|
||||||
self.pole_bone = None
|
|
||||||
self.pole_bone_name = None
|
|
||||||
|
|
||||||
self.step = get_step(hierarchy[0].id_data)
|
self.step = get_step(hierarchy[0].id_data)
|
||||||
|
|
||||||
@@ -6362,7 +6337,7 @@ class IK_Chain:
|
|||||||
self.parent = rig.pose.bones[self.parent_name]
|
self.parent = rig.pose.bones[self.parent_name]
|
||||||
if hasattr(self, 'root_name'):
|
if hasattr(self, 'root_name'):
|
||||||
self.root_ctrl = rig.pose.bones[self.root_name]
|
self.root_ctrl = rig.pose.bones[self.root_name]
|
||||||
if self.pole_bone_name:
|
if hasattr(self, 'pole_bone_name'):
|
||||||
self.pole_bone = rig.pose.bones[self.pole_bone_name]
|
self.pole_bone = rig.pose.bones[self.pole_bone_name]
|
||||||
# if hasattr(self, 'pole_bone_ref_name'):
|
# if hasattr(self, 'pole_bone_ref_name'):
|
||||||
# self.pole_bone_ref = rig.pose.bones[self.pole_bone_ref_name]
|
# self.pole_bone_ref = rig.pose.bones[self.pole_bone_ref_name]
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "AnimToolBox",
|
"name": "AnimToolBox",
|
||||||
"author": "Tal Hershkovich",
|
"author": "Tal Hershkovich",
|
||||||
"version" : (0, 2, 3),
|
"version" : (0, 2, 0),
|
||||||
"blender" : (3, 2, 0),
|
"blender" : (3, 2, 0),
|
||||||
"location": "View3D - Properties - Animation Panel",
|
"location": "View3D - Properties - Animation Panel",
|
||||||
"description": "A set of animation tools",
|
"description": "A set of animation tools",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"last_check": "2026-02-09 15:54:54.419194",
|
"last_check": "",
|
||||||
"backup_date": "February-9-2026",
|
"backup_date": "",
|
||||||
"update_ready": false,
|
"update_ready": false,
|
||||||
"ignore": false,
|
"ignore": false,
|
||||||
"just_restored": false,
|
"just_restored": false,
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ***** END GPL LICENCE BLOCK *****
|
|
||||||
|
|
||||||
import bpy
|
|
||||||
|
|
||||||
class GizmoSizeUp(bpy.types.Operator):
|
|
||||||
"""Share keyframes between all the selected objects and bones"""
|
|
||||||
bl_idname = "view3d.gizmo_size_up"
|
|
||||||
bl_label = "Gizmo_Size_Up"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
context.preferences.view.gizmo_size += context.scene.animtoolbox.gizmo_size
|
|
||||||
return {'PASS_THROUGH'}
|
|
||||||
|
|
||||||
class GizmoSizeDown(bpy.types.Operator):
|
|
||||||
"""Share keyframes between all the selected objects and bones"""
|
|
||||||
bl_idname = "view3d.gizmo_size_down"
|
|
||||||
bl_label = "Gizmo_Size_Down"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
context.preferences.view.gizmo_size -= context.scene.animtoolbox.gizmo_size
|
|
||||||
return {'PASS_THROUGH'}
|
|
||||||
|
|
||||||
########################################################################################################################
|
|
||||||
|
|
||||||
def clear_isolate_pose_mode(scene):
|
|
||||||
if not len(scene.animtoolbox.isolated):
|
|
||||||
return
|
|
||||||
for obj in scene.animtoolbox.isolated:
|
|
||||||
if not obj.hidden:
|
|
||||||
continue
|
|
||||||
obj.hidden.hide_set(False)
|
|
||||||
scene.animtoolbox.isolated.clear()
|
|
||||||
scene.animtoolbox.active_obj = None
|
|
||||||
|
|
||||||
def isolate_pose_mode(scene):
|
|
||||||
context = bpy.context
|
|
||||||
#return when going out of isolate pose or when active object is not in pose mode
|
|
||||||
if not scene.animtoolbox.isolate_pose_mode or context.active_object.mode != 'POSE':
|
|
||||||
clear_isolate_pose_mode(scene)
|
|
||||||
return
|
|
||||||
|
|
||||||
#handler continue only if the active object is None otherwise it collects all armature objects
|
|
||||||
if scene.animtoolbox.active_obj is None:
|
|
||||||
scene.animtoolbox.active_obj = context.active_object
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
isolated = scene.animtoolbox.isolated
|
|
||||||
for obj in context.view_layer.objects:
|
|
||||||
if obj.type != 'ARMATURE':
|
|
||||||
continue
|
|
||||||
if obj.hide_get():
|
|
||||||
continue
|
|
||||||
rig = isolated.add()
|
|
||||||
if obj.mode == 'POSE':
|
|
||||||
rig.selected = obj
|
|
||||||
else:
|
|
||||||
rig.hidden = obj
|
|
||||||
obj.hide_set(True)
|
|
||||||
|
|
||||||
class IsolatePoseMode(bpy.types.Operator):
|
|
||||||
"""Isolates armatures during pose mode"""
|
|
||||||
bl_idname = "anim.isolate_pose_mode"
|
|
||||||
bl_label = "Isolate Pose Mode"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
|
|
||||||
# If the modal is already running, then don't run it the second time
|
|
||||||
scene = context.scene
|
|
||||||
if scene.animtoolbox.isolate_pose_mode:
|
|
||||||
if isolate_pose_mode in bpy.app.handlers.depsgraph_update_pre:
|
|
||||||
clear_isolate_pose_mode(scene)
|
|
||||||
bpy.app.handlers.depsgraph_update_pre.remove(isolate_pose_mode)
|
|
||||||
scene.animtoolbox.isolate_pose_mode = False
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
scene.animtoolbox.isolate_pose_mode = True
|
|
||||||
isolate_pose_mode(scene)
|
|
||||||
if isolate_pose_mode not in bpy.app.handlers.depsgraph_update_pre:
|
|
||||||
bpy.app.handlers.depsgraph_update_pre.append(isolate_pose_mode)
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
class SwitchBoneCollectionsVisibility(bpy.types.Operator):
|
|
||||||
"""Turn all bone collections visible and then press again to switch back"""
|
|
||||||
bl_idname = "anim.switch_collections_visibility"
|
|
||||||
bl_label = "Bone Collections Visibility"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return bpy.app.version >= (4, 0, 0)
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
obj = context.object
|
|
||||||
if obj.type != 'ARMATURE':
|
|
||||||
return {'CANCELLED'}
|
|
||||||
if not obj.animation_data:
|
|
||||||
self.report({'INFO'}, 'No animation is available')
|
|
||||||
return {'CANCELLED'}
|
|
||||||
|
|
||||||
if not obj.animation_data.action:
|
|
||||||
self.report({'INFO'}, 'No animation is available')
|
|
||||||
return {'CANCELLED'}
|
|
||||||
|
|
||||||
collections = obj.data.collections
|
|
||||||
|
|
||||||
if not len(collections):
|
|
||||||
self.report({'INFO'}, 'No collections are available')
|
|
||||||
return {'CANCELLED'}
|
|
||||||
#check if there are collections that are marked with
|
|
||||||
tagged_col = ['atb' in col.keys() for col in collections]
|
|
||||||
atb_ui = context.scene.animtoolbox
|
|
||||||
|
|
||||||
if any(tagged_col) and atb_ui.col_vis:
|
|
||||||
#collections are already marked so return to previous collection visibilty
|
|
||||||
for col in collections:
|
|
||||||
if 'atb' in col.keys():
|
|
||||||
col.is_visible = col['atb']
|
|
||||||
del col['atb']
|
|
||||||
atb_ui.col_vis = False
|
|
||||||
else:
|
|
||||||
#Mark visible collections and turn collections with animated bones on
|
|
||||||
animated_bones = set()
|
|
||||||
start = 'pose.bones["'
|
|
||||||
end = '"]'
|
|
||||||
#get all the animated bones from the fcurves
|
|
||||||
for fcu in obj.animation_data.action.fcurves:
|
|
||||||
start_index = fcu.data_path.find(start)
|
|
||||||
end_index = fcu.data_path.find(end)
|
|
||||||
#if it's not a posebone fcurve then skip
|
|
||||||
if start_index == -1 or end_index == -1:
|
|
||||||
continue
|
|
||||||
animated_bones.add(fcu.data_path[start_index + len(start):end_index])
|
|
||||||
|
|
||||||
#check if the collecetion that is turned off has animated bones
|
|
||||||
find_anim = []
|
|
||||||
for col in collections:
|
|
||||||
for bone in col.bones:
|
|
||||||
if bone.name in animated_bones and not col.is_visible:
|
|
||||||
# print(bone.name, 'in ', col.name)
|
|
||||||
find_anim.append(col)
|
|
||||||
break
|
|
||||||
|
|
||||||
if not find_anim:
|
|
||||||
self.report({'INFO'}, 'No collections with animated bones and no visibility are found')
|
|
||||||
return {'CANCELLED'}
|
|
||||||
|
|
||||||
#Turn on collections without visiblity
|
|
||||||
for col in collections:
|
|
||||||
if col in find_anim:
|
|
||||||
#tag visibility
|
|
||||||
col['atb'] = col.is_visible
|
|
||||||
col.is_visible = True
|
|
||||||
|
|
||||||
atb_ui.col_vis = True
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
classes = (GizmoSizeUp, GizmoSizeDown, IsolatePoseMode, SwitchBoneCollectionsVisibility)
|
|
||||||
|
|
||||||
def register():
|
|
||||||
from bpy.utils import register_class
|
|
||||||
for cls in classes:
|
|
||||||
register_class(cls)
|
|
||||||
|
|
||||||
def unregister():
|
|
||||||
from bpy.utils import unregister_class
|
|
||||||
for cls in classes:
|
|
||||||
unregister_class(cls)
|
|
||||||
@@ -1,549 +0,0 @@
|
|||||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ***** END GPL LICENCE BLOCK *****
|
|
||||||
|
|
||||||
import bpy
|
|
||||||
from mathutils import Matrix, Vector
|
|
||||||
from math import radians
|
|
||||||
import numpy
|
|
||||||
|
|
||||||
def draw_wgt(boneLength, bone):
|
|
||||||
suffix = bone.id_data.name + '_' + bone.name
|
|
||||||
if 'WGTB_object' + suffix in bpy.data.objects:
|
|
||||||
obj = bpy.data.objects['WGTB_object'] + suffix
|
|
||||||
if 'WGTB_shape' + suffix in obj.data.name:
|
|
||||||
return obj
|
|
||||||
mesh = bpy.data.meshes.new('WGTB_shape_' + suffix)
|
|
||||||
obj = bpy.data.objects.new('WGTB_object_' + suffix, mesh)
|
|
||||||
#coordinates of the sphere widget shape
|
|
||||||
sphere = {"edges": [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11], [11, 12], [12, 13], [13, 14], [14, 15], [15, 16], [16, 17], [17, 18], [18, 19], [19, 20], [20, 21], [21, 22], [22, 23], [0, 23], [24, 25], [25, 26], [26, 27], [27, 28], [28, 29], [29, 30], [30, 31], [31, 32], [32, 33], [33, 34], [34, 35], [35, 36], [36, 37], [37, 38], [38, 39], [39, 40], [40, 41], [41, 42], [42, 43], [43, 44], [44, 45], [45, 46], [46, 47], [24, 47], [48, 49], [49, 50], [50, 51], [51, 52], [52, 53], [53, 54], [54, 55], [55, 56], [56, 57], [57, 58], [58, 59], [59, 60], [60, 61], [61, 62], [62, 63], [63, 64], [64, 65], [65, 66], [66, 67], [67, 68], [68, 69], [69, 70], [70, 71], [48, 71]],
|
|
||||||
"vertices": [[0.0, 0.10000002384185791, 0.0], [-0.025881901383399963, 0.09659260511398315, 0.0], [-0.050000011920928955, 0.08660250902175903, 0.0], [-0.07071065902709961, 0.07071065902709961, 0.0], [-0.08660256862640381, 0.04999998211860657, 0.0], [-0.09659260511398315, 0.025881901383399963, 0.0], [-0.10000002384185791, 7.549793679118011e-09, 0.0], [-0.09659260511398315, -0.02588188648223877, 0.0], [-0.08660256862640381, -0.04999998211860657, 0.0], [-0.07071071863174438, -0.07071065902709961, 0.0], [-0.050000011920928955, -0.08660250902175903, 0.0], [-0.02588193118572235, -0.09659260511398315, 0.0], [-3.894143674187944e-08, -0.10000002384185791, 0.0], [0.025881856679916382, -0.09659260511398315, 0.0], [0.04999995231628418, -0.08660256862640381, 0.0], [0.07071065902709961, -0.07071071863174438, 0.0], [0.08660250902175903, -0.05000004172325134, 0.0], [0.09659254550933838, -0.025881946086883545, 0.0], [0.10000002384185791, -4.649123752642481e-08, 0.0], [0.09659260511398315, 0.025881856679916382, 0.0], [0.08660256862640381, 0.04999995231628418, 0.0], [0.07071071863174438, 0.07071065902709961, 0.0], [0.05000007152557373, 0.08660250902175903, 0.0], [0.025881975889205933, 0.09659254550933838, 0.0], [0.0, 7.450580596923828e-09, 0.10000002384185791], [-0.025881901383399963, 7.450580596923828e-09, 0.09659260511398315], [-0.050000011920928955, 7.450580596923828e-09, 0.08660250902175903], [-0.07071065902709961, 7.450580596923828e-09, 0.07071065902709961], [-0.08660256862640381, 3.725290298461914e-09, 0.04999998211860657], [-0.09659260511398315, 1.862645149230957e-09, 0.025881901383399963], [-0.10000002384185791, 8.881784197001252e-16, 7.549793679118011e-09], [-0.09659260511398315, -1.862645149230957e-09, -0.02588188648223877], [-0.08660256862640381, -3.725290298461914e-09, -0.04999998211860657], [-0.07071071863174438, -7.450580596923828e-09, -0.07071065902709961], [-0.050000011920928955, -7.450580596923828e-09, -0.08660250902175903], [-0.02588193118572235, -7.450580596923828e-09, -0.09659260511398315], [-3.894143674187944e-08, -7.450580596923828e-09, -0.10000002384185791], [0.025881856679916382, -7.450580596923828e-09, -0.09659260511398315], [0.04999995231628418, -7.450580596923828e-09, -0.08660256862640381], [0.07071065902709961, -7.450580596923828e-09, -0.07071071863174438], [0.08660250902175903, -3.725290298461914e-09, -0.05000004172325134], [0.09659254550933838, -1.862645149230957e-09, -0.025881946086883545], [0.10000002384185791, -3.552713678800501e-15, -4.649123752642481e-08], [0.09659260511398315, 1.862645149230957e-09, 0.025881856679916382], [0.08660256862640381, 3.725290298461914e-09, 0.04999995231628418], [0.07071071863174438, 7.450580596923828e-09, 0.07071065902709961], [0.05000007152557373, 7.450580596923828e-09, 0.08660250902175903], [0.025881975889205933, 7.450580596923828e-09, 0.09659254550933838], [-7.450580596923828e-09, 4.440892098500626e-16, 0.10000002384185791], [-9.313225746154785e-09, -0.025881901383399963, 0.09659260511398315], [-1.1175870895385742e-08, -0.050000011920928955, 0.08660250902175903], [-1.4901161193847656e-08, -0.07071065902709961, 0.07071065902709961], [-7.450580596923828e-09, -0.08660256862640381, 0.04999998211860657], [-7.450580596923828e-09, -0.09659260511398315, 0.025881901383399963], [-7.450580596923828e-09, -0.10000002384185791, 7.549793679118011e-09], [-7.450580596923828e-09, -0.09659260511398315, -0.02588188648223877], [0.0, -0.08660256862640381, -0.04999998211860657], [0.0, -0.07071071863174438, -0.07071065902709961], [3.725290298461914e-09, -0.050000011920928955, -0.08660250902175903], [5.587935447692871e-09, -0.02588193118572235, -0.09659260511398315], [7.450577044210149e-09, -3.894143674187944e-08, -0.10000002384185791], [9.313225746154785e-09, 0.025881856679916382, -0.09659260511398315], [1.1175870895385742e-08, 0.04999995231628418, -0.08660256862640381], [1.4901161193847656e-08, 0.07071065902709961, -0.07071071863174438], [7.450580596923828e-09, 0.08660250902175903, -0.05000004172325134], [7.450580596923828e-09, 0.09659254550933838, -0.025881946086883545], [7.450580596923828e-09, 0.10000002384185791, -4.649123752642481e-08], [7.450580596923828e-09, 0.09659260511398315, 0.025881856679916382], [0.0, 0.08660256862640381, 0.04999995231628418], [0.0, 0.07071071863174438, 0.07071065902709961], [-3.725290298461914e-09, 0.05000007152557373, 0.08660250902175903], [-5.587935447692871e-09, 0.025881975889205933, 0.09659254550933838]], "faces": []}
|
|
||||||
mesh.from_pydata(numpy.array(sphere['vertices'])*[boneLength, boneLength, boneLength] , sphere['edges'], sphere['faces'])
|
|
||||||
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def add_driver(obj, posebone, control, target, path, multiply = ''):
|
|
||||||
|
|
||||||
if isinstance(target, tuple):
|
|
||||||
attr = posebone.driver_add(target[0], target[1])
|
|
||||||
else:
|
|
||||||
attr = posebone.driver_add(target)
|
|
||||||
|
|
||||||
var = attr.driver.variables.new()
|
|
||||||
|
|
||||||
var.targets[0].id = obj
|
|
||||||
var.targets[0].data_path = 'pose.bones["' + control +'"].'+ path
|
|
||||||
attr.driver.expression = var.name + multiply
|
|
||||||
|
|
||||||
def dup_values(source, target):
|
|
||||||
if hasattr(source, 'parent'):
|
|
||||||
target.parent = source.parent
|
|
||||||
for prop in dir(source):
|
|
||||||
if not hasattr(target, prop):
|
|
||||||
continue
|
|
||||||
value = getattr(source, prop)
|
|
||||||
if type(value) not in {int, float, bool, str, Vector, Matrix, bpy.types.Object}:
|
|
||||||
continue
|
|
||||||
if '__' in prop[:2] and '__' in prop[-2:]:
|
|
||||||
continue
|
|
||||||
if target.is_property_readonly(prop):
|
|
||||||
continue
|
|
||||||
setattr(target, prop, value)
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
def dup_constraints(source, target):
|
|
||||||
if not source.constraints.items():
|
|
||||||
return
|
|
||||||
for source_con in source.constraints:
|
|
||||||
target_con = target.constraints.new(source_con.type)
|
|
||||||
dup_values(source_con, target_con)
|
|
||||||
|
|
||||||
def add_vis_bone_con(obj, bone_vis_name, bone_wgt_name):
|
|
||||||
bone_vis = obj.pose.bones[bone_vis_name]
|
|
||||||
con = bone_vis.constraints.new('STRETCH_TO')
|
|
||||||
con.target = obj
|
|
||||||
con.subtarget = bone_wgt_name
|
|
||||||
|
|
||||||
return bone_vis
|
|
||||||
|
|
||||||
class target:
|
|
||||||
def __init__(self, bone):
|
|
||||||
self.name = bone.name
|
|
||||||
self.point = tuple(bone.tail)
|
|
||||||
self.ctrl = 'TRGT_' + bone.name
|
|
||||||
if bone.parent:
|
|
||||||
self.parent = bone.parent.name
|
|
||||||
#print('assign parent to target ', self.name, self.ctrl, self.parent)
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
return self.point < other.point
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(self.point)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
#if not isinstance(other, type(self)):
|
|
||||||
# return NotImplemented
|
|
||||||
return self.point == other.point
|
|
||||||
|
|
||||||
class parent:
|
|
||||||
def __init__(self, bone):
|
|
||||||
self.name = bone.name
|
|
||||||
self.point = tuple(bone.head)
|
|
||||||
self.ctrl = 'CTRL_' + bone.name
|
|
||||||
if bone.parent:
|
|
||||||
self.parent = bone.parent.name
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
return self.point < other.point
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(self.point)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
#if not isinstance(other, type(self)):
|
|
||||||
# return NotImplemented
|
|
||||||
return self.point == other.point
|
|
||||||
|
|
||||||
class constraint_dup:
|
|
||||||
def __init__(self, bone, con):
|
|
||||||
self.name = con.name
|
|
||||||
self.target = con.target
|
|
||||||
self.subtarget = con.subtarget
|
|
||||||
self.bone = bone.name
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(self.bone)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self.bone == other.bone
|
|
||||||
|
|
||||||
def bone_orientation(source, target, value):
|
|
||||||
source.align_orientation(target)
|
|
||||||
x, y, z = source.matrix.to_3x3().col
|
|
||||||
R = (Matrix.Translation(source.head) @ Matrix.Rotation(radians(value), 4, x) @ Matrix.Translation(-source.head))
|
|
||||||
source.transform(R, roll = False)
|
|
||||||
source.align_roll(target.vector)
|
|
||||||
|
|
||||||
def find_ctrl(bone, controls):
|
|
||||||
i = list(controls).index(bone)
|
|
||||||
bone.ctrl = list(controls)[i].ctrl
|
|
||||||
|
|
||||||
return bone.ctrl
|
|
||||||
|
|
||||||
def add_controlers(self, obj, parents, targets):
|
|
||||||
|
|
||||||
#controls = set(parents).union(targets)
|
|
||||||
controls = set(parents + targets)
|
|
||||||
|
|
||||||
#create hierarchy
|
|
||||||
for bone in controls:
|
|
||||||
editbone = obj.data.edit_bones[bone.name]
|
|
||||||
if editbone.parent is None:
|
|
||||||
continue
|
|
||||||
parentnames = [bone.name for bone in parents]
|
|
||||||
#if a target and its parent are part of the hierarchy then linked to its own bone parent
|
|
||||||
if bone in targets and bone not in parents and editbone.parent.name in parentnames:
|
|
||||||
parentbone = parent(editbone)
|
|
||||||
else:
|
|
||||||
parentbone = parent(editbone.parent)
|
|
||||||
|
|
||||||
if parentbone in controls and parentbone != bone:
|
|
||||||
bone.parent = find_ctrl(parentbone, controls)
|
|
||||||
else:
|
|
||||||
bone.parent = editbone.parent.name
|
|
||||||
|
|
||||||
|
|
||||||
edit_bones = obj.data.edit_bones
|
|
||||||
for bone in controls:
|
|
||||||
editbone = edit_bones[bone.name]
|
|
||||||
ctrl = obj.data.edit_bones.new(bone.ctrl)
|
|
||||||
ctrl.head = bone.point
|
|
||||||
ctrl.tail = bone.point
|
|
||||||
ctrl.tail[2] = bone.point[2] + (editbone.length / 3)
|
|
||||||
ctrl.bbone_x = editbone.bbone_x
|
|
||||||
ctrl.bbone_z = editbone.bbone_z
|
|
||||||
ctrl.use_deform = False
|
|
||||||
if self.bone_align:
|
|
||||||
angle = 90 if self.align_90 else 0
|
|
||||||
bone_orientation(ctrl, editbone, angle)
|
|
||||||
if angle == 90:
|
|
||||||
ctrl.align_roll(editbone.vector)
|
|
||||||
else:
|
|
||||||
ctrl.roll = editbone.roll
|
|
||||||
|
|
||||||
#apply hierarchy
|
|
||||||
for bone in parents:
|
|
||||||
editbone = edit_bones[bone.name]
|
|
||||||
ctrl_name = find_ctrl(bone, controls)
|
|
||||||
ctrl = edit_bones[ctrl_name]
|
|
||||||
editbone.parent = ctrl
|
|
||||||
|
|
||||||
for bone in controls:
|
|
||||||
ctrl = edit_bones[bone.ctrl]
|
|
||||||
if hasattr(bone, 'parent'):
|
|
||||||
ctrl.parent = edit_bones[bone.parent]
|
|
||||||
|
|
||||||
return controls
|
|
||||||
|
|
||||||
def pose_bbone_setup(bone, posebone, bbone_group = None):
|
|
||||||
#add the custom shape to the widget bones
|
|
||||||
custom_shape = draw_wgt(bone['length'], posebone)
|
|
||||||
posebone.custom_shape = custom_shape
|
|
||||||
posebone.use_custom_shape_bone_size = False
|
|
||||||
if bbone_group:
|
|
||||||
posebone.bone_group = bbone_group
|
|
||||||
posebone.rotation_mode = 'XZY'
|
|
||||||
posebone.lock_rotation[0] = True
|
|
||||||
posebone.lock_rotation[2] = True
|
|
||||||
|
|
||||||
#####MAIN####
|
|
||||||
class BboneWidgets(bpy.types.Operator):
|
|
||||||
"""Add Bbone widget controls to the selected bones"""
|
|
||||||
bl_idname = "armature.add_bbone_widgets"
|
|
||||||
bl_label = "Add_Bbone_widgets"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return bpy.context.object.type == 'ARMATURE'
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
obj = context.object
|
|
||||||
|
|
||||||
obj.data.display_type = 'BBONE'
|
|
||||||
|
|
||||||
bones = []
|
|
||||||
parentlayers = [False if i != 24 else True for i in range(32)]
|
|
||||||
wgtlayers = [True if i == 0 else False for i in range(32)]
|
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
|
||||||
obj.data.use_mirror_x = False
|
|
||||||
for bone in obj.data.edit_bones:
|
|
||||||
if not bone.select:
|
|
||||||
continue
|
|
||||||
if bone.bbone_segments == 1:
|
|
||||||
bone.bbone_segments = 10
|
|
||||||
bone.bbone_handle_type_start = 'TANGENT'
|
|
||||||
bone.bbone_handle_type_end = 'TANGENT'
|
|
||||||
bone_name = bone.name
|
|
||||||
#add parent bone to the Bbone widgets
|
|
||||||
parent = obj.data.edit_bones.new('WGTB_parent_'+ bone_name)
|
|
||||||
parent_name = parent.name
|
|
||||||
dup_values(bone, parent)
|
|
||||||
parent.name = parent_name
|
|
||||||
parent.select = False
|
|
||||||
parent.select_head = False
|
|
||||||
parent.select_tail = False
|
|
||||||
|
|
||||||
#change layer of the parent bone
|
|
||||||
if bpy.app.version < (4, 0, 0):
|
|
||||||
parent.layers = parentlayers
|
|
||||||
|
|
||||||
#add bbone widget bones
|
|
||||||
head_widget = obj.data.edit_bones.new('Bhead_'+ bone.name)
|
|
||||||
head_widget.parent = parent
|
|
||||||
#head_widget.head = bone.head
|
|
||||||
head_widget.head = bone.head + (bone.tail - bone.head) * 0.25
|
|
||||||
#head_widget.tail = (bone.tail - bone.head)/10
|
|
||||||
head_widget.length = bone.length * 0.1
|
|
||||||
head_widget.bbone_x = bone.bbone_x
|
|
||||||
head_widget.bbone_z = bone.bbone_z
|
|
||||||
head_widget.align_orientation(bone)
|
|
||||||
head_widget.inherit_scale = 'NONE'
|
|
||||||
head_name = head_widget.name
|
|
||||||
|
|
||||||
tail_widget = obj.data.edit_bones.new('Btail_'+ bone.name)
|
|
||||||
tail_widget.parent = parent
|
|
||||||
#tail_widget.head = bone.tail
|
|
||||||
tail_widget.head = bone.head + (bone.tail - bone.head) * 0.75
|
|
||||||
#tail_widget.tail = bone.tail - (bone.tail - bone.head)/10
|
|
||||||
tail_widget.length = bone.length * 0.1
|
|
||||||
tail_widget.bbone_x = bone.bbone_x
|
|
||||||
tail_widget.bbone_z = bone.bbone_z
|
|
||||||
tail_widget.align_orientation(bone)
|
|
||||||
tail_widget.inherit_scale = 'NONE'
|
|
||||||
tail_name = tail_widget.name
|
|
||||||
|
|
||||||
#add vis bones
|
|
||||||
head_vis = obj.data.edit_bones.new('Bhead_vis_'+ bone.name)
|
|
||||||
head_vis.parent = parent
|
|
||||||
head_vis.head = bone.head
|
|
||||||
head_vis.tail = head_widget.head
|
|
||||||
head_vis.bbone_x = bone.bbone_x*0.1
|
|
||||||
head_vis.bbone_z = bone.bbone_z*0.1
|
|
||||||
|
|
||||||
#head_vis_name = head_vis.name
|
|
||||||
head_vis.hide_select = True
|
|
||||||
head_vis.use_deform = False
|
|
||||||
tail_vis = obj.data.edit_bones.new('Btail_vis_'+ bone.name)
|
|
||||||
tail_vis.parent = parent
|
|
||||||
tail_vis.head = bone.tail
|
|
||||||
tail_vis.tail = tail_widget.head
|
|
||||||
tail_vis.bbone_x = bone.bbone_x*0.1
|
|
||||||
tail_vis.bbone_z = bone.bbone_z*0.1
|
|
||||||
|
|
||||||
#tail_vis_name = tail_vis.name
|
|
||||||
tail_vis.hide_select = True
|
|
||||||
|
|
||||||
tail_vis.use_deform = False
|
|
||||||
if bpy.app.version < (4, 0, 0):
|
|
||||||
tail_widget.layers = wgtlayers
|
|
||||||
head_widget.layers = wgtlayers
|
|
||||||
head_vis.layers = wgtlayers
|
|
||||||
tail_vis.layers = wgtlayers
|
|
||||||
|
|
||||||
bones.append({'name': bone_name, 'parent': parent_name, 'head': head_name, 'tail': tail_name, 'head_vis': head_vis.name, 'tail_vis': tail_vis.name, 'length': bone.length})
|
|
||||||
|
|
||||||
#####POSE MODE#######
|
|
||||||
bpy.ops.object.mode_set(mode = 'POSE')
|
|
||||||
|
|
||||||
if bpy.app.version < (4, 0, 0):
|
|
||||||
bone_groups = obj.pose.bone_groups
|
|
||||||
if 'BBone Widgets' not in bone_groups:
|
|
||||||
bbone_group = bone_groups.new(name = 'BBone Widgets')
|
|
||||||
bbone_group.color_set = 'THEME09'
|
|
||||||
else:
|
|
||||||
bbone_group = bone_groups['BBone Widgets']
|
|
||||||
else:
|
|
||||||
bbone_group = None
|
|
||||||
|
|
||||||
for bone in bones:
|
|
||||||
posebone = obj.pose.bones[bone['name']]
|
|
||||||
# Prepare parent bone in pose mode
|
|
||||||
poseparent = obj.pose.bones[bone['parent']]
|
|
||||||
#disable use deform
|
|
||||||
obj.data.bones[bone['parent']].use_deform = False
|
|
||||||
obj.data.bones[bone['head']].use_deform = False
|
|
||||||
obj.data.bones[bone['tail']].use_deform = False
|
|
||||||
|
|
||||||
pose_bbone_setup(bone, obj.pose.bones[bone['head']], bbone_group)
|
|
||||||
pose_bbone_setup(bone, obj.pose.bones[bone['tail']], bbone_group)
|
|
||||||
|
|
||||||
dup_constraints(posebone, poseparent)
|
|
||||||
|
|
||||||
#add all the drivers
|
|
||||||
add_driver(obj, posebone, bone['head'], 'bbone_curveinx', 'location.x')
|
|
||||||
add_driver(obj, posebone, bone['head'], 'bbone_curveinz', 'location.z')
|
|
||||||
add_driver(obj, posebone, bone['head'], 'bbone_easein', 'location.y', '*5/'+ str(bone['length']))
|
|
||||||
add_driver(obj, posebone, bone['head'], 'bbone_rollin', 'rotation_euler.y')
|
|
||||||
add_driver(obj, posebone, bone['head'], ('bbone_scalein', 0), 'scale.x')
|
|
||||||
add_driver(obj, posebone, bone['head'], ('bbone_scalein', 1), 'scale.y')
|
|
||||||
add_driver(obj, posebone, bone['head'], ('bbone_scalein', 2), 'scale.z')
|
|
||||||
|
|
||||||
add_driver(obj, posebone, bone['tail'], 'bbone_curveoutx', 'location.x')
|
|
||||||
add_driver(obj, posebone, bone['tail'], 'bbone_curveoutz', 'location.z')
|
|
||||||
add_driver(obj, posebone, bone['tail'], 'bbone_easeout', 'location.y', '*-5/'+ str(bone['length']))
|
|
||||||
add_driver(obj, posebone, bone['tail'], 'bbone_rollout', 'rotation_euler.y')
|
|
||||||
add_driver(obj, posebone, bone['tail'], ('bbone_scaleout', 0), 'scale.x')
|
|
||||||
add_driver(obj, posebone, bone['tail'], ('bbone_scaleout', 1), 'scale.y')
|
|
||||||
add_driver(obj, posebone, bone['tail'], ('bbone_scaleout', 2), 'scale.z')
|
|
||||||
|
|
||||||
#add constraints to visual bones
|
|
||||||
head_vis = add_vis_bone_con(obj, bone['head_vis'], bone['head'])
|
|
||||||
tail_vis = add_vis_bone_con(obj, bone['tail_vis'], bone['tail'])
|
|
||||||
if bpy.app.version < (4, 0, 0):
|
|
||||||
head_vis.bone_group = bbone_group
|
|
||||||
tail_vis.bone_group = bbone_group
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
class ChainControls(bpy.types.Operator):
|
|
||||||
"""Add parent and target controls to the selected bones to create a chain control"""
|
|
||||||
bl_idname = "armature.add_chain_ctrls"
|
|
||||||
bl_label = "Add_Chain_Controls"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
parents: bpy.props.BoolProperty(name = 'Add Parents', description = "Align the controls 90 degrees to the original bones", default = True)
|
|
||||||
targets: bpy.props.BoolProperty(name = 'Add Targets', description = "Align the controls 90 degrees to the original bones", default = True)
|
|
||||||
keep_hierarchy: bpy.props.BoolProperty(name = 'Keep Hierarchy', description = "Keep the controls in the hierarchy of the original bones", default = True)
|
|
||||||
bone_align: bpy.props.BoolProperty(name = 'Align to Bones', description = "Align the controls to the original bones", default = True)
|
|
||||||
align_90: bpy.props.BoolProperty(name = '+90°', description = "Align the controls 90 degrees to the original bones", default = True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return bpy.context.object.type == 'ARMATURE'
|
|
||||||
def invoke(self, context, event):
|
|
||||||
#obj = context.object
|
|
||||||
wm = context.window_manager
|
|
||||||
return wm.invoke_props_dialog(self, width = 200)
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
row = layout.row()
|
|
||||||
row.label(text = 'Add Control Bones')
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(self, 'parents') #text = 'Size'
|
|
||||||
row.prop(self, 'targets')
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
col = layout.column()
|
|
||||||
col.prop(self, 'keep_hierarchy')
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(self, 'bone_align')
|
|
||||||
if self.bone_align:
|
|
||||||
row.prop(self, 'align_90', toggle=True)
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
obj = context.object
|
|
||||||
targets = []
|
|
||||||
parents = []
|
|
||||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
|
||||||
edit_bones = bpy.context.selected_editable_bones
|
|
||||||
#create list of parent and target objects
|
|
||||||
for bone in edit_bones:
|
|
||||||
bone.use_connect = False
|
|
||||||
if self.targets:
|
|
||||||
targets.append(target(bone))
|
|
||||||
if self.parents:
|
|
||||||
parents.append(parent(bone))
|
|
||||||
|
|
||||||
controls = add_controlers(self, obj, parents, targets)
|
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode = 'POSE')
|
|
||||||
|
|
||||||
#Add the bone group for the ctrls if doesn't exist
|
|
||||||
if bpy.app.version < (4, 0, 0):
|
|
||||||
bone_groups = obj.pose.bone_groups
|
|
||||||
if 'Ctrl Bones' not in bone_groups:
|
|
||||||
ctrl_group = bone_groups.new(name = 'Ctrl Bones')
|
|
||||||
ctrl_group.color_set = 'THEME01'
|
|
||||||
else:
|
|
||||||
ctrl_group = bone_groups['Ctrl Bones']
|
|
||||||
|
|
||||||
for bone in controls:
|
|
||||||
posebone = obj.pose.bones[bone.ctrl]
|
|
||||||
if bpy.app.version < (4, 0, 0):
|
|
||||||
posebone.bone_group = ctrl_group
|
|
||||||
else:
|
|
||||||
posebone.color.palette = 'THEME01'
|
|
||||||
|
|
||||||
if self.targets:
|
|
||||||
for bone in targets:
|
|
||||||
#update from the controls set
|
|
||||||
ctrl = find_ctrl(bone, controls)
|
|
||||||
posebone = obj.pose.bones[bone.name]
|
|
||||||
|
|
||||||
con = posebone.constraints.new('STRETCH_TO')
|
|
||||||
con.target = obj
|
|
||||||
|
|
||||||
con.subtarget = ctrl
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
class MergeRigs(bpy.types.Operator):
|
|
||||||
"""Merge selected rigs to active and keep hierarchy and constraints for shared bones"""
|
|
||||||
bl_idname = "armature.merge"
|
|
||||||
bl_label = "Merge_Rigs"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return bpy.context.object.type == 'ARMATURE'
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
target_obj = context.object
|
|
||||||
|
|
||||||
if target_obj.type != 'ARMATURE':
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
target_bones = set([bone.name for bone in target_obj.data.bones])
|
|
||||||
constraints = []
|
|
||||||
childrens = {}
|
|
||||||
|
|
||||||
#Store children and constraints
|
|
||||||
bpy.ops.object.mode_set(mode = 'POSE')
|
|
||||||
for obj in bpy.context.selected_objects:
|
|
||||||
if obj.type != 'ARMATURE':
|
|
||||||
continue
|
|
||||||
if obj == target_obj:
|
|
||||||
continue
|
|
||||||
#create a set of all the similiar bones in all the rigs
|
|
||||||
obj_bones = set([bone.name for bone in obj.data.bones])
|
|
||||||
shared_bones = target_bones.intersection(obj_bones)
|
|
||||||
|
|
||||||
#find all the constraints and children
|
|
||||||
for bone in obj.pose.bones:
|
|
||||||
#store all the constraints
|
|
||||||
for con in bone.constraints:
|
|
||||||
if not hasattr(con, 'subtarget'):
|
|
||||||
continue
|
|
||||||
if con.target == obj and con.subtarget in shared_bones:
|
|
||||||
constraints.append(constraint_dup(bone, con))
|
|
||||||
if bone.name in shared_bones:
|
|
||||||
for child in bone.children:
|
|
||||||
if child.name in childrens:
|
|
||||||
continue
|
|
||||||
childrens.update({child.name : bone.name})
|
|
||||||
|
|
||||||
#remove shared bones
|
|
||||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
|
||||||
for obj in bpy.context.selected_objects:
|
|
||||||
if obj.type != 'ARMATURE':
|
|
||||||
continue
|
|
||||||
if obj == target_obj:
|
|
||||||
continue
|
|
||||||
for bone in shared_bones:
|
|
||||||
if bone not in obj.data.edit_bones:
|
|
||||||
continue
|
|
||||||
obj.data.edit_bones.remove(obj.data.edit_bones[bone])
|
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode = 'POSE')
|
|
||||||
bpy.ops.object.join()
|
|
||||||
|
|
||||||
#restore constraints
|
|
||||||
for con_dup in constraints:
|
|
||||||
if con_dup.bone in target_bones:
|
|
||||||
continue
|
|
||||||
if con_dup.bone not in target_obj.pose.bones:
|
|
||||||
continue
|
|
||||||
#print('constraint on ',con_dup.bone, con_dup.name)
|
|
||||||
posebone = target_obj.pose.bones[con_dup.bone]
|
|
||||||
if con_dup.name not in posebone.constraints:
|
|
||||||
continue
|
|
||||||
con = posebone.constraints[con_dup.name]
|
|
||||||
con.target = target_obj
|
|
||||||
con.subtarget = con_dup.subtarget
|
|
||||||
|
|
||||||
#reparent all child bones
|
|
||||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
|
||||||
for child, parent in childrens.items():
|
|
||||||
target_obj.data.edit_bones[child].parent = target_obj.data.edit_bones[parent]
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
classes = (MergeRigs,BboneWidgets, ChainControls)
|
|
||||||
def register():
|
|
||||||
from bpy.utils import register_class
|
|
||||||
for cls in classes:
|
|
||||||
register_class(cls)
|
|
||||||
# bpy.utils.register_class(BboneWidgets)
|
|
||||||
# bpy.utils.register_class(ChainControls)
|
|
||||||
# bpy.utils.register_class(RiggerToolBox_PT_Panel)
|
|
||||||
|
|
||||||
def unregister():
|
|
||||||
from bpy.utils import unregister_class
|
|
||||||
for cls in classes:
|
|
||||||
unregister_class(cls)
|
|
||||||
# bpy.utils.unregister_class(BboneWidgets)
|
|
||||||
# bpy.utils.unregister_class(ChainControls)
|
|
||||||
# bpy.utils.unregister_class(RiggerToolBox_PT_Panel)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
register()
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,534 +0,0 @@
|
|||||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ***** END GPL LICENCE BLOCK *****
|
|
||||||
|
|
||||||
bl_info = {
|
|
||||||
"name": "AnimToolBox",
|
|
||||||
"author": "Tal Hershkovich",
|
|
||||||
"version" : (0, 0, 8),
|
|
||||||
"blender" : (3, 2, 0),
|
|
||||||
"location": "View3D - Properties - Animation Panel",
|
|
||||||
"description": "A set of animation tools",
|
|
||||||
"wiki_url": "",
|
|
||||||
"category": "Animation"}
|
|
||||||
|
|
||||||
if "bpy" in locals():
|
|
||||||
import importlib
|
|
||||||
if "Rigger_Toolbox" in locals():
|
|
||||||
importlib.reload(Rigger_Toolbox)
|
|
||||||
if "TempCtrls" in locals():
|
|
||||||
importlib.reload(TempCtrls)
|
|
||||||
if "Tools" in locals():
|
|
||||||
importlib.reload(Tools)
|
|
||||||
if "Display" in locals():
|
|
||||||
importlib.reload(Display)
|
|
||||||
if "emp" in locals():
|
|
||||||
importlib.reload(emp)
|
|
||||||
if "multikey" in locals():
|
|
||||||
importlib.reload(multikey)
|
|
||||||
if "Rigger_Toolbox" in locals():
|
|
||||||
importlib.reload(Rigger_Toolbox)
|
|
||||||
if "ui" in locals():
|
|
||||||
importlib.reload(ui)
|
|
||||||
if "addon_updater_ops" in locals():
|
|
||||||
importlib.reload(addon_updater_ops)
|
|
||||||
|
|
||||||
import bpy
|
|
||||||
from . import addon_updater_ops
|
|
||||||
from . import TempCtrls
|
|
||||||
from . import Rigger_Toolbox
|
|
||||||
from . import Tools
|
|
||||||
from . import Display
|
|
||||||
from . import emp
|
|
||||||
from . import ui
|
|
||||||
from . import multikey
|
|
||||||
from . import Rigger_Toolbox
|
|
||||||
from pathlib import Path
|
|
||||||
from bpy.utils import register_class
|
|
||||||
from bpy.utils import unregister_class
|
|
||||||
from bpy.app.handlers import persistent
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class TempCtrlsItems(bpy.types.PropertyGroup):
|
|
||||||
#located at context.scene.btc.ctrl_items
|
|
||||||
controlled: bpy.props.PointerProperty(name = "controlled object", description = "rigs and objects that are being controlled", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
controller: bpy.props.PointerProperty(name = "controller object", description = "rigs and objects that are controling", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
class TempCtrlsSceneSettings(bpy.types.PropertyGroup):
|
|
||||||
#located at context.scene.btc
|
|
||||||
root: bpy.props.BoolProperty(name = "Root Empty", description = "Add a root to the empties ", default = False, override = {'LIBRARY_OVERRIDABLE'}, update = TempCtrls.root_prop)
|
|
||||||
root_bone: bpy.props.StringProperty(name = "Root bone", description = "Root empty as a root bone ", override = {'LIBRARY_OVERRIDABLE'}, update = TempCtrls.root_update)
|
|
||||||
root_object: bpy.props.PointerProperty(name = "Root object", description = "Root empty as a root object ", update = TempCtrls.root_update, type = bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
ctrl_type: bpy.props.EnumProperty(name = 'Controllers', description="Select empties or a bone with a new rig to bake to", items = [('BONE', 'Bone','Bake to bones','BONE_DATA', 0), ('EMPTY', 'Empty', 'Bake to empties', 'EMPTY_ARROWS', 1)])
|
|
||||||
ctrl_items: bpy.props.CollectionProperty(type = TempCtrlsItems, override = {'LIBRARY_OVERRIDABLE', 'USE_INSERTION'})
|
|
||||||
|
|
||||||
bake_range_type: bpy.props.EnumProperty(name = 'Bake Range', description="Use either scene, actions length or custom frame range", default = 'KEYFRAMES', update= TempCtrls.update_range_type,
|
|
||||||
items = [('SCENE', 'Scene Range', 'Bake to the scene range'), ('KEYFRAMES', 'Keyframes Range', 'Bake all the keyframes in the layers'), ('CUSTOM', 'Custom', 'Enter a custom frame range')], override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bake_range: bpy.props.IntVectorProperty(name='Frame Range', description='Bake to a custom frame range', size = 2, update= TempCtrls.update_bake_range)
|
|
||||||
bake_layers: bpy.props.BoolProperty(name = "Bake Layers", description = "Use keyframes from all the layers to include in the bake", default = False)
|
|
||||||
|
|
||||||
target: bpy.props.EnumProperty(name = 'Affect', description="Cleanup created constraints and empties", default = 1,
|
|
||||||
items = [('ALL', 'All Ctrl Rigs','Bake to all Ctrl Rigs', 0),
|
|
||||||
('SELECTED', 'Selected Chains','Bake to only selected chain controlls', 1),
|
|
||||||
('RELATIVE', 'Relative Ctrls Rig','Bake to the Relative Control rigs', 2)])
|
|
||||||
# ('CONSTRAINTS', 'Constraints', 'Clean all the bone constraints', 3),
|
|
||||||
# ('CONTROLLERS', 'Controllers', 'Remove all the baked empties', 4)])
|
|
||||||
|
|
||||||
selection: bpy.props.EnumProperty(name = 'Select', description="Select all controls, original bones or their relative", default = 'CONTROLLERS',
|
|
||||||
items = [('RELATIVE_CTRLS', 'Relative Ctrls','Select the Relative controller to your current selection', 0),
|
|
||||||
('RELATIVE_CONSTRAINED', 'Relative Constrained','Select the Relative original constrained bone to your current selection', 1),
|
|
||||||
('CONTROLLERS', 'All Ctrls', 'Select all the controller bones or empties', 2), ('CONSTRAINED', 'All Constrained', 'Select all the original constrained bones', 3)])
|
|
||||||
|
|
||||||
#smartbake setting
|
|
||||||
linksettings: bpy.props.BoolProperty(name = "Link Settings", description = "Link Settings", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bakesettings: bpy.props.BoolProperty(name = "bake settings", description = "bake settings", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
cleansettings: bpy.props.BoolProperty(name = "clean settings", description = "clean settings", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
smartbake: bpy.props.BoolProperty(name = "Smart Bake", description = "Keep Original Frame count", default = True, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
inbetween_keyframes: bpy.props.IntProperty(name = "Inbetween Keyframes", description = "Add inbetween keyframes", default = 0, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
from_origin: bpy.props.BoolProperty(name = "From Origin", description = "Use Keyframes from Original Bone", default = True, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
from_ctrl: bpy.props.BoolProperty(name = "From Controller", description = "Use Keyframes from Controller Bone", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
clean_ctrls: bpy.props.BoolProperty(name = "Remove Ctrls", description = "Remove Controls", default = True, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
clean_constraints: bpy.props.BoolProperty(name = "Remove Constraints", description = "Remove Constraints", default = True, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
rebake_to_org: bpy.props.BoolProperty(name = "ReBake connections to original bones", description = "ReBake ctrls from connected chains current anim to the original bones", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
link_to: bpy.props.EnumProperty(name = 'Link to Chain', description="Link to begining of an active chain or the tip of the chain", default = 1,
|
|
||||||
items = [('BASE', 'Base','Link to the base of the active chain', 0), ('TIP', 'Tip', 'Link to the tip of the chain', 1)])
|
|
||||||
# link_from: bpy.props.EnumProperty(name = 'Link to Chain', description="Link to begining of an active chain or the tip of the chain", default = 0,
|
|
||||||
# items = [('BASE', 'Base','Link to the base of the active chain', 0), ('TIP', 'Tip', 'Link to the tip of the chain', 1)])
|
|
||||||
|
|
||||||
shape_size: bpy.props.FloatProperty(name='Size', description="Multiple factor for the shape size of the temp controls", update = TempCtrls.tempctrl_shapesize, min = 0.001, default = 1.5, override = {'LIBRARY_OVERRIDABLE'})#
|
|
||||||
shape_type: bpy.props.EnumProperty(name = 'Shape Type', description="Display type for the controls", items = TempCtrls.ctrl_shape_items, update = TempCtrls.tempctrl_shape_type)
|
|
||||||
color_set: bpy.props.EnumProperty(name="Bone Color Set", description="Choose a bone color set", items = TempCtrls.get_bone_color_sets, update = TempCtrls.update_bone_color, default = 9)
|
|
||||||
|
|
||||||
add_ik_ctrl: bpy.props.BoolProperty(name = 'Add an Extra IK Ctrl Bone', description = "Adds an extra bone ctrl as the ik ctrl", default = False, update = TempCtrls.add_ik_prop)
|
|
||||||
pole_target: bpy.props.BoolProperty(name = 'Add Pole Target', description = "Adding Pole Target to the IK Chain", default = True, update = TempCtrls.pole_prop)
|
|
||||||
pole_offset: bpy.props.FloatProperty(name="Offset", description="Offset the bone in the axis direction", default=1.0, update = TempCtrls.pole_offset)
|
|
||||||
child: bpy.props.BoolProperty(name = 'Add extra child Ctrls', description = "Add an child control for an overlay control", default = False, update = TempCtrls.child_prop)
|
|
||||||
orientation: bpy.props.BoolProperty(name = 'Use World Space Orientation', description = "Orient the bones to world space instead of to the original bones", default = True)
|
|
||||||
|
|
||||||
# enabled: bpy.props.BoolProperty(name = 'Switch On / Off', description = "Enabling and Disabling Temp Ctrls influence", default = True)
|
|
||||||
|
|
||||||
class TempCtrlsBoneSettings(bpy.types.PropertyGroup):
|
|
||||||
#located at obj.pose.bones[##].btc
|
|
||||||
root: bpy.props.BoolProperty(name = "Root Bone", description = "Bone is marked as the root bone", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
child: bpy.props.BoolProperty(name = "Child Bone", description = "Bone is marked as a child bone inside the setup", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
org_id: bpy.props.IntProperty(name = "Originate ID", description = "ID number of the bone the ctrl originates from", override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
setup_id: bpy.props.IntProperty(name = "Setup ID", description = "ID number of the current chain setup", override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
setup: bpy.props.EnumProperty(name = 'Setup Type', description="Describes what kind of setup the bone is part of", override = {'LIBRARY_OVERRIDABLE'},
|
|
||||||
items = [('NONE', 'No Setup','No Setup Applied', 0),
|
|
||||||
('WORLDSPACE', 'World Space Ctrl','World Space Ctrl setup', 1),
|
|
||||||
('WORLDSPACE_CURSOR', 'World Space Cursor Ctrl','World Space Cursor pivot', 2),
|
|
||||||
('TEMPFK', 'Temporary FK setup','Temporary FK chain setup', 3),
|
|
||||||
('TEMPFK_FLIP', 'Temporary flipped FK setup','Temporary flipped FK chain setup', 4),
|
|
||||||
('TEMPIK', 'Temporary IK setup','Temporary IK setup', 5),
|
|
||||||
('POLE', 'Temporary IK Pole setup','Temporary IK Pole', 6),
|
|
||||||
('PARENTCTRL', 'Parent Ctrl from cursor setup','Parent Ctrl from cursor setup', 7),
|
|
||||||
('ROOT', 'Root', 'Root Ctrl for all the setups', 8),
|
|
||||||
('EMPTY', 'Root', 'Root Ctrl for all the setups', 9),
|
|
||||||
('TRACK_TO', 'Track To','World Space Track to Ctrl setup', 10),
|
|
||||||
('TRACK_TO_EMPTY', 'Track To Empty','World Space Track to Empty Ctrl setup', 11)])
|
|
||||||
|
|
||||||
#using org mostly to decide if it needs a custom shape
|
|
||||||
org: bpy.props.EnumProperty(name = 'Org Type', description="Describes what if the function of the bone", override = {'LIBRARY_OVERRIDABLE'},
|
|
||||||
items = [('CTRL', 'Controller Bone','Controller Bone', 0),
|
|
||||||
('ORG', 'Original Bone','Original Bone', 1),
|
|
||||||
('MCH', 'Mechanical Bone','Mechanical Bone', 2),
|
|
||||||
('NONE', 'Nothing applied','Nothing applied', 3)])
|
|
||||||
|
|
||||||
shape: bpy.props.BoolProperty(name = "Apply shape", description = "Mark if the bone needs a shape", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
class TempCtrlsOrgIds(bpy.types.PropertyGroup):
|
|
||||||
# A collection of the org ids used in each setup. Org ID is the direct connection
|
|
||||||
# between original bones and ctrls
|
|
||||||
pass
|
|
||||||
|
|
||||||
class TempCtrlsObjectSetups(bpy.types.PropertyGroup):
|
|
||||||
#located at obj.animtoolbox.ctrl_setups
|
|
||||||
#name: using string of the id
|
|
||||||
setup: bpy.props.EnumProperty(name = 'Setup Type', description="Describes what kind of setup the bone is part of",
|
|
||||||
items = [('NONE', 'No Setup','No Setup Applied', 0),
|
|
||||||
('WORLDSPACE', 'World Space Ctrl','World Space Ctrl setup', 1),
|
|
||||||
('WORLDSPACE_CURSOR', 'World Space Cursor Ctrl','World Space Cursor pivot', 2),
|
|
||||||
('TEMPFK', 'Temporary FK setup','Temporary FK chain setup', 3),
|
|
||||||
('TEMPFK_FLIP', 'Temporary flipped FK setup','Temporary flipped FK chain setup', 4),
|
|
||||||
('TEMPIK', 'Temporary IK setup','Temporary IK setup', 5),
|
|
||||||
('POLE', 'Temporary IK Pole setup','Temporary IK Pole', 6),
|
|
||||||
('PARENTCTRL', 'Parent Ctrl from cursor setup','Parent Ctrl from cursor setup', 7),
|
|
||||||
('ROOT', 'Root', 'Root Ctrl for all the setups', 8),
|
|
||||||
('EMPTY', 'Root', 'Root Ctrl for all the setups', 9),
|
|
||||||
('TRACK_TO', 'Track To','World Space Track to Ctrl setup', 10),
|
|
||||||
('TRACK_TO_EMPTY', 'Track To Empty','World Space Track to Empty Ctrl setup', 11)])
|
|
||||||
|
|
||||||
org_ids: bpy.props.CollectionProperty(type = TempCtrlsOrgIds)
|
|
||||||
|
|
||||||
class MultikeyProperties(bpy.types.PropertyGroup):
|
|
||||||
|
|
||||||
selectedbones: bpy.props.BoolProperty(name="Selected Bones", description="Affect only selected bones", default=True, options={'HIDDEN'})
|
|
||||||
handletype: bpy.props.BoolProperty(name="Keep handle types", description="Keep handle types", default=False, options={'HIDDEN'})
|
|
||||||
scale: bpy.props.FloatProperty(name="Scale Factor", description="Scale percentage of the average value", default=1.0, update = multikey.scale_value)
|
|
||||||
randomness: bpy.props.FloatProperty(name="Randomness", description="Random Threshold of keyframes", default=0.1, min=0.0, max = 1.0, update = multikey.random_value)
|
|
||||||
|
|
||||||
class AnimToolBoxObjectSettings(bpy.types.PropertyGroup):
|
|
||||||
|
|
||||||
controlled: bpy.props.PointerProperty(name = 'Controlled Rig', description="Adding the rig object that is being controlled by the current object", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
controller: bpy.props.PointerProperty(name = 'Controller Rig', description="Adding the rig object that is used as the temp control object", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
ctrl_setups: bpy.props.CollectionProperty(type = TempCtrlsObjectSetups, override = {'LIBRARY_OVERRIDABLE', 'USE_INSERTION'})
|
|
||||||
ctrls_enabled: bpy.props.BoolProperty(name = 'Temp Ctrls Switch', description = "Enabling and Disabling Temp Ctrls influence", default = True)
|
|
||||||
# influence: bpy.props.FloatProperty(name = "Influence Slider for the Temp Ctrls", description = "Switching the influence slider for the temp ctrls", default = 1, min = 0.0, max = 1.0)
|
|
||||||
|
|
||||||
#Used for Bake to Empties
|
|
||||||
# org_id: bpy.props.IntProperty(name = "Originate ID", description = "ID number of the bone the ctrl originates from", override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
setup_id: bpy.props.IntProperty(name = "Setup ID", description = "ID number of the current chain setup", override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
root: bpy.props.BoolProperty(name = "Root Empty", description = "Empty is marked as the root ctrl", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
child: bpy.props.BoolProperty(name = "Child Empty", description = "Empty is marked as a child bone inside the setup", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
keyframes_offset: bpy.props.FloatProperty(name = "Keyframes Offset", description = "Interactive slider to offset keyframes back and forth ", default = 0)
|
|
||||||
|
|
||||||
class IsolatedRigs(bpy.types.PropertyGroup):
|
|
||||||
|
|
||||||
hidden: bpy.props.PointerProperty(name = "Hidden Rigs", description = "List of Rigs that are hidden during pose mode isolation", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
selected: bpy.props.PointerProperty(name = "Selected Rigs", description = "List of Rigs that are hidden during pose mode isolation", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
class AnimToolBoxUILayout(bpy.types.PropertyGroup):
|
|
||||||
'''Layout properties for the UI'''
|
|
||||||
quick_menu: bpy.props.BoolProperty(name = "Use Quick Menu", description = "Opens header menu with only icon", default = False)
|
|
||||||
copy_paste_matrix: bpy.props.BoolProperty(name = "Copy Matrix Menu", description = "Opens the menu for copy paste matrices", default = True)
|
|
||||||
copy_paste_world: bpy.props.BoolProperty(name = "Copy Paste World Matrix", description = "Copy and Paste the World Matrix", default = False, update = Tools.copy_paste_world_update)
|
|
||||||
copy_paste_relative: bpy.props.BoolProperty(name = "Copy Paste Relative Matrix", description = "Copy and Paste the Matrix relative to the active bone", default = False, update = Tools.copy_paste_relative_update)
|
|
||||||
Inbetweens: bpy.props.BoolProperty(name = "Blendings/Inbetweens", description = "Opens the menu for Inbetweens", default = True)
|
|
||||||
gizmo_size: bpy.props.BoolProperty(name = "Gizmo size", description = "Change the Gizmo size using alt +/- hotkeys", default = False)
|
|
||||||
# temp_ctrls: bpy.props.BoolProperty(name = "Temp Ctrls", description = "Open Temp Ctrls", default = False)
|
|
||||||
temp_ctrls_switch: bpy.props.BoolProperty(name = "Temp Ctrls Switch", description = "Temp Ctrls Switch", default = True)
|
|
||||||
temp_ctrls_shapes: bpy.props.BoolProperty(name = "Temp Ctrls Shapes", description = "Temp Ctrls Shapes", default = True)
|
|
||||||
|
|
||||||
markers_retimer: bpy.props.BoolProperty(name = "Marker Retimer", description = "Flag when marker retimer turned on", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
relative_cursor: bpy.props.BoolProperty(name = "Relative Cursor Mode", description = "Cursor moves relative to the selection", default = False)
|
|
||||||
|
|
||||||
is_dragging: bpy.props.BoolProperty(default = False)
|
|
||||||
#using Blending sliders in the window manager to avoid undo issues with modal operators
|
|
||||||
inbetween_worldmatrix: bpy.props.FloatProperty(name='Inbetween World Matrix', description="Adds an inbetween of the World Matrix to the Layer's neighbor keyframes", soft_min = -1, soft_max = 1, default=0.0, update = Tools.add_inbetween_worldmatrix, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
blend_mirror: bpy.props.FloatProperty(name='Blend Mirror', description="Blend into the mirrored pose", soft_min = 0, soft_max = 1, default=0, step = 1, update = Tools.blend_to_mirror, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
multikey: bpy.props.PointerProperty(type = MultikeyProperties, options={'LIBRARY_EDITABLE'}, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
class AnimToolBoxGlobalSettings(bpy.types.PropertyGroup):
|
|
||||||
#context.scene.animtoolbox
|
|
||||||
marker_frame_range: bpy.props.BoolProperty(name = "Marker Frame Range", description = "Flag when marker frame range turned on", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bake_frame_range: bpy.props.BoolProperty(name = "Bake Frame Range", description = "Flag when marker bake range turned on", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
# markers_retimer: bpy.props.BoolProperty(name = "Marker Retimer", description = "Flag when marker retimer turned on", default = False, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
keyframes_offset: bpy.props.FloatProperty(name = "Keyframes Offset", description = "Interactive slider to offset keyframes back and forth ", soft_max = 2, soft_min = -2, default = 0, update = Tools.keyframes_offset_slider)
|
|
||||||
rotation_mode: bpy.props.EnumProperty(name = 'Rotation Mode', description="Describes what kind of setup the bone is part of", override = {'LIBRARY_OVERRIDABLE'},
|
|
||||||
items = [('QUATERNION', 'Quaternion','Quaternion Rotation Order - No Gimbal Lock', 0),
|
|
||||||
('XYZ', 'XYZ', 'XYZ Rotation Order', 1), ('XZY', 'XZY','XZY Rotation Order', 2),
|
|
||||||
('YXZ', 'YXZ','YXZ Rotation Order', 3), ('YZX', 'YZX', 'YZX Rotation Order', 4),
|
|
||||||
('ZXY', 'ZXY', 'ZXY Rotation Order', 5), ('ZYX', 'ZYX', 'ZYX Rotation Order', 6),
|
|
||||||
('AXIS_ANGLE', 'AXIS_ANGLE', 'Axis Angle Rotation Order', 7)])
|
|
||||||
|
|
||||||
isolate_pose_mode: bpy.props.BoolProperty(name = "Isolate rig in pose mode", description = "Isolates the rig during pose mode, rigs in object mode are hidden", default = False)
|
|
||||||
active_obj: bpy.props.PointerProperty(name = "Active Object", description = "Current Active Object", type=bpy.types.Object, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
isolated: bpy.props.CollectionProperty(type = IsolatedRigs, override = {'LIBRARY_OVERRIDABLE', 'USE_INSERTION'})
|
|
||||||
|
|
||||||
#Blendings
|
|
||||||
inbetweener : bpy.props.FloatProperty(name='Inbetween Keyframe', description="Adds an inbetween Keyframe between the Layer's neighbor keyframes", soft_min = -1, soft_max = 1, default=0.0, options = set(), update = Tools.add_inbetween_key, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
gizmo_size: bpy.props.IntProperty(name = "Add to Gizmo Size", description = "Addition to Gizmo Size", max = 100, min = -100, default = 10)
|
|
||||||
|
|
||||||
#Copy/Pase Matrix
|
|
||||||
range_type: bpy.props.EnumProperty(name = 'Paste to Frames', description="Paste to current frame or a range of frames.", update = Tools.bake_range_type,
|
|
||||||
items = [('CURRENT', 'Current Frame','Paste Matrix to only current frame', 0),
|
|
||||||
('SELECTED', 'Selected Keyframe','Paste Matrix to only selected keyframes', 1),
|
|
||||||
('RANGE', 'Frame Range','Paste Matrix to a Frame Range', 2)])
|
|
||||||
bake_frame_start: bpy.props.IntProperty(name = "Bake Frame Start", description = "Define the start frame to paste the matrix", min = 0, update = Tools.bake_frame_start_limit)
|
|
||||||
bake_frame_end: bpy.props.IntProperty(name = "Bake Frame End", description = "Define the end frame to paste the matrix", min = 0, update = Tools.bake_frame_end_limit)
|
|
||||||
|
|
||||||
filter_location: bpy.props.BoolVectorProperty(name="Location", description="Filter Location properties", default=(False, False, False), size = 3, options={'HIDDEN'}, update = Tools.filter_name_update)
|
|
||||||
filter_rotation: bpy.props.BoolVectorProperty(name="Rotation", description="Filter Rotation properties", default=(False, False, False, False), size = 4, options={'HIDDEN'}, update = Tools.filter_name_update)
|
|
||||||
filter_scale: bpy.props.BoolVectorProperty(name="Scale", description="Filter Scale properties", default=(False, False, False), size = 3, options={'HIDDEN'}, update = Tools.filter_name_update)
|
|
||||||
#The name displayed on the filter button
|
|
||||||
filter_name: bpy.props.StringProperty(name="Filter Name", description="Change the name of the button while chaging the filter options", default= "", options={'HIDDEN'})
|
|
||||||
filter_custom_props: bpy.props.BoolProperty(name = "Filter Custom Properties", description = "Filter custom properties", default = False)
|
|
||||||
filter_keyframes: bpy.props.BoolProperty(name = "Filter Aelected Keyframes", description = "Filter selected keyframes for specific tools", default = False)
|
|
||||||
|
|
||||||
col_vis: bpy.props.BoolProperty(name = "Animated collections visibility", description = "Display if animated collections are turned on or off", default = False)
|
|
||||||
|
|
||||||
@addon_updater_ops.make_annotations
|
|
||||||
class AnimToolBoxPreferences(bpy.types.AddonPreferences):
|
|
||||||
# this must match the addon name, use '__package__'
|
|
||||||
# when defining this in a submodule of a python package.
|
|
||||||
bl_idname = __package__
|
|
||||||
|
|
||||||
category: bpy.props.StringProperty(
|
|
||||||
name="Tab Category",
|
|
||||||
description="Choose a name for the category of the panel",
|
|
||||||
default="Animation",
|
|
||||||
update=ui.update_panel
|
|
||||||
)
|
|
||||||
|
|
||||||
quick_menu: bpy.props.BoolProperty(name = "Use Quick Menu", description = "Opens header menu with only icon", default = False)
|
|
||||||
riggertoolbox: bpy.props.BoolProperty(name = "RiggerToolBox", description = "Include RiggerToolbox (experimental)", default = False, update = ui.add_riggertoolbox)
|
|
||||||
multikey: bpy.props.BoolProperty(name = "Multikey", description = "Include Multikey for adju\sting multiply keyframes", default = False, update = ui.add_multikey)
|
|
||||||
|
|
||||||
#Temp Ctrls properties
|
|
||||||
in_front: bpy.props.BoolProperty(name = "Always In Front", description = "Set Temp Ctrls to be always in front", default = True)
|
|
||||||
clear_setup : bpy.props.BoolProperty(name = "Clear Selection Before Creating New Temp Ctrls", description = "Clear old setup when adding Temp ctrls to an existing chain", default = False)
|
|
||||||
|
|
||||||
#Editable motion path
|
|
||||||
keyframes_range: bpy.props.IntProperty(name = "Keyframe Range", description = "The range of distance from the keyframes while hovering over them", min = 5, max = 100, default = 15)
|
|
||||||
mp_pref: bpy.props.BoolProperty(name = "Editable Motion Path Colors Theme", description = "Set the Color them of editable motion path visualization", default = False)
|
|
||||||
mp_keyframe_color: bpy.props.FloatVectorProperty(name="Keyframes", subtype='COLOR', default=(1.0, 1.0, 0.0, 1.0), size=4, min=0.0, max=1.0, description="Handles selection color")
|
|
||||||
mp_handle_color: bpy.props.FloatVectorProperty(name="Handles", subtype='COLOR', default=(1.0, 0.8, 0.2, 1.0), size=4, min=0.0, max=1.0, description="Handles selection color")
|
|
||||||
mp_remove_color: bpy.props.FloatVectorProperty(name="Remove Keyframes", subtype='COLOR', default=(0.0, 0.5, 1.0, 1.0), size=4, min=0.0, max=1.0, description="Keyframe color displayed before removing")
|
|
||||||
mp_hover_color: bpy.props.FloatVectorProperty(name="Hover", subtype='COLOR', default=(1.0, 0.4, 0.2, 1.0), size=4, min=0.0, max=1.0, description="Color during Hovering")
|
|
||||||
mp_handle_selection_color: bpy.props.FloatVectorProperty(name="Handles Selection", subtype='COLOR', default=(0.8, 0.65, 0.6, 0.8), size=4, min=0.0, max=1.0, description="Handles selection color")
|
|
||||||
mp_key_selection_color: bpy.props.FloatVectorProperty(name="Keyframe Selection", subtype='COLOR', default=(0.8, 0.8, 0.6, 0.8), size=4, min=0.0, max=1.0, description="Keyframe selection color")
|
|
||||||
|
|
||||||
# addon updater preferences from `__init__`, be sure to copy all of them
|
|
||||||
auto_check_update: bpy.props.BoolProperty(
|
|
||||||
name = "Auto-check for Update",
|
|
||||||
description = "If enabled, auto-check for updates using an interval",
|
|
||||||
default = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
updater_interval_months: bpy.props.IntProperty(
|
|
||||||
name='Months',
|
|
||||||
description = "Number of months between checking for updates",
|
|
||||||
default=0,
|
|
||||||
min=0
|
|
||||||
)
|
|
||||||
updater_interval_days: bpy.props.IntProperty(
|
|
||||||
name='Days',
|
|
||||||
description = "Number of days between checking for updates",
|
|
||||||
default=7,
|
|
||||||
min=0,
|
|
||||||
|
|
||||||
)
|
|
||||||
updater_interval_hours: bpy.props.IntProperty(
|
|
||||||
name='Hours',
|
|
||||||
description = "Number of hours between checking for updates",
|
|
||||||
default=0,
|
|
||||||
min=0,
|
|
||||||
max=23
|
|
||||||
)
|
|
||||||
updater_interval_minutes: bpy.props.IntProperty(
|
|
||||||
name='Minutes',
|
|
||||||
description = "Number of minutes between checking for updates",
|
|
||||||
default=0,
|
|
||||||
min=0,
|
|
||||||
max=59
|
|
||||||
)
|
|
||||||
|
|
||||||
#Draw the UI in the preferences
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
addon_updater_ops.update_settings_ui(self, context)
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
col = row.column()
|
|
||||||
|
|
||||||
col.label(text="Tab Category:")
|
|
||||||
col.prop(self, "category", text="")
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
col = layout.column()
|
|
||||||
col.prop(self, "quick_menu", text="Use Quick Icons Menu")
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
box = layout.box()
|
|
||||||
row = box.row()
|
|
||||||
row.label(text = 'Temp Ctrls: ')
|
|
||||||
row = box.row()
|
|
||||||
row.prop(self, 'clear_setup')
|
|
||||||
row.prop(self, 'in_front')
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
box = layout.box()
|
|
||||||
col = box.column()
|
|
||||||
col.prop(self, 'mp_pref', icon = 'DOWNARROW_HLT', text = 'Editable Motion Path Preferences')
|
|
||||||
if self.mp_pref:
|
|
||||||
col.prop(self, 'keyframes_range', text = 'Keyframe Distance Range')
|
|
||||||
col.label(text = 'Colors Theme')
|
|
||||||
row = box.row()
|
|
||||||
row.prop(self, 'mp_keyframe_color')
|
|
||||||
row.prop(self, 'mp_handle_color')
|
|
||||||
row.prop(self, 'mp_remove_color')
|
|
||||||
row = box.row()
|
|
||||||
row.prop(self, 'mp_hover_color')
|
|
||||||
row.prop(self, 'mp_key_selection_color')
|
|
||||||
row.prop(self, 'mp_handle_selection_color')
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
col = layout.column()
|
|
||||||
col.label(text = 'Include Extras: ')
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(self, "multikey", text="Multikey - Edit Multiply keyframes")
|
|
||||||
row.prop(self, "riggertoolbox", text="RiggerToolBox (Experimental)")
|
|
||||||
|
|
||||||
@persistent
|
|
||||||
def loadanimtoolbox_pre(self, context):
|
|
||||||
scene = bpy.context.scene
|
|
||||||
dns = bpy.app.driver_namespace
|
|
||||||
if scene.animtoolbox.bake_frame_range:
|
|
||||||
scene.animtoolbox.bake_frame_range = False
|
|
||||||
|
|
||||||
if scene.emp.motion_path:
|
|
||||||
scene.emp.motion_path = False
|
|
||||||
bpy.context.workspace.status_text_set(None)
|
|
||||||
if 'mp_dh' in dns:
|
|
||||||
bpy.types.SpaceView3D.draw_handler_remove(dns['mp_dh'], 'WINDOW')
|
|
||||||
bpy.app.driver_namespace.pop('mp_dh')
|
|
||||||
bpy.context.scene.emp.selected_keyframes = '{}'
|
|
||||||
|
|
||||||
if 'markers_retimer_dh' in dns:
|
|
||||||
bpy.types.SpaceView3D.draw_handler_remove(dns['markers_retimer_dh'], 'WINDOW')
|
|
||||||
bpy.app.driver_namespace.pop('markers_retimer_dh')
|
|
||||||
|
|
||||||
#remove the motion path app handler if it's still inside
|
|
||||||
if emp.mp_value_update in bpy.app.handlers.depsgraph_update_post:
|
|
||||||
bpy.app.handlers.depsgraph_update_post.remove(emp.mp_value_update)
|
|
||||||
if emp.mp_frame_change in bpy.app.handlers.frame_change_post:
|
|
||||||
bpy.app.handlers.frame_change_post.remove(emp.mp_frame_change)
|
|
||||||
if emp.mp_undo_update in bpy.app.handlers.undo_pre:
|
|
||||||
bpy.app.handlers.undo_pre.remove(emp.mp_undo_update)
|
|
||||||
|
|
||||||
@persistent
|
|
||||||
def loadanimtoolbox_post(self, context):
|
|
||||||
scene = bpy.context.scene
|
|
||||||
dns = bpy.app.driver_namespace
|
|
||||||
if scene.animtoolbox.isolate_pose_mode:
|
|
||||||
if Display.isolate_pose_mode not in bpy.app.handlers.depsgraph_update_pre:
|
|
||||||
bpy.app.handlers.depsgraph_update_pre.append(Display.isolate_pose_mode)
|
|
||||||
|
|
||||||
if scene.emp.motion_path:
|
|
||||||
scene.emp.motion_path = False
|
|
||||||
bpy.context.workspace.status_text_set(None)
|
|
||||||
if 'mp_dh' in dns:
|
|
||||||
bpy.types.SpaceView3D.draw_handler_remove(dns['mp_dh'], 'WINDOW')
|
|
||||||
bpy.app.driver_namespace.pop('mp_dh')
|
|
||||||
# Reset keyframe selection for motion paths it is not used in window manager
|
|
||||||
# Because it is used for undo
|
|
||||||
bpy.context.scene.emp.selected_keyframes = '{}'
|
|
||||||
|
|
||||||
Tools.selection_order(self, context)
|
|
||||||
|
|
||||||
classes = (TempCtrlsItems, TempCtrlsOrgIds, TempCtrlsObjectSetups, TempCtrlsSceneSettings,TempCtrlsBoneSettings, MultikeyProperties,
|
|
||||||
IsolatedRigs, AnimToolBoxObjectSettings, AnimToolBoxUILayout, AnimToolBoxGlobalSettings) + ui.classes
|
|
||||||
|
|
||||||
addon_keymaps = []
|
|
||||||
|
|
||||||
def register():
|
|
||||||
# Note that preview collections returned by bpy.utils.previews
|
|
||||||
# are regular py objects - you can use them to store custom data.
|
|
||||||
|
|
||||||
addon_updater_ops.register(bl_info)
|
|
||||||
register_class(AnimToolBoxPreferences)
|
|
||||||
addon_updater_ops.make_annotations(AnimToolBoxPreferences) # to avoid blender 2.8 warnings
|
|
||||||
TempCtrls.register()
|
|
||||||
Tools.register()
|
|
||||||
Display.register()
|
|
||||||
emp.register()
|
|
||||||
|
|
||||||
ui.register_custom_icon()
|
|
||||||
|
|
||||||
for cls in classes:
|
|
||||||
# print(cls)
|
|
||||||
register_class(cls)
|
|
||||||
|
|
||||||
bpy.types.Scene.btc = bpy.props.PointerProperty(type = TempCtrlsSceneSettings, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bpy.types.PoseBone.btc = bpy.props.PointerProperty(type = TempCtrlsBoneSettings, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bpy.types.Object.animtoolbox = bpy.props.PointerProperty(type = AnimToolBoxObjectSettings, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bpy.types.Scene.animtoolbox = bpy.props.PointerProperty(type = AnimToolBoxGlobalSettings, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
bpy.types.WindowManager.atb_ui = bpy.props.PointerProperty(type = AnimToolBoxUILayout, override = {'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
ui.update_panel(None, bpy.context)
|
|
||||||
ui.add_multikey(None, bpy.context)
|
|
||||||
ui.add_riggertoolbox(None, bpy.context)
|
|
||||||
|
|
||||||
if loadanimtoolbox_pre not in bpy.app.handlers.load_pre:
|
|
||||||
bpy.app.handlers.load_pre.append(loadanimtoolbox_pre)
|
|
||||||
if loadanimtoolbox_post not in bpy.app.handlers.load_post:
|
|
||||||
bpy.app.handlers.load_post.append(loadanimtoolbox_post)
|
|
||||||
|
|
||||||
if Tools.selection_order not in bpy.app.handlers.depsgraph_update_post:
|
|
||||||
bpy.app.handlers.depsgraph_update_post.append(Tools.selection_order)
|
|
||||||
|
|
||||||
#Make sure TAB hotkey in the NLA goes into full stack mode
|
|
||||||
wm = bpy.context.window_manager
|
|
||||||
kc = wm.keyconfigs.addon
|
|
||||||
km = kc.keymaps.new(name= '3D View', space_type= 'VIEW_3D')
|
|
||||||
if 'view3d.gizmo_size_up' not in km.keymap_items:
|
|
||||||
kmi = km.keymap_items.new('view3d.gizmo_size_up', type= 'NUMPAD_PLUS', value= 'PRESS', alt = True, repeat = True)
|
|
||||||
addon_keymaps.append((km, kmi))
|
|
||||||
if 'view3d.gizmo_size_down' not in km.keymap_items:
|
|
||||||
kmi = km.keymap_items.new('view3d.gizmo_size_down', type= 'NUMPAD_MINUS', value= 'PRESS', alt = True, repeat = True)
|
|
||||||
addon_keymaps.append((km, kmi))
|
|
||||||
|
|
||||||
#Add Tools to the Toolbar
|
|
||||||
bpy.utils.register_tool(ui.KeyframeOffsetTool, separator=True)
|
|
||||||
|
|
||||||
#Add tools to the menu
|
|
||||||
bpy.types.VIEW3D_MT_editor_menus.append(ui.draw_menu)
|
|
||||||
|
|
||||||
def unregister():
|
|
||||||
for pcoll in ui.preview_collections.values():
|
|
||||||
bpy.utils.previews.remove(pcoll)
|
|
||||||
ui.preview_collections.clear()
|
|
||||||
|
|
||||||
#addon_updater_ops.unregister()
|
|
||||||
addon_updater_ops.unregister()
|
|
||||||
unregister_class(AnimToolBoxPreferences)
|
|
||||||
|
|
||||||
TempCtrls.unregister()
|
|
||||||
# Rigger_Toolbox.unregister()
|
|
||||||
Tools.unregister()
|
|
||||||
Display.unregister()
|
|
||||||
emp.unregister()
|
|
||||||
|
|
||||||
ui.add_multikey(None, bpy.context)
|
|
||||||
ui.add_riggertoolbox(None, bpy.context)
|
|
||||||
|
|
||||||
for cls in classes:
|
|
||||||
unregister_class(cls)
|
|
||||||
|
|
||||||
bpy.utils.unregister_tool(ui.KeyframeOffsetTool)
|
|
||||||
|
|
||||||
#Remove the header menu ui
|
|
||||||
bpy.types.VIEW3D_MT_editor_menus.remove(ui.draw_menu)
|
|
||||||
|
|
||||||
del bpy.types.Scene.btc
|
|
||||||
# del bpy.types.Bone.btc
|
|
||||||
del bpy.types.Object.animtoolbox
|
|
||||||
del bpy.types.Scene.animtoolbox
|
|
||||||
if hasattr(bpy.types.Object, 'keyframes_offset'):
|
|
||||||
del bpy.types.Object.keyframes_offset
|
|
||||||
if hasattr(bpy.types.PoseBone, 'keyframes_offset'):
|
|
||||||
del bpy.types.PoseBone.keyframes_offset
|
|
||||||
|
|
||||||
if loadanimtoolbox_pre in bpy.app.handlers.load_pre:
|
|
||||||
bpy.app.handlers.load_pre.remove(loadanimtoolbox_pre)
|
|
||||||
if loadanimtoolbox_post in bpy.app.handlers.load_post:
|
|
||||||
bpy.app.handlers.load_post.remove(loadanimtoolbox_post)
|
|
||||||
if Tools.selection_order in bpy.app.handlers.depsgraph_update_post:
|
|
||||||
bpy.app.handlers.depsgraph_update_post.remove(Tools.selection_order)
|
|
||||||
|
|
||||||
for km, kmi in addon_keymaps:
|
|
||||||
km.keymap_items.remove(kmi)
|
|
||||||
addon_keymaps.clear()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
register()
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-16
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"last_check": "2026-02-09 15:54:54.419194",
|
|
||||||
"backup_date": "September-23-2025",
|
|
||||||
"update_ready": true,
|
|
||||||
"ignore": false,
|
|
||||||
"just_restored": false,
|
|
||||||
"just_updated": false,
|
|
||||||
"version_text": {
|
|
||||||
"link": "https://gitlab.com/api/v4/projects/45739913/repository/archive.zip?sha=7a9ad24a463bf1c8ae095ec853409979344e0738",
|
|
||||||
"version": [
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user