Skip to content

Latest commit

 

History

History
120 lines (110 loc) · 6.15 KB

File metadata and controls

120 lines (110 loc) · 6.15 KB
Error in user YAML: (<unknown>): found a tab character that violate indentation while scanning a plain scalar at line 3 column 3
---
- oeasy Python 0722
- 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。
- 本教程同步发布在: 
	- 个人网站: `https://oeasy.org` 
	- 蓝桥云课: `https://www.lanqiao.cn/courses/3584` 
	- GitHub: `https://github.com/overmind1980/oeasy-python-tutorial` 
	- Gitee: `https://gitee.com/overmind1980/oeasypython` 
---

图片描述

import bpy
import os

# 获取当前blender文件路径,复原脚本保存在同目录
file_path = bpy.data.filepath
save_path = "/tmp/recover_scene.py"

# 排除默认对象(避免冗余)
exclude_objs = {"Cube", "Light", "Camera"}

# 生成复原代码的内容
recover_code = [
    "import bpy\n",
    "# 清空当前场景(先删旧对象)\n",
    "bpy.ops.object.select_all(action='SELECT')\n",
    "bpy.ops.object.delete()\n",
    "bpy.ops.outliner.orphans_purge()\n\n"
]

# 1. 遍历并生成Mesh对象(含坐标/旋转/缩放)
recover_code.append("===== 创建Mesh对象 =====\n")
for obj in bpy.data.objects:
    if obj.type == 'MESH' and obj.name not in exclude_objs:
        mesh = obj.data
        # 写入Mesh创建
        recover_code.append(f"# 创建{obj.name} Mesh\n")
        recover_code.append(f"mesh_{obj.name} = bpy.data.meshes.new(name='{mesh.name}')\n")
        recover_code.append(f"obj_{obj.name} = bpy.data.objects.new('{obj.name}', mesh_{obj.name})\n")
        recover_code.append(f"bpy.context.collection.objects.link(obj_{obj.name})\n")
        # 写入顶点/面数据(核心复原)
        vertices = [tuple(v.co) for v in mesh.vertices]
        faces = [tuple(p.vertices) for p in mesh.polygons]
        recover_code.append(f"mesh_{obj.name}.from_pydata({vertices}, [], {faces})\n")
        # 写入位置/旋转/缩放
        recover_code.append(f"obj_{obj.name}.location = {tuple(obj.location)}\n")
        recover_code.append(f"obj_{obj.name}.rotation_euler = {tuple(obj.rotation_euler)}\n")
        recover_code.append(f"obj_{obj.name}.scale = {tuple(obj.scale)}\n\n")

# 2. 遍历并生成Camera
recover_code.append("===== 创建相机 =====\n")
for cam in bpy.data.objects:
    if cam.type == 'CAMERA' and cam.name not in exclude_objs:
        recover_code.append(f"# 创建{cam.name} 相机\n")
        recover_code.append(f"cam_data_{cam.name} = bpy.data.cameras.new(name='{cam.name}')\n")
        recover_code.append(f"cam_obj_{cam.name} = bpy.data.objects.new('{cam.name}', cam_data_{cam.name})\n")
        recover_code.append(f"bpy.context.collection.objects.link(cam_obj_{cam.name})\n")
        recover_code.append(f"cam_obj_{cam.name}.location = {tuple(cam.location)}\n")
        recover_code.append(f"cam_obj_{cam.name}.rotation_euler = {tuple(cam.rotation_euler)}\n")
        recover_code.append(f"cam_obj_{cam.name}.scale = {tuple(cam.scale)}\n")
        # 补充相机焦距参数
        recover_code.append(f"cam_data_{cam.name}.lens = {cam.data.lens}\n\n")

# 3. 遍历并生成Light
recover_code.append("===== 创建灯光 =====\n")
for light in bpy.data.objects:
    if light.type == 'LIGHT' and light.name not in exclude_objs:
        light_data = light.data
        recover_code.append(f"# 创建{light.name} 灯光\n")
        recover_code.append(f"light_data_{light.name} = bpy.data.lights.new(name='{light.name}', type='{light_data.type}')\n")
        recover_code.append(f"light_obj_{light.name} = bpy.data.objects.new('{light.name}', light_data_{light.name})\n")
        recover_code.append(f"bpy.context.collection.objects.link(light_obj_{light.name})\n")
        recover_code.append(f"light_obj_{light.name}.location = {tuple(light.location)}\n")
        recover_code.append(f"light_obj_{light.name}.rotation_euler = {tuple(light.rotation_euler)}\n")
        recover_code.append(f"light_obj_{light.name}.scale = {tuple(light.scale)}\n")
        # 灯光亮度/颜色
        recover_code.append(f"light_data_{light.name}.energy = {light_data.energy}\n")
        recover_code.append(f"light_data_{light.name}.color = {tuple(light_data.color)}\n\n")

# 4. 遍历并生成Material(绑定到对应Mesh)
recover_code.append("===== 创建材质 =====\n")
for mat in bpy.data.materials:
    if mat.name not in exclude_objs and not mat.is_grease_pencil:
        recover_code.append(f"# 创建材质{mat.name}\n")
        recover_code.append(f"mat_{mat.name} = bpy.data.materials.new(name='{mat.name}')\n")
        recover_code.append(f"mat_{mat.name}.use_nodes = True\n")
        # 简化材质(保留基础色/金属度/粗糙度)
        mat.use_nodes = True
        bsdf = mat.node_tree.nodes.get("Principled BSDF")
        if bsdf:
            base_color = tuple(bsdf.inputs['Base Color'].default_value)
            metallic = bsdf.inputs['Metallic'].default_value
            roughness = bsdf.inputs['Roughness'].default_value
            recover_code.append(f"bsdf = mat_{mat.name}.node_tree.nodes['Principled BSDF']\n")
            recover_code.append(f"bsdf.inputs['Base Color'].default_value = {base_color}\n")
            recover_code.append(f"bsdf.inputs['Metallic'].default_value = {metallic}\n")
            recover_code.append(f"bsdf.inputs['Roughness'].default_value = {roughness}\n")
        # 修复核心:用材质名称判断是否绑定到对象
        for obj in bpy.data.objects:
            if obj.type == 'MESH' and obj.name not in exclude_objs:
                # 遍历对象的材质名称,匹配当前材质
                obj_mat_names = [m.name for m in obj.data.materials if m]
                if mat.name in obj_mat_names:
                    recover_code.append(f"# 材质绑定到{obj.name}\n")
                    recover_code.append(f"if obj_{obj.name}.data.materials: obj_{obj.name}.data.materials[0] = mat_{mat.name}\n")
                    recover_code.append(f"else: obj_{obj.name}.data.materials.append(mat_{mat.name})\n")
        recover_code.append("\n")

# 写入文件
with open(save_path, 'w', encoding='utf-8') as f:
    f.write(''.join(recover_code))

print(f"✅复原脚本已生成:{save_path}")
print("⚠️直接运行该脚本即可复原当前场景")

  • 本文来自 oeasy Python 系统教程。
  • 想完整、扎实学 Python,
  • 搜索 oeasy 即可。