# サイコロ：角を丸めた立方体から、球で目をくり抜く（ブーリアン）
# 向かい合う面の和は7（1-6, 2-5, 3-4）。1の目だけ赤く大きく（日本式）
import bpy, sys, os
sys.path.append(os.path.dirname(__file__))
from common import reset, mat, stage, render

reset()
S = 1.0          # 辺の長さ
h = S / 2
bpy.ops.mesh.primitive_cube_add(size=S, location=(0, 0, h))
die = bpy.context.object; die.name = "Die"
bv = die.modifiers.new("bevel", "BEVEL"); bv.width = 0.09; bv.segments = 6

ivory = mat("ivory", (0.93, 0.91, 0.86), rough=0.25, sss=0.05)
black = mat("pip_black", (0.02, 0.02, 0.02), rough=0.3)
red = mat("pip_red", (0.7, 0.02, 0.02), rough=0.3)
die.data.materials.append(ivory)

o = 0.25  # 目の間隔
layouts = {1: [(0, 0)], 2: [(-o, -o), (o, o)], 3: [(-o, -o), (0, 0), (o, o)],
           4: [(-o, -o), (-o, o), (o, -o), (o, o)],
           5: [(-o, -o), (-o, o), (0, 0), (o, -o), (o, o)],
           6: [(-o, -o), (-o, 0), (-o, o), (o, -o), (o, 0), (o, o)]}
# 面の法線と面内の2軸
faces = {1: ((0, 0, 1), (1, 0, 0), (0, 1, 0)),    # 上
         6: ((0, 0, -1), (1, 0, 0), (0, 1, 0)),   # 下
         2: ((0, -1, 0), (1, 0, 0), (0, 0, 1)),   # 手前
         5: ((0, 1, 0), (1, 0, 0), (0, 0, 1)),    # 奥
         3: ((1, 0, 0), (0, 1, 0), (0, 0, 1)),    # 右
         4: ((-1, 0, 0), (0, 1, 0), (0, 0, 1))}   # 左

pips = []
for n, (nrm, u, v) in faces.items():
    r = 0.14 if n == 1 else 0.075
    for a, b in layouts[n]:
        p = [h * nrm[i] + a * u[i] + b * v[i] for i in range(3)]
        p[2] += h
        # 球の中心を面より少し外に置き、浅い皿状にくぼませる
        c = [p[i] + nrm[i] * r * 0.45 for i in range(3)]
        bpy.ops.mesh.primitive_uv_sphere_add(radius=r, location=c, segments=32, ring_count=16)
        s = bpy.context.object
        s.data.materials.append(red if n == 1 else black)
        pips.append(s)

# 目をひとつにまとめてからくり抜く（くぼみの面に目の色が移る）
bpy.ops.object.select_all(action="DESELECT")
for s in pips: s.select_set(True)
bpy.context.view_layer.objects.active = pips[0]
bpy.ops.object.join()
cutter = bpy.context.object; cutter.name = "Pips"
bo = die.modifiers.new("pips", "BOOLEAN")
bo.object = cutter; bo.operation = "DIFFERENCE"; bo.material_mode = "TRANSFER"
cutter.hide_render = True; cutter.hide_viewport = True
bpy.ops.object.select_all(action="DESELECT")
die.select_set(True); bpy.context.view_layer.objects.active = die
# 角を丸めてから（bevel）くり抜く（boolean）順に確定させる
bpy.ops.object.modifier_apply(modifier="bevel")
bpy.ops.object.modifier_apply(modifier="pips")
bpy.ops.object.shade_auto_smooth(angle=0.6)
# 検算：目の数＝くぼみの島の数
import bmesh
bm = bmesh.new(); bm.from_mesh(die.data)
for idx, m in enumerate(die.data.materials):
    if m.name == "ivory": continue
    name = m.name
    fs = {f for f in bm.faces if f.material_index == idx}
    seen, isl = set(), 0
    for f in fs:
        if f in seen: continue
        isl += 1; st = [f]
        while st:
            g = st.pop()
            if g in seen: continue
            seen.add(g)
            st += [h for e in g.edges for h in e.link_faces if h in fs and h not in seen]
    print(f"CHECK {name}の目: {isl} 個")
die.rotation_euler = (0, 0, 0.5)

stage(target=(0, 0, 0.45), cam_loc=(2.6, -2.9, 2.5), lens=60)
bpy.data.lights[0].energy = 300
out = os.path.join(os.path.dirname(__file__), "out")
os.makedirs(out, exist_ok=True)
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(out, "dice.blend"))
render(os.path.join(out, "dice.png"))
