128 lines
11 KiB
Python
128 lines
11 KiB
Python
# Executed by add_daily_life.py inside the scene's construction context.
|
|
# Replace the old simplified kitchen, retaining its position and the shared room.
|
|
old_prefixes=('Simple timber kitchen cabinet','Flat cabinet pull','Continuous kitchen worktop','Stainless sink','Exposed kitchen tap','Tap spout','Induction cooktop','Open timber kitchen shelf','Pantry ceramic jar')
|
|
for o in list(bpy.data.objects):
|
|
if o.name.startswith(old_prefixes):bpy.data.objects.remove(o,do_unlink=True)
|
|
# Pale marble: distorted fine mineral veins, soft honed reflections.
|
|
marble=mat('Honed natural marble - ivory and warm grey veins',(.78,.76,.70),.26)
|
|
ns=marble.node_tree.nodes;ls=marble.node_tree.links;bs=ns.get('Principled BSDF')
|
|
coord=ns.new('ShaderNodeTexCoord');noise=ns.new('ShaderNodeTexNoise');noise.inputs['Scale'].default_value=2.8;noise.inputs['Detail'].default_value=5
|
|
ls.new(coord.outputs['Generated'],noise.inputs['Vector'])
|
|
scale=ns.new('ShaderNodeVectorMath');scale.operation='SCALE';scale.inputs[3].default_value=.33;ls.new(noise.outputs['Color'],scale.inputs[0])
|
|
add=ns.new('ShaderNodeVectorMath');add.operation='ADD';ls.new(coord.outputs['Generated'],add.inputs[0]);ls.new(scale.outputs[0],add.inputs[1])
|
|
wave=ns.new('ShaderNodeTexWave');wave.wave_type='BANDS';wave.bands_direction='DIAGONAL';wave.inputs['Scale'].default_value=3.7;wave.inputs['Distortion'].default_value=6;wave.inputs['Detail'].default_value=4;ls.new(add.outputs[0],wave.inputs['Vector'])
|
|
ramp=ns.new('ShaderNodeValToRGB');ramp.color_ramp.elements[0].position=.055;ramp.color_ramp.elements[0].color=(.20,.21,.20,1);ramp.color_ramp.elements[1].position=.14;ramp.color_ramp.elements[1].color=(.81,.79,.73,1)
|
|
ls.new(wave.outputs['Color'],ramp.inputs[0]);ls.new(ramp.outputs[0],bs.inputs['Base Color'])
|
|
fine=ns.new('ShaderNodeTexNoise');fine.inputs['Scale'].default_value=170;ls.new(coord.outputs['Generated'],fine.inputs['Vector']);bump=ns.new('ShaderNodeBump');bump.inputs['Strength'].default_value=.10;bump.inputs['Distance'].default_value=.0005;ls.new(fine.outputs['Fac'],bump.inputs['Height']);ls.new(bump.outputs[0],bs.inputs['Normal'])
|
|
copperpot=textured('Copper cookware - brushed warm patina',(.32,.10,.035),(.72,.34,.13),(75,75,8),.26,.0006);copperpot.node_tree.nodes['Principled BSDF'].inputs['Metallic'].default_value=.94
|
|
stainless=mat('Cookware food-contact stainless lining',(.55,.59,.61),.23,.96)
|
|
ovenblack=mat('Oven and induction reflective smoked glass',(.009,.016,.019),.12,.25)
|
|
mark=mat('Induction subtle etched markings',(.36,.42,.42),.45)
|
|
display=mat('Appliance soft white display',(.72,.82,.75),.3);display.node_tree.nodes['Principled BSDF'].inputs['Emission Color'].default_value=(.65,.85,.74,1);display.node_tree.nodes['Principled BSDF'].inputs['Emission Strength'].default_value=.6
|
|
# Run of detailed cabinets, including a 600 mm oven bay.
|
|
for i,(x,w) in enumerate([(-5.15,.72),(-4.32,.90),(-3.36,.96),(-2.38,.96),(-1.49,.78),(-.88,.42)]):
|
|
box('Kitchen timber cabinet carcass',(x,-2.53,F+.45),(w,.64,.88),wood,.008)
|
|
box('Kitchen recessed dark plinth',(x,-2.53,F+.075),(w-.06,.55,.13),steel,.006)
|
|
if i==4:continue
|
|
for row,h in enumerate([.29,.56,.79]):
|
|
box('Kitchen flush timber drawer',(x,-2.194,F+h),(w-.018,.032,.22 if row<2 else .19),wood,.006)
|
|
rod('Kitchen brushed drawer pull',(x-.14,-2.162,F+h+.065),(x+.14,-2.162,F+h+.065),.009,metal,sides=12)
|
|
# Worktop parts leave a real sink opening at x=-4.32.
|
|
for x,w in [(-5.15,.80),(-2.405,3.21)]:box('Kitchen honed marble rear worktop',(x,-2.52,F+.925),(w,.75,.045),marble,.008)
|
|
for y,d in [(-2.80,.19),(-2.225,.16)]:box('Sink cutout marble edge',(-4.32,y,F+.925),(.86,d,.045),marble,.005)
|
|
box('Kitchen marble low splashback',(-3.1,-2.905,F+1.09),(4.95,.025,.28),marble,.006)
|
|
# Recessed sink basin with separate bottom and four walls.
|
|
box('Sink recessed basin floor',(-4.32,-2.5,F+.73),(.66,.40,.025),stainless,.015)
|
|
for x in [-4.66,-3.98]:box('Sink basin side',(x,-2.5,F+.825),(.025,.42,.20),stainless,.009)
|
|
for y in [-2.715,-2.285]:box('Sink basin end',(-4.32,y,F+.825),(.70,.025,.20),stainless,.009)
|
|
rod('Sink drain',(-4.32,-2.5,F+.744),(-4.32,-2.5,F+.750),.044,steel,sides=32)
|
|
# Curved copper tap, exposed and replaceable.
|
|
pts=[(-4.32,-2.8,F+.95),(-4.32,-2.8,F+1.26)]
|
|
for i in range(17):
|
|
a=pi-pi*i/16;pts.append((-4.32,-2.69+.11*cos(a),F+1.26+.11*sin(a)))
|
|
for i,(a,b) in enumerate(zip(pts,pts[1:])):rod('Copper mixer tap '+str(i),a,b,.014,copperpot,sides=16)
|
|
rod('Tap outlet',pts[-1],(-4.32,-2.58,F+1.20),.014,copperpot,sides=16)
|
|
rod('Tap lever',(-4.20,-2.78,F+.95),(-4.20,-2.78,F+1.07),.01,stainless,sides=12)
|
|
# Built-in oven, facing the living room (north).
|
|
ox=-1.49
|
|
box('OVEN - brushed steel surround',(ox,-2.177,F+.49),(.62,.04,.68),metal,.013)
|
|
box('OVEN - insulated glass door',(ox,-2.144,F+.43),(.555,.032,.44),ovenblack,.015)
|
|
box('Oven inner viewing panel',(ox,-2.125,F+.435),(.435,.006,.285),mat('Oven glass subtle interior',(.025,.035,.035),.18),.018)
|
|
for z in [F+.37,F+.49]:box('Oven internal rack hint',(ox,-2.120,z),(.39,.004,.008),metal)
|
|
rod('Oven tubular handle',(ox-.23,-2.085,F+.663),(ox+.23,-2.085,F+.663),.018,metal,sides=20)
|
|
for x in [ox-.22,ox+.22]:rod('Oven handle standoff',(x,-2.14,F+.663),(x,-2.085,F+.663),.012,metal,sides=16)
|
|
box('Oven control fascia',(ox,-2.142,F+.779),(.57,.028,.115),ovenblack,.007)
|
|
for x in [ox-.205,ox+.205]:rod('Oven rotary dial',(x,-2.13,F+.78),(x,-2.097,F+.78),.027,metal,sides=32)
|
|
box('Oven display',(ox,-2.121,F+.78),(.14,.004,.036),display,.002)
|
|
for i in range(9):box('Oven bottom ventilation slot',(ox-.24+i*.06,-2.15,F+.17),(.035,.009,.011),black,.002)
|
|
# Four-zone induction glass and etched circles.
|
|
box('INDUCTION - four zone glass cooktop',(-1.49,-2.51,F+.961),(.70,.53,.018),ovenblack,.009)
|
|
def horizontal_ring(name,x,y,z,r,t,material):
|
|
ob=ring(name,(0,0,0),r,t,material);ob.rotation_euler.x=pi/2;ob.location=(x,y,z);return ob
|
|
for x,y,r in [(-1.67,-2.64,.105),(-1.30,-2.64,.086),(-1.68,-2.40,.082),(-1.32,-2.40,.103)]:
|
|
horizontal_ring('Induction etched cooking zone',x,y,F+.973,r,.0012,mark)
|
|
for i in range(7):box('Induction touch slider',(-1.65+i*.05,-2.277,F+.972),(.019,.009,.002),mark,.001)
|
|
# Slim extraction canopy with visible duct; no hidden construction language.
|
|
box('Kitchen extraction hood',(-1.49,-2.49,F+1.68),(.82,.54,.075),metal,.01)
|
|
for x in [-1.74,-1.24]:box('Hood warm task light',(x,-2.35,F+1.639),(.08,.12,.003),cream)
|
|
rod('Exposed kitchen extraction duct',(-1.49,-2.60,F+1.71),(-1.49,-2.60,F+2.33),.105,metal,sides=48)
|
|
# Timber shelving away from hob and exposed copper cookware rail.
|
|
box('Kitchen upper hardwood shelf',(-3.96,-2.72,F+1.84),(2.77,.32,.05),wood,.008)
|
|
rod('Copper cookware hanging rail',(-5.1,-2.57,F+1.52),(-2.75,-2.57,F+1.52),.014,copperpot,sides=20)
|
|
for x in [-5.04,-2.81]:rod('Cookware rail wall bracket',(x,-2.89,F+1.52),(x,-2.57,F+1.52),.012,metal,sides=16)
|
|
# Hollow copper vessels with stainless lining; induction-compatible base concept.
|
|
def vessel(n,x,y,z,r,h):
|
|
N=64;profile=[(0,0),(r*.83,0),(r,.025),(r,h),(r-.012,h+.003),(r-.016,.036),(0,.036)]
|
|
vs=[(x+rr*cos(i*2*pi/N),y+rr*sin(i*2*pi/N),z+zz) for rr,zz in profile for i in range(N)]
|
|
fs=[]
|
|
for j in range(len(profile)-1):
|
|
for i in range(N):fs.append((j*N+i,j*N+(i+1)%N,(j+1)*N+(i+1)%N,(j+1)*N+i))
|
|
ob=mesh(n,vs,fs,copperpot);ob.data.materials.append(stainless)
|
|
for p in ob.data.polygons:p.use_smooth=True;p.material_index=1 if p.index//N>=3 else 0
|
|
rod(n+' induction compatible base concept',(x,y,z-.003),(x,y,z+.004),r*.85,stainless,sides=64)
|
|
horizontal_ring(n+' rolled rim',x,y,z+h,r-.005,.006,stainless)
|
|
return ob
|
|
vessel('COPPER STOCKPOT',-2.91,-2.50,F+.954,.18,.235)
|
|
for x in [-3.13,-2.69]:
|
|
rod('Stockpot handle',(x,-2.57,F+1.12),(x,-2.43,F+1.12),.012,metal,sides=16)
|
|
for y in [-2.57,-2.43]:rod('Stockpot handle fixing',(x,y,F+1.12),(x+(.055 if x<-2.9 else -.055),y,F+1.12),.009,metal,sides=12)
|
|
vessel('COPPER SAUCEPAN',-1.32,-2.40,F+.977,.09,.09)
|
|
rod('Saucepan handle',(-1.22,-2.40,F+1.05),(-.95,-2.40,F+1.09),.012,metal,sides=20)
|
|
vessel('COPPER FRYING PAN',-3.45,.02,F+.965,.155,.037)
|
|
rod('Frying pan long handle',(-3.29,.02,F+1.0),(-3.0,.02,F+1.03),.013,metal,sides=20)
|
|
# Marble-topped island: central prep surface clear of the dining table.
|
|
ix,iy=-3.8,.10
|
|
box('ISLAND - warm timber cabinet body',(ix,iy,F+.44),(2.05,.83,.88),wood,.012)
|
|
box('ISLAND - recessed plinth',(ix,iy,F+.06),(1.93,.73,.12),steel,.007)
|
|
box('ISLAND - honed marble countertop',(ix,iy,F+.94),(2.2,.95,.06),marble,.012)
|
|
for x in [ix-.68,ix,ix+.68]:
|
|
for z in [.30,.69]:
|
|
box('Island drawer front',(x,iy-.425,F+z),(.657,.028,.36),wood,.006)
|
|
rod('Island drawer pull',(x-.14,iy-.448,F+z+.09),(x+.14,iy-.448,F+z+.09),.009,metal,sides=16)
|
|
for i in range(29):box('Island north face timber slat',(ix-.98+i*.07,iy+.425,F+.49),(.042,.023,.75),woodz,.004)
|
|
box('Island end grain chopping board',(-4.37,.14,F+.985),(.45,.34,.03),wood,.015)
|
|
# Tea crockery and pantry objects add scale without filling the work surface.
|
|
for x in [-5.03,-4.67,-4.30]:
|
|
vessel('Shelf ceramic storage vessel',x,-2.71,F+1.87,.085,.18)
|
|
for ob in list(col.objects):
|
|
if ob.name.startswith('Shelf ceramic storage vessel') and ob.type=='MESH':
|
|
for slot in range(len(ob.data.materials)):ob.data.materials[slot]=cream
|
|
# Rebuild only the old furniture proxy so replaced kitchen blocks disappear in fast view.
|
|
furniture=bpy.data.collections.get('10 Furniture');fast=bpy.data.collections['00 FAST TOUR - lightweight viewport']
|
|
oldproxy=bpy.data.objects.get('FAST | 10 Furniture')
|
|
if oldproxy and furniture:
|
|
vs=[];fs=[];indices=[];materials=[];mapping={}
|
|
for ob in furniture.objects:
|
|
if ob.type!='MESH' or ob.hide_render:continue
|
|
remap=[]
|
|
for m in ob.data.materials:
|
|
if m not in mapping:mapping[m]=len(materials);materials.append(m)
|
|
remap.append(mapping[m])
|
|
world=Matrix.LocRotScale(ob.location.copy(),ob.rotation_euler.to_quaternion(),ob.scale.copy());off=len(vs);vs.extend(tuple(world@v.co) for v in ob.data.vertices)
|
|
for poly in ob.data.polygons:fs.append(tuple(off+j for j in poly.vertices));indices.append(remap[poly.material_index])
|
|
me=bpy.data.meshes.new('Furniture after kitchen replacement');me.from_pydata(vs,[],fs);me.update()
|
|
for m in materials:me.materials.append(m)
|
|
me.polygons.foreach_set('material_index',indices);oldproxy.data=me
|
|
kitchen_checks={'oven':1,'induction_zones':4,'copper_stockpot':1,'copper_saucepan':1,'copper_frying_pan':1,'marble_island_m':[2.2,.95],'island_rear_work_aisle_m':1.67,'old_simplified_kitchen_removed':True,'fast_furniture_refreshed':bool(oldproxy)}
|
|
s['Kitchen design']='Honed marble island, detailed timber drawers, oven, four-zone induction, extraction, hollow copper cookware with stainless food-contact lining and an induction-compatible base concept.'
|