mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 20:00:53 +00:00
feat(auto_export): exploration, changes, debug etc for change detection weirdness
This commit is contained in:
parent
11e8786b59
commit
64fd308fd3
@ -116,7 +116,6 @@ classes = [
|
|||||||
GLTF_PT_auto_export_SidePanel,
|
GLTF_PT_auto_export_SidePanel,
|
||||||
|
|
||||||
AutoExportTracker,
|
AutoExportTracker,
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def glTF2_pre_export_callback(data):
|
def glTF2_pre_export_callback(data):
|
||||||
@ -191,10 +190,6 @@ def register():
|
|||||||
bpy.types.TOPBAR_MT_file_export.append(menu_func_import)
|
bpy.types.TOPBAR_MT_file_export.append(menu_func_import)
|
||||||
bpy.types.WindowManager.gltf_settings_backup = StringProperty(default="")
|
bpy.types.WindowManager.gltf_settings_backup = StringProperty(default="")
|
||||||
|
|
||||||
# FIXME: perhaps move this to tracker
|
|
||||||
bpy.types.WindowManager.exports_count = IntProperty(default=0)
|
|
||||||
|
|
||||||
|
|
||||||
"""bpy.utils.register_class(AutoExportExtensionProperties)
|
"""bpy.utils.register_class(AutoExportExtensionProperties)
|
||||||
bpy.types.Scene.AutoExportExtensionProperties = bpy.props.PointerProperty(type=AutoExportExtensionProperties)"""
|
bpy.types.Scene.AutoExportExtensionProperties = bpy.props.PointerProperty(type=AutoExportExtensionProperties)"""
|
||||||
|
|
||||||
@ -207,7 +202,6 @@ def unregister():
|
|||||||
bpy.app.handlers.save_post.remove(post_save)
|
bpy.app.handlers.save_post.remove(post_save)
|
||||||
|
|
||||||
"""bpy.utils.unregister_class(AutoExportExtensionProperties)"""
|
"""bpy.utils.unregister_class(AutoExportExtensionProperties)"""
|
||||||
del bpy.types.WindowManager.exports_count
|
|
||||||
|
|
||||||
if "gltf_auto_export" == "__main__":
|
if "gltf_auto_export" == "__main__":
|
||||||
register()
|
register()
|
||||||
|
@ -109,20 +109,23 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
|
|
||||||
main_scenes_to_export = [scene_name for scene_name in main_scene_names if not export_change_detection or changed_export_parameters or scene_name in changes_per_scene.keys() or not check_if_blueprint_on_disk(scene_name, export_levels_path, gltf_extension)]
|
main_scenes_to_export = [scene_name for scene_name in main_scene_names if not export_change_detection or changed_export_parameters or scene_name in changes_per_scene.keys() or not check_if_blueprint_on_disk(scene_name, export_levels_path, gltf_extension)]
|
||||||
|
|
||||||
bpy.context.window_manager.exports_count = len(collections_to_export)
|
bpy.context.window_manager.auto_export_tracker.exports_count = len(collections_to_export)
|
||||||
bpy.context.window_manager.exports_count += len(main_scenes_to_export)
|
bpy.context.window_manager.auto_export_tracker.exports_count += len(main_scenes_to_export)
|
||||||
if export_materials_library:
|
if export_materials_library:
|
||||||
bpy.context.window_manager.exports_count += 1
|
bpy.context.window_manager.auto_export_tracker.exports_count += 1
|
||||||
|
|
||||||
print("--------------")
|
print("-------------------------------")
|
||||||
print("collections: all:", collections)
|
print("collections: all:", collections)
|
||||||
print("collections: changed:", changed_collections)
|
print("collections: changed:", changed_collections)
|
||||||
print("collections: not found on disk:", collections_not_on_disk)
|
print("collections: not found on disk:", collections_not_on_disk)
|
||||||
print("collections: in library:", library_collections)
|
print("collections: in library:", library_collections)
|
||||||
print("collections: to export:", collections_to_export)
|
print("collections: to export:", collections_to_export)
|
||||||
print("collections: per_scene:", collections_per_scene)
|
print("collections: per_scene:", collections_per_scene)
|
||||||
print("--------------")
|
print("-------------------------------")
|
||||||
print("MAIN SCENES TO EXPORT", main_scenes_to_export)
|
print("BLUEPRINTS: to export:", collections_to_export)
|
||||||
|
print("-------------------------------")
|
||||||
|
print("MAIN SCENES: to export:", main_scenes_to_export)
|
||||||
|
print("-------------------------------")
|
||||||
|
|
||||||
|
|
||||||
# backup current active scene
|
# backup current active scene
|
||||||
@ -131,6 +134,7 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
old_selections = bpy.context.selected_objects
|
old_selections = bpy.context.selected_objects
|
||||||
|
|
||||||
# first export any main/level/world scenes
|
# first export any main/level/world scenes
|
||||||
|
if len(main_scenes_to_export) > 0:
|
||||||
print("export MAIN scenes")
|
print("export MAIN scenes")
|
||||||
for scene_name in main_scene_names:
|
for scene_name in main_scene_names:
|
||||||
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
||||||
@ -142,8 +146,8 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
|
|
||||||
# now deal with blueprints/collections
|
# now deal with blueprints/collections
|
||||||
do_export_library_scene = not export_change_detection or changed_export_parameters or len(collections_to_export) > 0 # export_library_scene_name in changes_per_scene.keys()
|
do_export_library_scene = not export_change_detection or changed_export_parameters or len(collections_to_export) > 0 # export_library_scene_name in changes_per_scene.keys()
|
||||||
print("export LIBRARY")
|
|
||||||
if do_export_library_scene:
|
if do_export_library_scene:
|
||||||
|
print("export LIBRARY")
|
||||||
# we only want to go through the library scenes where our collections to export are present
|
# we only want to go through the library scenes where our collections to export are present
|
||||||
for (scene_name, collections_to_export) in collections_per_scene.items():
|
for (scene_name, collections_to_export) in collections_per_scene.items():
|
||||||
print(" exporting collections from scene:", scene_name)
|
print(" exporting collections from scene:", scene_name)
|
||||||
@ -164,6 +168,8 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
|||||||
for scene_name in main_scene_names:
|
for scene_name in main_scene_names:
|
||||||
export_main_scene(bpy.data.scenes[scene_name], folder_path, addon_prefs, [])
|
export_main_scene(bpy.data.scenes[scene_name], folder_path, addon_prefs, [])
|
||||||
|
|
||||||
|
print("we are done with all export work",bpy.context.window_manager.auto_export_tracker.change_detection_enabled)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
@ -168,13 +168,13 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
|||||||
auto_settings_changed = sorted(json.loads(previous_auto_settings.as_string()).items()) != sorted(json.loads(current_auto_settings.as_string()).items()) if current_auto_settings != None else False
|
auto_settings_changed = sorted(json.loads(previous_auto_settings.as_string()).items()) != sorted(json.loads(current_auto_settings.as_string()).items()) if current_auto_settings != None else False
|
||||||
gltf_settings_changed = sorted(json.loads(previous_gltf_settings.as_string()).items()) != sorted(json.loads(current_gltf_settings.as_string()).items()) if current_gltf_settings != None else False
|
gltf_settings_changed = sorted(json.loads(previous_gltf_settings.as_string()).items()) != sorted(json.loads(current_gltf_settings.as_string()).items()) if current_gltf_settings != None else False
|
||||||
|
|
||||||
print("auto settings previous", sorted(json.loads(previous_auto_settings.as_string()).items()))
|
"""print("auto settings previous", sorted(json.loads(previous_auto_settings.as_string()).items()))
|
||||||
print("auto settings current", sorted(json.loads(current_auto_settings.as_string()).items()))
|
print("auto settings current", sorted(json.loads(current_auto_settings.as_string()).items()))
|
||||||
print("auto_settings_changed", auto_settings_changed)
|
print("auto_settings_changed", auto_settings_changed)
|
||||||
|
|
||||||
print("gltf settings previous", sorted(json.loads(previous_gltf_settings.as_string()).items()))
|
print("gltf settings previous", sorted(json.loads(previous_gltf_settings.as_string()).items()))
|
||||||
print("gltf settings current", sorted(json.loads(current_gltf_settings.as_string()).items()))
|
print("gltf settings current", sorted(json.loads(current_gltf_settings.as_string()).items()))
|
||||||
print("gltf_settings_changed", gltf_settings_changed)
|
print("gltf_settings_changed", gltf_settings_changed)"""
|
||||||
|
|
||||||
changed = auto_settings_changed or gltf_settings_changed
|
changed = auto_settings_changed or gltf_settings_changed
|
||||||
# now write the current settings to the "previous settings"
|
# now write the current settings to the "previous settings"
|
||||||
@ -191,6 +191,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
|||||||
return changed
|
return changed
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
print("execute")
|
||||||
# disable change detection while the operator runs
|
# disable change detection while the operator runs
|
||||||
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
bpy.context.window_manager.auto_export_tracker.disable_change_detection()
|
||||||
if self.direct_mode:
|
if self.direct_mode:
|
||||||
@ -206,12 +207,14 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
|||||||
params_changed = self.did_export_settings_change()
|
params_changed = self.did_export_settings_change()
|
||||||
auto_export(changes_per_scene, params_changed, self)
|
auto_export(changes_per_scene, params_changed, self)
|
||||||
# cleanup
|
# cleanup
|
||||||
if bpy.context.window_manager.exports_count == 0: # we need this in case there was nothing to export, to make sure change detection is enabled again
|
print("AUTO EXPORT DONE")
|
||||||
print("YOLOOO")
|
if bpy.context.window_manager.auto_export_tracker.exports_count == 0: # we need this in case there was nothing to export, to make sure change detection is enabled again
|
||||||
bpy.context.window_manager.auto_export_tracker.enable_change_detection()
|
pass #print("YOLOOO")
|
||||||
|
#py.context.window_manager.auto_export_tracker.enable_change_detection()
|
||||||
|
#bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
||||||
#bpy.context.window_manager.auto_export_tracker.enable_change_detection()
|
#bpy.context.window_manager.auto_export_tracker.enable_change_detection()
|
||||||
# FIXME: wrong logic, this should be called only in an glTF2_post_export_callback
|
# FIXME: wrong logic, this should be called only in an glTF2_post_export_callback
|
||||||
bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
#bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
||||||
else:
|
else:
|
||||||
print("auto export disabled, skipping")
|
print("auto export disabled, skipping")
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import (PropertyGroup)
|
from bpy.types import (PropertyGroup)
|
||||||
from bpy.props import (PointerProperty)
|
from bpy.props import (PointerProperty, IntProperty)
|
||||||
|
|
||||||
from .internals import CollectionsToExport
|
from .internals import CollectionsToExport
|
||||||
|
|
||||||
@ -15,6 +15,12 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
last_operator = None
|
last_operator = None
|
||||||
dummy_file_path = ""
|
dummy_file_path = ""
|
||||||
|
|
||||||
|
exports_count : IntProperty(
|
||||||
|
name='exports_count',
|
||||||
|
description='Number of exports in progress',
|
||||||
|
default=0
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(cls):
|
def register(cls):
|
||||||
bpy.types.WindowManager.auto_export_tracker = PointerProperty(type=AutoExportTracker)
|
bpy.types.WindowManager.auto_export_tracker = PointerProperty(type=AutoExportTracker)
|
||||||
@ -53,7 +59,7 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def deps_update_handler(cls, scene, depsgraph):
|
def deps_update_handler(cls, scene, depsgraph):
|
||||||
print("change detection enabled", cls.change_detection_enabled)
|
print("change detection enabled", cls.change_detection_enabled, bpy.context.window_manager.auto_export_tracker.change_detection_enabled)
|
||||||
active_operator = bpy.context.active_operator
|
active_operator = bpy.context.active_operator
|
||||||
if active_operator:
|
if active_operator:
|
||||||
# print("Operator", active_operator.bl_label, active_operator.bl_idname)
|
# print("Operator", active_operator.bl_label, active_operator.bl_idname)
|
||||||
@ -74,8 +80,8 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
active_operator.will_save_settings = True
|
active_operator.will_save_settings = True
|
||||||
active_operator.auto_export = True
|
active_operator.auto_export = True
|
||||||
|
|
||||||
if scene.name != "temp_scene":
|
if not scene.name.startswith("__temp_scene"):
|
||||||
# print("depsgraph_update_post", scene.name)
|
print("depsgraph_update_post", scene.name)
|
||||||
changed_scene = scene.name or ""
|
changed_scene = scene.name or ""
|
||||||
|
|
||||||
# only deal with changes if we are no in the mids of saving/exporting
|
# only deal with changes if we are no in the mids of saving/exporting
|
||||||
@ -90,7 +96,8 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
if isinstance(obj.id, bpy.types.Object):
|
if isinstance(obj.id, bpy.types.Object):
|
||||||
# get the actual object
|
# get the actual object
|
||||||
object = bpy.data.objects[obj.id.name]
|
object = bpy.data.objects[obj.id.name]
|
||||||
#print("changed object", obj.id.name)
|
print("changed object", obj.id.name)
|
||||||
|
print("FOO","transforms", obj.is_updated_transform, "geometry", obj.is_updated_geometry)
|
||||||
cls.changed_objects_per_scene[scene.name][obj.id.name] = object
|
cls.changed_objects_per_scene[scene.name][obj.id.name] = object
|
||||||
elif isinstance(obj.id, bpy.types.Material): # or isinstance(obj.id, bpy.types.ShaderNodeTree):
|
elif isinstance(obj.id, bpy.types.Material): # or isinstance(obj.id, bpy.types.ShaderNodeTree):
|
||||||
# print("changed material", obj.id, "scene", scene.name,)
|
# print("changed material", obj.id, "scene", scene.name,)
|
||||||
@ -114,19 +121,27 @@ class AutoExportTracker(PropertyGroup):
|
|||||||
for update in depsgraph.updates:
|
for update in depsgraph.updates:
|
||||||
print("update", update)"""
|
print("update", update)"""
|
||||||
|
|
||||||
def disable_change_detection(self,):
|
def disable_change_detection(self):
|
||||||
|
print("disable change detection")
|
||||||
self.change_detection_enabled = False
|
self.change_detection_enabled = False
|
||||||
self.__class__.change_detection_enabled = False
|
self.__class__.change_detection_enabled = False
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def enable_change_detection(self):
|
def enable_change_detection(self):
|
||||||
|
print("enable change detection")
|
||||||
self.change_detection_enabled = True
|
self.change_detection_enabled = True
|
||||||
self.__class__.change_detection_enabled = True
|
self.__class__.change_detection_enabled = True
|
||||||
|
# bpy.context.window_manager.auto_export_tracker.change_detection_enabled = True
|
||||||
|
print("bpy.context.window_manager.auto_export_tracker.change_detection_enabled", bpy.context.window_manager.auto_export_tracker.change_detection_enabled)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def export_finished(self):
|
def export_finished(self):
|
||||||
print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHH export_finished")
|
print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHH export_finished")
|
||||||
bpy.context.window_manager.exports_count -= 1
|
bpy.context.window_manager.auto_export_tracker.exports_count -= 1
|
||||||
if bpy.context.window_manager.exports_count == 0:
|
if bpy.context.window_manager.auto_export_tracker.exports_count == 0:
|
||||||
print("YOLOOO")
|
#print("preparing to reset change detection")
|
||||||
|
#bpy.app.timers.register(bpy.context.window_manager.auto_export_tracker.enable_change_detection, first_interval=1)
|
||||||
|
|
||||||
self.enable_change_detection()
|
self.enable_change_detection()
|
||||||
|
return None
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import mathutils
|
||||||
import pytest
|
import pytest
|
||||||
import shutil
|
import shutil
|
||||||
|
import pathlib
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def setup_data(request):
|
def setup_data(request):
|
||||||
@ -133,9 +135,20 @@ def test_export_changed_parameters(setup_data):
|
|||||||
models_library_path = os.path.join(models_path, "library")
|
models_library_path = os.path.join(models_path, "library")
|
||||||
model_library_file_paths = list(map(lambda file_name: os.path.join(models_library_path, file_name), sorted(os.listdir(models_library_path))))
|
model_library_file_paths = list(map(lambda file_name: os.path.join(models_library_path, file_name), sorted(os.listdir(models_library_path))))
|
||||||
modification_times_first = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
modification_times_first = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
||||||
#print("files", model_library_file_paths)
|
|
||||||
|
mapped_files_to_timestamps_and_index = {}
|
||||||
|
for (index, file_path) in enumerate(model_library_file_paths+ [world_file_path]):
|
||||||
|
file_path = pathlib.Path(file_path).stem
|
||||||
|
mapped_files_to_timestamps_and_index[file_path] = (modification_times_first[index], index)
|
||||||
|
print("files", mapped_files_to_timestamps_and_index)
|
||||||
#print("mod times", modification_times_first)
|
#print("mod times", modification_times_first)
|
||||||
|
|
||||||
|
# export again with no changes
|
||||||
|
print("----------------")
|
||||||
|
print("no changes")
|
||||||
|
print("----------------")
|
||||||
|
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
auto_export=True,
|
||||||
direct_mode=True,
|
direct_mode=True,
|
||||||
@ -154,7 +167,7 @@ def test_export_changed_parameters(setup_data):
|
|||||||
print("main scene change")
|
print("main scene change")
|
||||||
print("----------------")
|
print("----------------")
|
||||||
|
|
||||||
#py.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
||||||
bpy.data.objects["Cube"].location = [1, 0, 0]
|
bpy.data.objects["Cube"].location = [1, 0, 0]
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
@ -169,6 +182,14 @@ def test_export_changed_parameters(setup_data):
|
|||||||
|
|
||||||
modification_times = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
modification_times = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
||||||
assert modification_times != modification_times_first
|
assert modification_times != modification_times_first
|
||||||
|
# only the "world" file should have changed
|
||||||
|
world_file_index = mapped_files_to_timestamps_and_index["World"][1]
|
||||||
|
other_files_modification_times = [value for index, value in enumerate(modification_times) if index not in [world_file_index]]
|
||||||
|
other_files_modification_times_first = [value for index, value in enumerate(modification_times_first) if index not in [world_file_index]]
|
||||||
|
|
||||||
|
assert modification_times[world_file_index] != modification_times_first[world_file_index]
|
||||||
|
assert other_files_modification_times == other_files_modification_times_first
|
||||||
|
# reset the comparing
|
||||||
modification_times_first = modification_times
|
modification_times_first = modification_times
|
||||||
|
|
||||||
|
|
||||||
@ -176,6 +197,7 @@ def test_export_changed_parameters(setup_data):
|
|||||||
print("----------------")
|
print("----------------")
|
||||||
print("library change")
|
print("library change")
|
||||||
print("----------------")
|
print("----------------")
|
||||||
|
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
||||||
|
|
||||||
bpy.data.objects["Blueprint1_mesh"].location = [1, 2, 1]
|
bpy.data.objects["Blueprint1_mesh"].location = [1, 2, 1]
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
@ -190,14 +212,31 @@ def test_export_changed_parameters(setup_data):
|
|||||||
|
|
||||||
modification_times = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
modification_times = list(map(lambda file_path: os.path.getmtime(file_path), model_library_file_paths + [world_file_path]))
|
||||||
assert modification_times != modification_times_first
|
assert modification_times != modification_times_first
|
||||||
|
# only the "world" file should have changed
|
||||||
|
blueprint1_file_index = mapped_files_to_timestamps_and_index["Blueprint1"][1]
|
||||||
|
other_files_modification_times = [value for index, value in enumerate(modification_times) if index not in [blueprint1_file_index]]
|
||||||
|
other_files_modification_times_first = [value for index, value in enumerate(modification_times_first) if index not in [blueprint1_file_index]]
|
||||||
|
|
||||||
|
assert modification_times[blueprint1_file_index] != modification_times_first[blueprint1_file_index]
|
||||||
|
assert other_files_modification_times == other_files_modification_times_first
|
||||||
|
# reset the comparing
|
||||||
modification_times_first = modification_times
|
modification_times_first = modification_times
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# now same, but using an operator
|
# now same, but using an operator
|
||||||
print("----------------")
|
print("----------------")
|
||||||
print("change using operator")
|
print("change using operator")
|
||||||
print("----------------")
|
print("----------------")
|
||||||
|
bpy.context.window_manager.auto_export_tracker.enable_change_detection() # FIXME: should not be needed, but ..
|
||||||
|
|
||||||
|
with bpy.context.temp_override(active_object=bpy.data.objects["Cube"]):
|
||||||
|
print("translate using operator")
|
||||||
|
bpy.ops.transform.translate(value=mathutils.Vector((2.0, 1.0, -5.0)))
|
||||||
|
bpy.ops.transform.rotate(value=0.378874, constraint_axis=(False, False, True), mirror=False, proportional_edit_falloff='SMOOTH', proportional_size=1)
|
||||||
|
bpy.ops.object.transform_apply()
|
||||||
|
bpy.ops.transform.translate(value=(0.5, 0, 0), constraint_axis=(True, False, False))
|
||||||
|
|
||||||
bpy.ops.transform.translate(value=(20.0, 0.0, 0.0))
|
|
||||||
|
|
||||||
auto_export_operator(
|
auto_export_operator(
|
||||||
auto_export=True,
|
auto_export=True,
|
||||||
|
Loading…
Reference in New Issue
Block a user