import bpy, math, random
from mathutils import Vector
random.seed(27)
s=bpy.data.scenes.new('CLAWD | CYPHERPUNK SOLANA')
bpy.context.window.scene=s
s.render.engine='CYCLES'
s.cycles.samples=64
s.cycles.use_denoising=True
s.render.resolution_x=1600
s.render.resolution_y=1000
s.render.resolution_percentage=100
s.render.fps=24
s.frame_start=1
s.frame_end=144
s.world=bpy.data.worlds.new('Midnight atmosphere')
s.world.use_nodes=True
s.world.node_tree.nodes['Background'].inputs[0].default_value=(.003,.006,.012,1)
s.world.node_tree.nodes['Background'].inputs[1].default_value=.25
s.view_settings.view_transform='AgX'
def mat(name,color,metal=0,rough=.4,emit=0):
 m=bpy.data.materials.new(name);m.diffuse_color=(*color,1);m.use_nodes=True
 p=m.node_tree.nodes.get('Principled BSDF');p.inputs['Base Color'].default_value=(*color,1);p.inputs['Metallic'].default_value=metal;p.inputs['Roughness'].default_value=rough
 p.inputs['Emission Color'].default_value=(*color,1);p.inputs['Emission Strength'].default_value=emit
 return m
black=mat('Obsidian brushed alloy',(.015,.024,.036),.82,.26)
wall=mat('Graphite architecture',(.013,.018,.026),.55,.45)
green=mat('Solana mint light',(.02,1,.48),.3,.25,4)
purple=mat('Solana violet light',(.40,.035,1),.3,.25,4)
white=mat('Ice typography',(.48,.8,.9),.2,.3,1.8)
dim=mat('Low intensity circuitry',(.012,.15,.16),.5,.35,.6)
def cube(name,loc,scale,material,bev=0):
 bpy.ops.mesh.primitive_cube_add(size=1,location=loc);o=bpy.context.object;o.name=name;o.dimensions=scale;bpy.ops.object.transform_apply(location=False,rotation=False,scale=True);o.data.materials.append(material)
 if bev:m=o.modifiers.new('Machined edges','BEVEL');m.width=bev;m.segments=3;o.modifiers.new('Weighted normals','WEIGHTED_NORMAL')
 return o
def line(name,pts,material,r=.016):
 c=bpy.data.curves.new(name,'CURVE');c.dimensions='3D';c.bevel_depth=r;c.bevel_resolution=3;p=c.splines.new('POLY');p.points.add(len(pts)-1)
 for v,co in zip(p.points,pts):v.co=(*co,1)
 o=bpy.data.objects.new(name,c);s.collection.objects.link(o);o.data.materials.append(material);return o
def ring(name,loc,radius,material):
 bpy.ops.mesh.primitive_torus_add(major_radius=radius,minor_radius=.026,major_segments=96,minor_segments=8,location=loc);o=bpy.context.object;o.name=name;o.data.materials.append(material);return o
def text(name,body,loc,size,material):
 c=bpy.data.curves.new(name,'FONT');c.body=body;c.size=size;c.extrude=.001;c.space_character=1.18
 o=bpy.data.objects.new(name,c);s.collection.objects.link(o);o.location=loc;o.rotation_euler=(math.pi/2,0,0);o.data.materials.append(material);return o
cube('Endless dark reflective floor',(0,2,-.12),(40,35,.2),black,.05)
cube('Rear vault wall',(0,6,4),(24,.3,10),wall,.1)
for x in range(-12,13,2):line('Floor circuit',[(x,-10,.005),(x,6,.005)],dim,.009)
for y in range(-8,7,2):line('Floor circuit',[(-14,y,.006),(14,y,.006)],dim,.009)
for x in [-9,-7,-5,5,7,9]:
 cube('Server monolith',(x,4.8,2.7),(1.15,1.3,5.4),black,.07)
 for z in range(12):
  cube('Server ventilation',(x,4.12,.3+z*.4),(.87,.025,.035),dim)
  cube('Validator status',(x-.37,4.08,.3+z*.4),(.055,.02,.055),green if z%3 else purple)
 line('Architectural light',[(x+.55,4.05,.2),(x+.55,4.05,5.3)],purple if x<0 else green,.019)
