Created
May 28, 2025 01:32
-
-
Save Cdaprod/0dcf30e1865b6c550c9ed9369d7e3559 to your computer and use it in GitHub Desktop.
Blender Shellfish iOS Terminal Drive BPY Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
import os | |
# 1. ——— CONFIGURE these paths & data ————————————— | |
FONT_PATH = "/path/to/JetBrainsMono Nerd Font.ttf" # ← point to your local Nerd Font | |
LINES = [ | |
"cd ~/Projects/Cdaprod", | |
"git status", | |
"exa -lh --color=always", | |
"ssh [email protected]", | |
# …add as many lines as you like… | |
] | |
CHAR_SPACING = 0.22 # horizontal spacing | |
LINE_SPACING = 0.30 # vertical spacing (if you want y-axis depth per line) | |
DEPTH_SPACING = 0.05 # z-axis offset per line (for the dive) | |
EXTRUDE_DEPTH = 0.02 # thickness of each character | |
BEVEL_DEPTH = 0.0005 # subtle bevel for nicer edges | |
# 2. ——— Load font ———————————————————————————— | |
if not os.path.isfile(FONT_PATH): | |
raise FileNotFoundError(f"Font not found at {FONT_PATH}") | |
font = bpy.data.fonts.load(FONT_PATH) | |
# 3. ——— Clear existing text objects —————————————————— | |
for obj in [o for o in bpy.data.objects if o.type == 'FONT']: | |
bpy.data.objects.remove(obj, do_unlink=True) | |
# 4. ——— Create text chars in 3D space ————————————— | |
for row, line in enumerate(LINES): | |
for col, ch in enumerate(line): | |
# new text curve | |
txt_curve = bpy.data.curves.new(f"char_{row}_{col}", 'FONT') | |
txt_curve.body = ch | |
txt_curve.font = font | |
txt_curve.extrude = EXTRUDE_DEPTH | |
txt_curve.bevel_depth = BEVEL_DEPTH | |
txt_obj = bpy.data.objects.new(f"char_{row}_{col}", txt_curve) | |
bpy.context.collection.objects.link(txt_obj) | |
# position: x = col*CHAR_SPACING, y=0, z = -row*DEPTH_SPACING | |
txt_obj.location = ( | |
col * CHAR_SPACING, | |
0, | |
-row * DEPTH_SPACING | |
) | |
# rotate so that +X is right, +Z is forward, camera looks down -Y | |
txt_obj.rotation_euler = (1.5708, 0, 0) | |
# 5. ——— Material: Emissive “Cdaprod Blue” text over dark bg ————— | |
mat = bpy.data.materials.new("CdaprodBlue_Text") | |
mat.use_nodes = True | |
tree = mat.node_tree | |
for n in tree.nodes: | |
tree.nodes.remove(n) | |
# nodes | |
nodes = tree.nodes | |
out = nodes.new("ShaderNodeOutputMaterial") | |
emit = nodes.new("ShaderNodeEmission") | |
emit.inputs['Color'].default_value = (0.231, 0.608, 0.953, 1) # #3B85F3 | |
emit.inputs['Strength'].default_value = 3.0 | |
tree.links.new(emit.outputs['Emission'], out.inputs['Surface']) | |
# assign to all char meshes | |
for obj in [o for o in bpy.data.objects if o.type == 'FONT']: | |
obj.data.materials.append(mat) | |
# 6. ——— Set world background to dark purple ————————— | |
world = bpy.data.worlds['World'] | |
world.use_nodes = True | |
nodes = world.node_tree.nodes | |
bg = nodes.get('Background') | |
if bg: | |
bg.inputs['Color'].default_value = (0.118, 0.0, 0.169, 1) # dark purple #1E002B | |
bg.inputs['Strength'].default_value = 0.2 | |
# 7. ——— Camera setup & animation ———————————————————— | |
cam = bpy.data.objects.get('Camera') | |
if cam is None: | |
cam_data = bpy.data.cameras.new("TerminalCam") | |
cam = bpy.data.objects.new("TerminalCam", cam_data) | |
bpy.context.collection.objects.link(cam) | |
bpy.context.scene.camera = cam | |
# initial cam position (above the first row, a bit back on Y) | |
cam.location = (len(LINES[0]) * CHAR_SPACING / 2, 1.5, 0) | |
cam.rotation_euler = (1.0472, 0, 1.5708) # tilt down 60°, face negative Z | |
cam.data.lens = 35 | |
cam.data.dof.use_dof = True | |
cam.data.dof.focus_distance = 1.5 | |
cam.data.dof.aperture_fstop = 1.8 | |
# keyframe start | |
cam.keyframe_insert(data_path="location", frame=1) | |
# end position: dive past last row | |
end_z = - (len(LINES) - 1) * DEPTH_SPACING | |
cam.location = (len(LINES[0]) * CHAR_SPACING / 2, 0.1, end_z) | |
cam.keyframe_insert(data_path="location", frame=250) | |
# 8. ——— Render settings —————————————————————— | |
scene = bpy.context.scene | |
scene.render.engine = 'CYCLES' | |
scene.cycles.samples = 128 | |
scene.render.film_transparent = True | |
scene.render.resolution_x = 1920 | |
scene.render.resolution_y = 1080 | |
scene.frame_start = 1 | |
scene.frame_end = 250 | |
print("Setup complete! Press F12 to render animation.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment