import bpy
import math
from mathutils import Vector
# ---------------------------
# Utility: Create/Reuse Material
# ---------------------------
def ensure_material(name, setup_fn):
mat = [Link](name)
if mat is None:
mat = [Link](name)
mat.use_nodes = True
nt = mat.node_tree
nodes = [Link]
links = [Link]
for n in nodes:
[Link](n)
output = [Link]("ShaderNodeOutputMaterial")
bsdf = [Link]("ShaderNodeBsdfPrincipled")
[Link] = (-200, 0)
[Link]([Link]["BSDF"], [Link]["Surface"])
setup_fn(nt, bsdf, output)
return mat
# ---------------------------
# Materials
# ---------------------------
def mat_wall():
def setup(nt, bsdf, output):
[Link]["Base Color"].default_value = (0.8, 0.75, 0.7, 1.0)
[Link]["Roughness"].default_value = 0.8
return ensure_material("MAT_Wall", setup)
def mat_roof():
def setup(nt, bsdf, output):
[Link]["Base Color"].default_value = (0.2, 0.05, 0.05, 1.0)
[Link]["Roughness"].default_value = 0.6
return ensure_material("MAT_Roof", setup)
def mat_wood():
def setup(nt, bsdf, output):
tex = [Link]("ShaderNodeTexNoise")
[Link] = (-400, 0)
[Link]["Scale"].default_value = 10
[Link]([Link]["Color"], [Link]["Base Color"])
[Link]["Roughness"].default_value = 0.5
return ensure_material("MAT_Wood", setup)
def mat_metal_dark():
def setup(nt, bsdf, output):
[Link]["Base Color"].default_value = (0.08, 0.08, 0.08, 1.0)
[Link]["Metallic"].default_value = 0.7
[Link]["Roughness"].default_value = 0.35
return ensure_material("MAT_MetalDark", setup)
def mat_target_paint():
def setup(nt, bsdf, output):
wave = [Link]("ShaderNodeTexWave")
[Link] = (-500, 0)
wave.wave_type = "RINGS"
wave.rings_direction = "SPHERICAL" # ✅ Blender 4.5-safe
[Link]["Scale"].default_value = 3.5
ramp = [Link]("ShaderNodeValToRGB")
[Link] = (-250, 0)
ramp.color_ramp.elements[0].color = (0.05, 0.85, 0.05, 1)
ramp.color_ramp.elements[1].color = (0.25, 0.25, 0.25, 1)
ramp.color_ramp.elements[1].position = 0.55
[Link]([Link]["Color"], [Link]["Fac"])
[Link]([Link]["Color"], [Link]["Base Color"])
[Link]["Roughness"].default_value = 0.6
return ensure_material("MAT_TargetPaint", setup)
# ---------------------------
# Geometry Builders
# ---------------------------
def create_building():
[Link].primitive_cube_add(size=2, location=(0, 1, 1))
b = [Link].active_object
[Link] = (6, 6, 3)
[Link](mat_wall())
# Roof
[Link].primitive_cone_add(vertices=4, radius1=8, depth=2, location=(0, 1,
4.5))
r = [Link].active_object
r.rotation_euler = (0, 0, [Link](45))
[Link](mat_roof())
def create_tower(x, y):
[Link].primitive_cylinder_add(vertices=16, radius=1.2, depth=8,
location=(x, y, 4))
t = [Link].active_object
[Link](mat_wall())
# Roof
[Link].primitive_cone_add(vertices=16, radius1=1.5, depth=2, location=(x,
y, 8))
roof = [Link].active_object
[Link](mat_roof())
def create_gate():
[Link].primitive_cube_add(size=2, location=(0, -6, 2))
g = [Link].active_object
[Link] = (4, 1, 3)
[Link](mat_wood())
def create_target(x, y):
[Link].primitive_cylinder_add(vertices=32, radius=0.7, depth=0.2,
location=(x, y, 1))
tgt = [Link].active_object
[Link](mat_target_paint())
# ---------------------------
# Scene Setup
# ---------------------------
def clear_scene():
[Link].select_all(action='SELECT')
[Link](use_global=False)
def build_academy():
clear_scene()
create_building()
create_tower(8, 8)
create_tower(-8, 8)
create_tower(8, -6)
create_tower(-8, -6)
create_gate()
create_target(3, -10)
create_target(-3, -10)
# Lights
[Link].light_add(type="SUN", radius=1, location=(10, -10, 15))
sun = [Link].active_object
[Link] = 5
# Camera
[Link].camera_add(location=(20, -20, 12), rotation=([Link](60),
0, [Link](45)))
cam = [Link].active_object
[Link] = cam
# Render engine
[Link] = "BLENDER_EEVEE_NEXT" # ✅ Blender 4.5 safe
# ---------------------------
# Run
# ---------------------------
build_academy()
import bpy
import math
# =========================
# MATERIALS
# =========================
def create_material(name, base_color, metallic=0.0, roughness=0.5):
mat = [Link](name)
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
[Link]["Base Color"].default_value = (*base_color, 1)
[Link]["Metallic"].default_value = metallic
[Link]["Roughness"].default_value = roughness
return mat
# Define materials
wall_mat = create_material("Wall_Mat", (0.95, 0.75, 0.55), 0.0, 0.7) # Sandy
walls
roof_mat = create_material("Roof_Mat", (0.8, 0.1, 0.1), 0.1, 0.4) # Red
roof
stone_mat = create_material("Stone_Mat", (0.4, 0.4, 0.45), 0.0, 0.6) # Grey
stone
flag_mat = create_material("Flag_Mat", (1.0, 0.1, 0.1), 0.0, 0.3) # Red
flags
# =========================
# FLAGS
# =========================
def add_flag(location, height=6):
# Flag pole
[Link].primitive_cylinder_add(radius=0.05, depth=height,
location=location)
pole = [Link].active_object
[Link](stone_mat)
# Flag (plane)
[Link].primitive_plane_add(size=2, location=(location[0]+1, location[1],
location[2]+height/2))
flag = [Link].active_object
[Link](flag_mat)
[Link][1] = 0.3 # make it rectangular
# Add wave modifier (cloth effect look)
[Link](name="Wave", type="WAVE")
# =========================
# WINDOWS
# =========================
def add_window(location, size=(1, 0.1, 1.5)):
[Link].primitive_cube_add(location=location)
window = [Link].active_object
[Link] = size
[Link](stone_mat)
# =========================
# APPLY MATERIALS TO OBJECTS
# =========================
def apply_materials():
for obj in [Link]:
if "Cube" in [Link]: # Main building
[Link](wall_mat)
elif "Cone" in [Link]: # Roofs
[Link](roof_mat)
elif "Cylinder" in [Link]: # Towers
[Link](stone_mat)
# =========================
# BUILD DETAILS
# =========================
def add_details():
# Apply materials
apply_materials()
# Add flags on two towers
add_flag(location=(6, 6, 12))
add_flag(location=(-6, 6, 12))
# Add windows
add_window(location=(0, 2.6, 3))
add_window(location=(0, -2.6, 3))
# Add ground plane
[Link].primitive_plane_add(size=60, location=(0,0,0))
ground = [Link].active_object
[Link](create_material("Ground_Mat", (0.2, 0.6, 0.2),
0.0, 0.8)) # Green grass
# =========================
# RUN
# =========================
add_details()
import bpy
# =========================
# ENTRANCE CUT (BOOLEAN)
# =========================
def add_entrance(building_name="Cube"):
# Create entrance shape (cube)
[Link].primitive_cube_add(size=2, location=(0, 2.6, 1.5))
entrance = [Link].active_object
[Link][0] = 1.5 # width
[Link][1] = 0.2 # depth
[Link][2] = 2.0 # height
[Link] = "Entrance_Cutter"
# Select building
building = [Link](building_name)
if building:
mod_bool = [Link](name="Entrance_Hole", type="BOOLEAN")
mod_bool.operation = 'DIFFERENCE'
mod_bool.object = entrance
[Link].view_layer.[Link] = building
[Link].modifier_apply(modifier=mod_bool.name)
# Delete cutter cube
[Link](entrance, do_unlink=True)
# =========================
# FLAGS
# =========================
def add_flag(location, height=6):
# Flag pole
[Link].primitive_cylinder_add(radius=0.05, depth=height,
location=location)
pole = [Link].active_object
[Link] = "FlagPole"
# Flag banner
[Link].primitive_plane_add(size=2, location=(location[0]+1, location[1],
location[2]+height/2))
flag = [Link].active_object
[Link] = "Flag"
[Link][1] = 0.3
# Add waving effect
[Link](name="Wave", type="WAVE")
# =========================
# RUN SCRIPT
# =========================
# Cut entrance in the front cube (main building usually named "Cube")
add_entrance("Cube")
# Add two flags on the towers
add_flag(location=(6, 6, 12))
add_flag(location=(-6, 6, 12))
import bpy
# =========================
# MATERIAL CREATOR
# =========================
def make_material(name, color):
mat = [Link](name=name)
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
[Link]["Base Color"].default_value = (*color, 1) # RGBA
[Link]["Roughness"].default_value = 0.6
return mat
# =========================
# CREATE MATERIALS
# =========================
mat_wall = make_material("Wall_Mat", (0.95, 0.85, 0.7)) # beige walls
mat_roof = make_material("Roof_Mat", (0.8, 0.2, 0.05)) # red roof
mat_wood = make_material("Wood_Mat", (0.3, 0.15, 0.05)) # dark brown
mat_flag = make_material("Flag_Mat", (0.8, 0.1, 0.1)) # bright red
mat_ground = make_material("Ground_Mat", (0.4, 0.6, 0.3)) # green grass
# =========================
# ASSIGN MATERIALS
# =========================
def assign_material(obj_name, mat):
obj = [Link](obj_name)
if obj:
if [Link]:
[Link][0] = mat
else:
[Link](mat)
# Assign to main building
assign_material("Cube", mat_wall)
# Assign to towers
for obj_name in ["Cylinder", "Cylinder.001", "Cylinder.002", "Cylinder.003"]:
if [Link](obj_name):
assign_material(obj_name, mat_wall)
# Assign to roofs (cones)
for obj_name in ["Cone", "Cone.001", "Cone.002", "Cone.003"]:
if [Link](obj_name):
assign_material(obj_name, mat_roof)
# Assign entrance frame (optional if exists)
assign_material("Entrance_Frame", mat_wood)
# Assign flags
for obj_name in ["Flag", "Flag.001"]:
if [Link](obj_name):
assign_material(obj_name, mat_flag)
# Assign ground
assign_material("Plane", mat_ground)
assign_material("Plane.002", mat_ground)
import bpy
# =========================
# MATERIAL CREATOR
# =========================
def make_material(name, color):
if name in [Link]:
return [Link][name]
mat = [Link](name=name)
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
[Link]["Base Color"].default_value = (*color, 1) # RGBA
[Link]["Roughness"].default_value = 0.6
return mat
# =========================
# CREATE MATERIALS
# =========================
mat_wall = make_material("Wall_Mat", (0.95, 0.85, 0.7)) # beige walls
mat_roof = make_material("Roof_Mat", (0.8, 0.2, 0.05)) # red roof
mat_wood = make_material("Wood_Mat", (0.3, 0.15, 0.05)) # dark brown
mat_flag = make_material("Flag_Mat", (0.8, 0.1, 0.1)) # bright red
mat_ground = make_material("Ground_Mat", (0.4, 0.6, 0.3)) # green grass
# =========================
# AUTO ASSIGN MATERIALS
# =========================
for obj in [Link]:
if [Link] == 'MESH':
name = [Link]()
if "cone" in name: # roofs
[Link]()
[Link](mat_roof)
elif "cylinder" in name: # towers
[Link]()
[Link](mat_wall)
elif "cube" in name: # main building blocks
[Link]()
[Link](mat_wall)
elif "plane" in name: # ground
[Link]()
[Link](mat_ground)
elif "flag" in name: # flags
[Link]()
[Link](mat_flag)
# =========================
# SWITCH TO MATERIAL PREVIEW MODE
# =========================
for area in [Link]:
if [Link] == 'VIEW_3D':
for space in [Link]:
if [Link] == 'VIEW_3D':
[Link] = 'MATERIAL' # switch viewport shading
import bpy
# Delete old objects
[Link].select_all(action='SELECT')
[Link](use_global=False)
# Ground plane
[Link].primitive_plane_add(size=40, location=(0,0,0))
ground = [Link].active_object
mat_ground = [Link]("Ground")
mat_ground.diffuse_color = (0.1, 0.5, 0.1, 1) # green grass
[Link](mat_ground)
# Tower base + tiers
heights = [6, 5, 4, 3] # heights of each tier
radii = [6, 5, 4, 3] # radius of each tier
z = 0
for i, (h, r) in enumerate(zip(heights, radii)):
[Link].primitive_cylinder_add(vertices=32, radius=r, depth=h,
location=(0,0,z+h/2))
cyl = [Link].active_object
mat = [Link](f"Tier{i}")
mat.diffuse_color = (0.9, 0.9, 0.9, 1) # off-white
[Link](mat)
# Roof
[Link].primitive_cone_add(vertices=32, radius1=r*1.2, depth=1.5,
location=(0,0,z+h+0.75))
roof = [Link].active_object
mat_roof = [Link](f"Roof{i}")
mat_roof.diffuse_color = (0.8, 0.2, 0.1, 1) # red-orange
[Link](mat_roof)
z += h
import bpy
import math
# Cleanup old academy objects if re-run
for obj in [Link]:
if [Link]("Academy") or [Link]("Entrance") or
[Link]("Window") or [Link]("Banner"):
[Link](obj, do_unlink=True)
# --- Materials ---
def get_material(name, color):
if name not in [Link]:
mat = [Link](name)
mat.use_nodes = True
bsdf = mat.node_tree.[Link]("Principled BSDF")
[Link]["Base Color"].default_value = (*color, 1)
return mat
return [Link][name]
mat_wall = get_material("MAT_Wall", (0.95, 0.8, 0.6)) # light beige
mat_roof = get_material("MAT_Roof", (0.8, 0.1, 0.1)) # red roof
mat_trim = get_material("MAT_Trim", (0.7, 0.3, 0.1)) # wooden trim
mat_glass = get_material("MAT_Glass", (0.4, 0.6, 0.9)) # window
mat_grass = get_material("MAT_Grass", (0.1, 0.5, 0.1)) # ground
# --- Main Base Building ---
[Link].primitive_cylinder_add(radius=6, depth=8, location=(0,0,4))
main = [Link].active_object
[Link] = "Academy_Main"
[Link](mat_wall)
# --- Roof on top ---
[Link].primitive_cone_add(radius1=7, depth=2, location=(0,0,9))
roof = [Link].active_object
[Link] = "Academy_Roof"
[Link](mat_roof)
# --- Roof Overhang trim ---
[Link].primitive_torus_add(major_radius=6.8, minor_radius=0.2,
location=(0,0,8))
trim = [Link].active_object
[Link] = "Academy_RoofTrim"
[Link](mat_trim)
# --- Entrance arch ---
[Link].primitive_cube_add(size=2, location=(0, -6, 1.5))
door_cut = [Link].active_object
door_cut.name = "Entrance_Cutter"
mod = [Link]("DoorBoolean", 'BOOLEAN')
[Link] = 'DIFFERENCE'
[Link] = door_cut
[Link].view_layer.[Link] = main
[Link].modifier_apply(modifier=[Link])
[Link](door_cut, do_unlink=True)
# --- Entrance Banner ---
[Link].primitive_plane_add(size=3, location=(0,-6.1,4))
banner = [Link].active_object
[Link] = "Entrance_Banner"
[Link][1] = 0.5
[Link](mat_roof)
# --- Windows (around cylinder) ---
for i in range(0, 360, 45):
rad = [Link](i)
x = 5.5 * [Link](rad)
y = 5.5 * [Link](rad)
z = 4
[Link].primitive_plane_add(size=1, location=(x,y,z))
win = [Link].active_object
[Link] = f"Window_{i}"
win.rotation_euler[2] = rad
[Link](mat_glass)
# --- Ground plane with grass ---
[Link].primitive_plane_add(size=40, location=(0,0,0))
ground = [Link].active_object
[Link] = "Academy_Ground"
[Link](mat_grass)
# Add a little noise for grass variation
ground_mod = [Link]("Displace", 'DISPLACE')
tex = [Link]("GrassNoise", 'CLOUDS')
ground_mod.texture = tex
ground_mod.strength = 0.3
import bpy
import math
# --- Cleanup previous objects ---
for obj in [Link]:
if [Link](("Entrance", "BannerArch", "NarutoBanner")):
[Link](obj, do_unlink=True)
# Re-get main building reference
main = [Link]("Academy_Main")
# --- Materials ---
def get_material(name, color, texture=False):
if name not in [Link]:
mat = [Link](name)
mat.use_nodes = True
bsdf = mat.node_tree.[Link]("Principled BSDF")
[Link]["Base Color"].default_value = (*color, 1)
if texture:
tex_img = mat.node_tree.[Link]("ShaderNodeTexImage")
# placeholder image slot for Naruto logo
mat.node_tree.[Link](tex_img.outputs["Color"], [Link]["Base
Color"])
return mat
return [Link][name]
mat_banner = get_material("MAT_Banner", (0.8, 0.1, 0.1)) # red banner
# --- Arch Entrance (instead of cube) ---
[Link].primitive_cylinder_add(vertices=32, radius=1.2, depth=0.5,
location=(0,-6,1.2))
arch_cut = [Link].active_object
arch_cut.name = "Entrance_ArchCutter"
arch_cut.scale[2] = 1.8
# Boolean difference for arch hole
mod = [Link]("ArchBoolean", 'BOOLEAN')
[Link] = 'DIFFERENCE'
[Link] = arch_cut
[Link].view_layer.[Link] = main
[Link].modifier_apply(modifier=[Link])
[Link](arch_cut, do_unlink=True)
# --- Naruto Banner on Tower ---
[Link].primitive_plane_add(size=4, location=(0, -5.9, 6))
banner = [Link].active_object
[Link] = "NarutoBanner"
[Link][0] = 1.2 # wide
[Link][1] = 0.05 # thin depth
banner.rotation_euler[0] = [Link](90)
[Link](mat_banner)
# Optional: slight wave effect to look like cloth
mod = [Link]("Wave", "WAVE")
[Link] = 0.1
[Link] = 1.5
[Link] = 0.5
import bpy
# --- find the main building ---
main = [Link]("Academy_Main")
if not main:
raise RuntimeError("Academy_Main not found. Run your base building script
first.")
# delete old entrance cutter if exists
if "EntranceCutter" in [Link]:
[Link]([Link]["EntranceCutter"], do_unlink=True)
# dimensions
building_width = [Link].x
building_depth = [Link].y
building_height = [Link].z
# entrance proportions (adjustable)
door_width = building_width * 0.35 # 35% of width
door_height = building_height * 0.45 # 45% of height
door_depth = building_depth * 0.6 # cut deep enough
# add cube as cutter
[Link].primitive_cube_add(size=1, location=(0, building_depth/2 -
door_depth/2, door_height/2))
cutter = [Link].active_object
[Link] = "EntranceCutter"
[Link] = (door_width/2, door_depth/2, door_height/2)
# apply boolean modifier to main building
bool_mod = [Link](name="Entrance_Boolean", type='BOOLEAN')
bool_mod.operation = 'DIFFERENCE'
bool_mod.object = cutter
# apply modifier permanently
[Link].view_layer.[Link] = main
[Link].modifier_apply(modifier=bool_mod.name)
# delete cutter cube
[Link](cutter, do_unlink=True)
print("✅ Entrance hole added to the front of the building.")
import bpy
# --- find the main building ---
main = [Link]("Academy_Main")
if not main:
raise RuntimeError("Academy_Main not found. Run your base building script
first.")
# delete old entrance cutter if exists
if "EntranceCutter" in [Link]:
[Link]([Link]["EntranceCutter"], do_unlink=True)
if "EntranceFrame" in [Link]:
[Link]([Link]["EntranceFrame"], do_unlink=True)
# dimensions
building_width = [Link].x
building_depth = [Link].y
building_height = [Link].z
# entrance proportions (adjustable)
door_width = building_width * 0.35
door_height = building_height * 0.45
door_depth = building_depth * 0.6
# --- Cut entrance hole ---
[Link].primitive_cube_add(size=1, location=(0, building_depth/2 -
door_depth/2, door_height/2))
cutter = [Link].active_object
[Link] = "EntranceCutter"
[Link] = (door_width/2, door_depth/2, door_height/2)
# Boolean difference
bool_mod = [Link](name="Entrance_Boolean", type='BOOLEAN')
bool_mod.operation = 'DIFFERENCE'
bool_mod.object = cutter
[Link].view_layer.[Link] = main
[Link].modifier_apply(modifier=bool_mod.name)
# remove cutter
[Link](cutter, do_unlink=True)
# --- Add Entrance Frame ---
frame_thickness = 0.15 # adjust thickness
[Link].primitive_cube_add(size=1, location=(0, building_depth/2 + 0.01,
door_height/2))
frame = [Link].active_object
[Link] = "EntranceFrame"
[Link] = (door_width/2 + frame_thickness, 0.1, door_height/2 +
frame_thickness)
# make frame hollow (boolean again)
[Link].primitive_cube_add(size=1, location=(0, building_depth/2 + 0.02,
door_height/2))
inner = [Link].active_object
[Link] = "FrameInner"
[Link] = (door_width/2, 0.15, door_height/2)
bool_mod2 = [Link](name="Frame_Hollow", type='BOOLEAN')
bool_mod2.operation = 'DIFFERENCE'
bool_mod2.object = inner
[Link].view_layer.[Link] = frame
[Link].modifier_apply(modifier=bool_mod2.name)
[Link](inner, do_unlink=True)
# --- Material for frame ---
mat_frame = [Link](name="FrameMaterial")
mat_frame.diffuse_color = (0.1, 0.05, 0.02, 1.0) # dark brown/black wood
[Link](mat_frame)
print("✅ Entrance hole with visible frame added.")
import bpy
# --- Parameters for steps ---
step_count = 4 # number of steps
step_depth = 0.4 # how far each step extends
step_height = 0.15 # height of each step
step_width_factor = 1.2 # how much wider than the entrance
# find building & entrance frame
main = [Link]("Academy_Main")
frame = [Link]("EntranceFrame")
if not main or not frame:
raise RuntimeError("Academy_Main or EntranceFrame not found. Run previous
scripts first.")
# get entrance dimensions from frame
door_width = [Link].x
door_bottom = [Link].z - [Link].z/2
# --- Create steps ---
for i in range(step_count):
[Link].primitive_cube_add(size=1,
location=(0, [Link].y/2 + (i+0.5)*step_depth,
door_bottom - (i+0.5)*step_height))
step = [Link].active_object
[Link] = f"DoorStep_{i+1}"
[Link] = (door_width/2 * step_width_factor, step_depth/2, step_height/2)
# assign stone material
if "StepMaterial" not in [Link]:
mat_step = [Link](name="StepMaterial")
mat_step.diffuse_color = (0.6, 0.6, 0.6, 1.0) # light stone gray
else:
mat_step = [Link]["StepMaterial"]
[Link](mat_step)
print("✅ Doorsteps added in front of entrance.")
import bpy
# Get or create a more realistic stone material
mat_name = "RealisticStone"
if mat_name not in [Link]:
mat = [Link](mat_name)
mat.use_nodes = True
# Clear default nodes
nodes = mat.node_tree.nodes
for node in nodes:
[Link](node)
# Create nodes
output = [Link](type="ShaderNodeOutputMaterial")
principled = [Link](type="ShaderNodeBsdfPrincipled")
noise = [Link](type="ShaderNodeTexNoise")
bump = [Link](type="ShaderNodeBump")
color_ramp = [Link](type="ShaderNodeValToRGB")
# Place nodes neatly
[Link] = (0, 0)
[Link] = (200, 0)
[Link] = (-600, 0)
color_ramp.location = (-400, 0)
[Link] = (-200, -200)
# Setup Noise Texture (rocky detail)
[Link]["Scale"].default_value = 20.0
[Link]["Detail"].default_value = 8.0
[Link]["Roughness"].default_value = 0.6
# Setup Color Ramp (gray variation)
color_ramp.color_ramp.elements[0].position = 0.3
color_ramp.color_ramp.elements[0].color = (0.5, 0.5, 0.5, 1) # dark gray
color_ramp.color_ramp.elements[1].position = 0.7
color_ramp.color_ramp.elements[1].color = (0.8, 0.8, 0.8, 1) # light gray
# Setup Principled BSDF
[Link]["Roughness"].default_value = 0.9
[Link]["Specular"].default_value = 0.2
# Link nodes
links = mat.node_tree.links
[Link]([Link]["Fac"], color_ramp.inputs["Fac"])
[Link](color_ramp.outputs["Color"], [Link]["Base Color"])
[Link]([Link]["Fac"], [Link]["Height"])
[Link]([Link]["Normal"], [Link]["Normal"])
[Link]([Link]["BSDF"], [Link]["Surface"])
else:
mat = [Link][mat_name]
# Apply to all steps
for obj in [Link]:
if [Link]("DoorStep_"):
if len([Link]) == 0:
[Link](mat)
else:
[Link][0] = mat
print("✅ Realistic stone material applied to steps.")
import bpy
# === Function to create a material ===
def create_material(name, setup_func):
if name not in [Link]:
mat = [Link](name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
for node in nodes:
[Link](node)
setup_func(mat)
return [Link][name]
# === Wall Material (Stucco/Plaster) ===
def setup_wall(mat):
nodes = mat.node_tree.nodes
links = mat.node_tree.links
output = [Link]("ShaderNodeOutputMaterial")
principled = [Link]("ShaderNodeBsdfPrincipled")
noise = [Link]("ShaderNodeTexNoise")
bump = [Link]("ShaderNodeBump")
colorramp = [Link]("ShaderNodeValToRGB")
[Link] = (0,0)
[Link] = (200,0)
[Link] = (-600,0)
[Link] = (-400,0)
[Link] = (-200,-200)
# Noise for plaster
[Link]["Scale"].default_value = 8.0
[Link]["Detail"].default_value = 5.0
# Stucco color
colorramp.color_ramp.elements[0].color = (0.9, 0.85, 0.75, 1) # light beige
colorramp.color_ramp.elements[1].color = (0.75, 0.7, 0.6, 1) # dirtier beige
[Link]["Roughness"].default_value = 0.8
[Link]["Specular"].default_value = 0.25
[Link]([Link]["Fac"], [Link]["Fac"])
[Link]([Link]["Color"], [Link]["Base Color"])
[Link]([Link]["Fac"], [Link]["Height"])
[Link]([Link]["Normal"], [Link]["Normal"])
[Link]([Link]["BSDF"], [Link]["Surface"])
# === Roof Material (Ceramic Tiles) ===
def setup_roof(mat):
nodes = mat.node_tree.nodes
links = mat.node_tree.links
output = [Link]("ShaderNodeOutputMaterial")
principled = [Link]("ShaderNodeBsdfPrincipled")
wave = [Link]("ShaderNodeTexWave")
bump = [Link]("ShaderNodeBump")
colorramp = [Link]("ShaderNodeValToRGB")
[Link] = (0,0)
[Link] = (200,0)
[Link] = (-600,0)
[Link] = (-400,0)
[Link] = (-200,-200)
# Wavy roof tiles
[Link]["Scale"].default_value = 3.0
[Link]["Distortion"].default_value = 0.2
# Tile colors
colorramp.color_ramp.elements[0].color = (0.6, 0.1, 0.05, 1) # dark red
colorramp.color_ramp.elements[1].color = (0.8, 0.2, 0.1, 1) # lighter red
[Link]["Roughness"].default_value = 0.5
[Link]["Specular"].default_value = 0.3
[Link]([Link]["Color"], [Link]["Fac"])
[Link]([Link]["Color"], [Link]["Base Color"])
[Link]([Link]["Fac"], [Link]["Height"])
[Link]([Link]["Normal"], [Link]["Normal"])
[Link]([Link]["BSDF"], [Link]["Surface"])
# === Wooden Entrance Material ===
def setup_wood(mat):
nodes = mat.node_tree.nodes
links = mat.node_tree.links
output = [Link]("ShaderNodeOutputMaterial")
principled = [Link]("ShaderNodeBsdfPrincipled")
wave = [Link]("ShaderNodeTexWave")
bump = [Link]("ShaderNodeBump")
colorramp = [Link]("ShaderNodeValToRGB")
[Link] = (0,0)
[Link] = (200,0)
[Link] = (-600,0)
[Link] = (-400,0)
[Link] = (-200,-200)
[Link]["Scale"].default_value = 20.0
[Link]["Distortion"].default_value = 1.5
colorramp.color_ramp.elements[0].color = (0.3, 0.15, 0.05, 1) # dark brown
colorramp.color_ramp.elements[1].color = (0.6, 0.3, 0.1, 1) # lighter wood
[Link]["Roughness"].default_value = 0.7
[Link]["Specular"].default_value = 0.2
[Link]([Link]["Fac"], [Link]["Fac"])
[Link]([Link]["Color"], [Link]["Base Color"])
[Link]([Link]["Fac"], [Link]["Height"])
[Link]([Link]["Normal"], [Link]["Normal"])
[Link]([Link]["BSDF"], [Link]["Surface"])
# === Create Materials ===
wall_mat = create_material("StuccoWall", setup_wall)
roof_mat = create_material("CeramicRoof", setup_roof)
wood_mat = create_material("WoodEntrance", setup_wood)
# === Apply to Objects ===
for obj in [Link]:
if [Link]("Building"):
[Link]()
[Link](wall_mat)
elif [Link]("Tower"):
[Link]()
[Link](wall_mat)
elif [Link]("Roof"):
[Link]()
[Link](roof_mat)
elif "Entrance" in [Link] or "Door" in [Link]:
[Link]()
[Link](wood_mat)
print("✅ Applied realistic materials to Academy (walls, roof, entrance).")
import bpy
# ----------------------------
# Helper for materials
# ----------------------------
def ensure_mat(name, rgba, rough=0.6, metallic=0.0):
m = [Link](name)
if not m:
m = [Link](name=name)
m.use_nodes = True
bsdf = m.node_tree.[Link]("Principled BSDF")
[Link]["Base Color"].default_value = (*rgba[:3], 1.0)
[Link]["Roughness"].default_value = rough
[Link]["Metallic"].default_value = metallic
return m
# ----------------------------
# Materials
# ----------------------------
mat_tower = ensure_mat("MAT_Tower", (0.75, 0.65, 0.5)) # stone / brown
mat_roof = ensure_mat("MAT_TowerRoof", (0.8, 0.1, 0.1)) # red cone top
# ----------------------------
# Main building (must exist already)
# ----------------------------
main = [Link]("Academy_Main")
if not main:
raise RuntimeError("Academy_Main not found. Run base building script first.")
# ----------------------------
# Tower dimensions
# ----------------------------
tower_radius = [Link].x * 0.22 # slightly slimmer
tower_height = [Link].z * 1.6 # taller than before
# Towers closer (reduce side offset)
side_offset = tower_radius * 0.8
# Z base
base_z = [Link].z - [Link].z * 0.5 + tower_height * 0.5
# ----------------------------
# Left Tower
# ----------------------------
tower_x_left = [Link].x - [Link].x * 0.5 - side_offset
tower_y = [Link].y
[Link].primitive_cylinder_add(radius=tower_radius, depth=tower_height,
location=(tower_x_left, tower_y, base_z))
tower_left = [Link].active_object
tower_left.name = "Academy_Tower_Left"
tower_left.[Link](mat_tower)
# Add cone roof to left tower
roof_height = tower_height * 0.4
[Link].primitive_cone_add(radius1=tower_radius * 1.1, depth=roof_height,
location=(tower_x_left, tower_y, base_z +
tower_height * 0.5 + roof_height * 0.5))
roof_left = [Link].active_object
roof_left.name = "Academy_TowerRoof_Left"
roof_left.[Link](mat_roof)
# ----------------------------
# Right Tower
# ----------------------------
tower_x_right = [Link].x + [Link].x * 0.5 + side_offset
[Link].primitive_cylinder_add(radius=tower_radius, depth=tower_height,
location=(tower_x_right, tower_y, base_z))
tower_right = [Link].active_object
tower_right.name = "Academy_Tower_Right"
tower_right.[Link](mat_tower)
# Add cone roof to right tower
[Link].primitive_cone_add(radius1=tower_radius * 1.1, depth=roof_height,
location=(tower_x_right, tower_y, base_z +
tower_height * 0.5 + roof_height * 0.5))
roof_right = [Link].active_object
roof_right.name = "Academy_TowerRoof_Right"
roof_right.[Link](mat_roof)
print("✅ Taller, closer towers with red cone rooftops created.")