# Raised dais anchors the original cropped portrait.
bpy.ops.mesh.primitive_cylinder_add(vertices=128,radius=2,depth=.32,location=(0,0,.18));bpy.context.object.name='Character plinth';bpy.context.object.data.materials.append(black)
ring('Mint pedestal rim',(0,0,.36),1.94,green)
ring('Violet outer circuit',(0,0,.035),2.22,purple)
ring('Mint outer circuit',(0,0,.035),2.38,dim)
# The supplied image is preserved and keyed in the material, without modifying it.
img=bpy.data.images.load('/Users/8bit/Downloads/IMG_3894.JPG',check_existing=True);img.pack()
m=bpy.data.materials.new('Original character | white-background key');m.use_nodes=True;n=m.node_tree.nodes;n.clear();l=m.node_tree.links
out=n.new('ShaderNodeOutputMaterial');mix=n.new('ShaderNodeMixShader');tr=n.new('ShaderNodeBsdfTransparent');em=n.new('ShaderNodeEmission');tex=n.new('ShaderNodeTexImage');tex.image=img;em.inputs['Strength'].default_value=.85
sep=n.new('ShaderNodeSeparateColor');l.new(tex.outputs['Color'],sep.inputs[0]);a=n.new('ShaderNodeMath');a.operation='MINIMUM';b=n.new('ShaderNodeMath');b.operation='MINIMUM';l.new(sep.outputs[0],a.inputs[0]);l.new(sep.outputs[1],a.inputs[1]);l.new(a.outputs[0],b.inputs[0]);l.new(sep.outputs[2],b.inputs[1]);r=n.new('ShaderNodeMapRange');r.inputs['From Min'].default_value=.5;r.inputs['From Max'].default_value=.78;r.inputs['To Min'].default_value=1;r.inputs['To Max'].default_value=0;l.new(b.outputs[0],r.inputs['Value']);l.new(r.outputs[0],mix.inputs[0]);l.new(tr.outputs[0],mix.inputs[1]);l.new(tex.outputs['Color'],em.inputs[0]);l.new(em.outputs[0],mix.inputs[2]);l.new(mix.outputs[0],out.inputs[0])
bpy.ops.mesh.primitive_plane_add(size=2,location=(0,-.12,2.5),rotation=(math.pi/2,0,0));hero=bpy.context.object;hero.name='CLAWD | animated original portrait';hero.scale=(3.82,2.15,1);hero.data.materials.append(m)
for f,dz,tilt in [(1,0,0),(37,.06,-.012),(73,0,0),(109,.045,.012),(144,0,0)]:
 hero.location.z=2.5+dz;hero.rotation_euler.y=tilt;hero.keyframe_insert(data_path='location',frame=f);hero.keyframe_insert(data_path='rotation_euler',frame=f)
# Actual supplied Solana gradient drives the holographic logo and panels.
grad=bpy.data.images.load('/Users/8bit/Downloads/Gradient/solanaGradient.png',check_existing=True);grad.pack()
gm=bpy.data.materials.new('Supplied Solana gradient hologram');gm.use_nodes=True;nn=gm.node_tree.nodes;pp=nn.get('Principled BSDF');tt=nn.new('ShaderNodeTexImage');tt.image=grad;gm.node_tree.links.new(tt.outputs['Color'],pp.inputs['Base Color']);gm.node_tree.links.new(tt.outputs['Color'],pp.inputs['Emission Color']);pp.inputs['Emission Strength'].default_value=2.2
for j in range(3):
 z=5.0-j*.30;shift=.15 if j!=1 else -.15
 verts=[(-.70+shift,5.72,z),(.52+shift,5.72,z),(.72+shift,5.72,z+.17),(-.50+shift,5.72,z+.17)]
 mesh=bpy.data.meshes.new('Solana slash');mesh.from_pydata(verts,[],[(0,1,2,3)]);mesh.uv_layers.new()
 for k,uv in enumerate([(0,0),(1,0),(1,1),(0,1)]):mesh.uv_layers[0].data[k].uv=uv
 o=bpy.data.objects.new('Solana hologram',mesh);s.collection.objects.link(o);o.data.materials.append(gm)
text('Solana wordmark','S O L A N A',(-1.28,5.68,4.18),.31,white)
text('Header','P E R M I S S I O N L E S S   /   A F T E R   D A R K',(-3.32,5.7,6.05),.16,white)
# Linked, rotating wireframe blocks behind the hero.
centers=[(-5.5,3.5,3),(-3.7,3.9,3.7),(-1.95,4.35,3.35),(1.95,4.35,3.35),(3.7,3.9,3.7),(5.5,3.5,3)]
for i,pos in enumerate(centers):
 o=cube('Blockchain block %02d'%i,pos,(.9,.9,.9),green if i%2 else purple)
 mod=o.modifiers.new('Holographic block edges','WIREFRAME');mod.thickness=.018
 o.rotation_euler=(.15,.2,.2)
 for f,ang in [(1,.2),(144,.2+math.tau)]:o.rotation_euler.z=ang;o.keyframe_insert(data_path='rotation_euler',frame=f)
 text('Block identifier','BLOCK / %04d'%(8401+i),(pos[0]-.48,pos[1]-.6,pos[2]-.88),.11,white)
 if i and i!=3:line('Encrypted link',[centers[i-1],pos],green,.02)
line('Chain passing behind portrait',[centers[2],(-.9,4.5,2.9),(.9,4.5,2.9),centers[3]],purple,.022)
for side in [-1,1]:
 x=side*4.1
 cube('Hologram terminal',(x,1.4,1.15),(2,.16,1.3),black,.04)
 line('Terminal accent',[(x-.95,1.3,1.8),(x+.95,1.3,1.8)],green if side>0 else purple)
 text('Terminal title','VALIDATOR // 01' if side<0 else 'ENCRYPTED // P2P',(x-.85,1.29,1.5),.15,white)
 for j,body in enumerate(['SIGNATURE  :: VERIFIED','CONSENSUS  :: ACTIVE','01  10  11  00  10  01']):text('Terminal data',body,(x-.85,1.29,1.23-j*.18),.095,green if side>0 else purple)
for i in range(90):
 pos=(random.uniform(-7,7),random.uniform(1.8,5),random.uniform(.5,6))
 bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=1,radius=random.uniform(.009,.028),location=pos);o=bpy.context.object;o.name='Drifting encrypted packet';o.data.materials.append(green if i%2 else purple)
 o.keyframe_insert(data_path='location',frame=1);o.location.z+=random.uniform(.15,.7);o.keyframe_insert(data_path='location',frame=144)
def area(name,loc,color,power,size,target):
 d=bpy.data.lights.new(name,'AREA');d.energy=power;d.color=color;d.shape='DISK';d.size=size;o=bpy.data.objects.new(name,d);s.collection.objects.link(o);o.location=loc;o.rotation_euler=(Vector(target)-o.location).to_track_quat('-Z','Y').to_euler()
area('Violet wash',(-5,-1,5),(.34,.035,1),1300,5,(0,1,1))
area('Mint wash',(5,0,5),(.02,1,.46),1500,5,(0,1,1))
area('Overhead softbox',(0,-1,7),(.35,.5,1),800,4,(0,0,0))
d=bpy.data.cameras.new('Portrait cinema camera');cam=bpy.data.objects.new('Portrait cinema camera',d);s.collection.objects.link(cam);s.camera=cam;cam.location=(0,-16.8,6.5);target=Vector((0,1.1,2.65));cam.rotation_euler=(target-cam.location).to_track_quat('-Z','Y').to_euler();d.type='PERSP';d.lens=43
for f,x in [(1,0),(73,.26),(144,0)]:cam.location.x=x;cam.rotation_euler=(target-cam.location).to_track_quat('-Z','Y').to_euler();cam.keyframe_insert(data_path='location',frame=f);cam.keyframe_insert(data_path='rotation_euler',frame=f)
# Bloom compositor.
s.use_nodes=True
try:
 tree=s.node_tree
except AttributeError:
 tree=bpy.data.node_groups.new('Cinematic bloom','CompositorNodeTree');s.compositing_node_group=tree
 tree.interface.new_socket(name='Image',in_out='OUTPUT',socket_type='NodeSocketColor')
n=tree.nodes;n.clear();rl=n.new('CompositorNodeRLayers');rl.scene=s;gl=n.new('CompositorNodeGlare');gl.inputs['Type'].default_value='Fog Glow';gl.inputs['Strength'].default_value=.35
try:out=n.new('CompositorNodeComposite')
except:out=n.new('NodeGroupOutput')
tree.links.new(rl.outputs['Image'],gl.inputs['Image']);tree.links.new(gl.outputs['Image'],out.inputs['Image'])
s.frame_set(1)
for screen in bpy.data.screens:
 for a in screen.areas:
  if a.type=='VIEW_3D':a.spaces.active.region_3d.view_perspective='CAMERA'
s.render.image_settings.file_format='PNG';s.render.filepath='/Users/8bit/Downloads/Cypherpunk-Solana/Cypherpunk-Solana.png'
bpy.ops.wm.save_as_mainfile(filepath='/Users/8bit/Downloads/Cypherpunk-Solana/Cypherpunk-Solana.blend')
print('Built scene:',len(s.objects),'objects. Saved Blender file.')
