Merge pull request #2 from KAymeric/Entrance

Entrance
This commit is contained in:
KAymeric
2024-06-14 03:22:54 +02:00
committed by GitHub
14 changed files with 226 additions and 52 deletions

View File

@@ -1,6 +1,10 @@
import random as rd
from utils.Enums import DIRECTION
from gdpc import Editor, Block, geometry
from buildings.Foundations import Foundations
from buildings.Facade import Facade
from buildings.Entrance import Entrance
from buildings.Roof import Roof
class Building:
def __init__(self,rdata, position : tuple[int,int], size : tuple[int, int], matrice : list[list[int]], floors : int):
@@ -14,16 +18,21 @@ class Building:
self.foundations = Foundations(rdata["foundations"], size, matrice, tile_size,)
self.facade = Facade(rdata["facade"], self.foundations.vertices, self.foundations.is_inner_or_outer)
self.entrance = Entrance(rdata, self.foundations.vertices, DIRECTION.EAST, self.foundations.is_inner_or_outer)
self.roof = Roof(rdata["roof"], self.foundations.polygon)
def build(self, editor, materials : list[str]):
for y in range(self.floors):
with editor.pushTransform((self.position[0], y*(self.foundations.floor_height+1), self.position[1])):
def build(self, editor : Editor, materials : list[str]):
for y in range(self.floors+1):
with editor.pushTransform((self.position[0], y*(self.foundations.floor_height+1) -1, self.position[1])):
if y == self.floors:
self.roof.build(editor, materials)
break
self.foundations.build(editor, materials)
self.facade.build(editor, materials)
if y == 0: self.entrance.build(editor, materials)
else : self.facade.build(editor, materials)
def gen_tile_size(self) -> int:
# Tiles are constant square units different for each buildings
return self.length
smaller_side = min(self.length, self.width)
# area is too small, will work but not very well

View File

@@ -0,0 +1,114 @@
import random as rd
from gdpc import Editor, Block, geometry
from utils.Enums import DIRECTION,COLLUMN_STYLE
from buildings.geometry.Vertice import Vertice
from buildings.Facade import Facade
class Entrance:
def __init__(self,
rdata,
vertices : list[Vertice],
direction : DIRECTION,
collumn_style : COLLUMN_STYLE):
self.vertices = self.correct_vertices(vertices)
self.direction = direction
self.rdata = rdata
self.collumn_style = collumn_style
self.is_centered = self.is_centered()
self.door_vertice, self.facade = self.get_door_and_facade()
self.door_width, self.door_height, self.padding, self.ypadding = self.get_door_dimention()
self.editor, self.materials = None,None
def build(self, editor : Editor, materials : list[str]):
self.editor = editor
self.materials = materials
self.correct_facade()
with self.editor.pushTransform((0,1,0)):
self.facade.build(self.editor, self.materials)
self.build_door()
def build_door(self):
# self.padding is the padding from the door to the facade, padding is the padding from the door+self.padding to the end of the vertice
padding = (len(self.door_vertice) - (self.padding*2 + self.door_width // 2)) // 2
self.door_vertice.fill(self.editor, self.materials[0],
y = self.door_height+self.ypadding,
xpadding = padding,
zpadding = padding)
# padding is now the padding from the door to the end of the vertice
padding += self.padding
self.door_vertice.fill(self.editor, "air",
y = self.door_height,
xpadding = padding,
zpadding = padding)
def correct_facade(self):
self.facade.has_balcony = False
def correct_vertices(self, vertices : list[Vertice]) -> list[Vertice]:
for v in vertices:
v.point2.set_position(y=v.point2.y-1)
return vertices
def is_centered(self) -> bool:
return rd.random() <= self.rdata["entrance"]["centered"]
def get_door_and_facade(self) -> tuple[Vertice, Facade]:
oriented_vertices = self.get_oriented_vertices()
door_vertice = None
if self.is_centered:
oriented_vertices.sort(key = lambda v: v.point1.x if self.direction.value % 2 == 0 else v.point1.z) # if direction is north or south, sort by x, else sort by z
mid = len(oriented_vertices) // 2
ver1, ver2 = oriented_vertices[mid], oriented_vertices[-mid-1]
if ver1.point1.x != ver2.point1.x and ver1.point1.z != ver2.point1.z:
door_vertice = rd.choice([ver1, ver2])
elif ver1.point1.position == ver2.point1.position:
door_vertice = ver1
else :
door_vertice = Vertice(ver2.point1.copy(), ver1.point2.copy())
else:
door_vertice = rd.choice(oriented_vertices)
facade = Facade(self.rdata["facade"], self.vertices, self.collumn_style)
return(door_vertice, facade)
def get_oriented_vertices(self) -> list[Vertice]:
# Get all the vertice that can contain the door
# if direction is north or south, compare by x, else compare by z
compare = lambda v: (v.point1.z,v.point1.x) if self.direction.value % 2 == 0 else (v.point1.x,v.point1.z)
# if direction is north or west, the most off_centered is the maximum, else it is the minimum
off_centered = lambda p1,p2: max(p1,p2) if self.direction == DIRECTION.NORTH or self.direction == DIRECTION.WEST else min(p1,p2)
oriented_vertices = []
for v in self.vertices:
if v.facing != self.direction: continue
sortby,position = compare(v)
alreadyset = False
for ov in oriented_vertices:
ov_sorted, ov_position = compare(ov)
if position == ov_position:
if off_centered(sortby,ov_sorted) == sortby: oriented_vertices.remove(ov)
else: alreadyset = True
if not alreadyset: oriented_vertices.append(v)
return oriented_vertices
def get_door_dimention(self) -> tuple[int,int,int,int]: # return width, height, padding, ypadding
max_width = len(self.door_vertice) - 2
max_height = self.door_vertice.get_height() - 1
door_width = rd.randint(self.rdata["entrance"]["door"]["size"]["min_width"], self.rdata["entrance"]["door"]["size"]["max_width"])
door_height = rd.randint(self.rdata["entrance"]["door"]["size"]["min_height"], self.rdata["entrance"]["door"]["size"]["max_height"])
xpadding = rd.randint(1, self.rdata["entrance"]["door"]["padding"]["max"])
ypadding = rd.randint(1, self.rdata["entrance"]["door"]["padding"]["max_top"])
if door_width > max_width: door_width = max_width
if door_height > max_height: door_height = max_height
if xpadding*2 + door_width > max_width: xpadding += (max_width - (xpadding*2 + door_width)-1)//2
if ypadding + door_height > max_height: ypadding += max_height - (ypadding + door_height)
return door_width,door_height,xpadding,ypadding

View File

@@ -8,7 +8,10 @@ from buildings.elements.Window import Window
from buildings.elements.Balcony import Balcony
class Facade:
def __init__(self, rdata, vertices : list[Vertice], collumn_style : COLLUMN_STYLE):
def __init__(self,
rdata,
vertices : list[Vertice],
collumn_style : COLLUMN_STYLE):
self.rdata = rdata
self.vertices = vertices
self.collumn_style = collumn_style
@@ -37,10 +40,10 @@ class Facade:
def correct_corners(self,points : list[Point], v : Vertice):
if self.padding == 0:
if self.window.border_radius != 0 and self.window.width == self.length:
if v.point1 in points:
if points.count(v.point1) >= 2:
self.editor.placeBlock((0,self.window.ypadding,0), Block(self.materials[8]))
self.editor.placeBlock((0,self.window.ypadding+self.window.height,0), Block(self.materials[8], {"type": "top"}))
if v.point2 in points:
if points.count(v.point2) >= 2:
self.editor.placeBlock((self.length-1,self.window.ypadding,0), Block(self.materials[8]))
self.editor.placeBlock((self.length-1,self.window.ypadding+self.window.height,0), Block(self.materials[8], {"type": "top"}))
@@ -51,16 +54,16 @@ class Facade:
elif self.inter_floor_border_style == INTER_FLOOR_BORDER.STAIRS:
material = Block(self.materials[4], {"facing": "south", "half": "top"})
if v.point1 in points:
if points.count(v.point1) >= 2:
self.editor.placeBlock((-1,self.height,-1), material)
if v.point2 in points:
if points.count(v.point2) >= 2:
self.editor.placeBlock((self.length,self.height,-1), material)
def get_window(self) -> Window:
if self.collumn_style.value >= 2: # collumn_style >= 2 = outer collumns
self.padding = 1
max_width = self.length-2*self.padding
max_height = min(self.height, self.rdata["windows"]["size"]["max_height"])
@@ -81,6 +84,6 @@ class Facade:
def has_inter_floor(self) -> bool:
return (self.rdata["inter_floor"]["proba"] >= rd.random(), select_random(self.rdata["inter_floor"]["border_style"], INTER_FLOOR_BORDER))
def get_dimentions(self) -> tuple[int]:
def get_dimentions(self) -> tuple[int,int]:
return ( self.vertices[0].get_height(), len(self.vertices[0]))

View File

@@ -45,7 +45,7 @@ class Foundations:
for collumn in self.collumns:
if collumn.is_outer and self.is_inner_or_outer == COLLUMN_STYLE.INNER: continue
if not collumn.is_outer and self.is_inner_or_outer == COLLUMN_STYLE.OUTER: continue
collumn.fill(editor, materials[7], self.floor_height)
collumn.fill(editor, materials[7], self.floor_height+1)
def add_tile(self, tile : Tile):
self.tiles.append(tile)

15
buildings/Roof.py Normal file
View File

@@ -0,0 +1,15 @@
import random as rd
from buildings.geometry.Polygon import Polygon
class Roof:
def __init__(self,rdata, polygon : Polygon):
self.rdata = rdata
self.polygon = polygon
self.has_rembard = self.has_rembard()
def build(self, editor, materials : list[str]):
self.polygon.fill(editor, materials[0])
if self.has_rembard: self.polygon.fill_vertice(editor, materials[9],1)
def has_rembard(self):
return rd.random() <= self.rdata["rembard"]

View File

@@ -1,13 +1,19 @@
Encadrement fenêtre
toit de balcon avec/sans pilliers
border radius balcon
collumn style
rembard object
détails facade
rdc
toit
toit (clim, chateau deau, pubs)
tiles 3d
textures object
opti textures
opti géométrique
opti gdpc
opti gdpc
pilliers quand trop de fenêtres + pas de pilliers si tile trop petite
limitateur taille
facade lisses/ immeubles collés
matrices pré-distribués
angles 270
bug entrée au milieu du O
bug entrée dans le pillier

View File

@@ -7,7 +7,11 @@ from buildings.geometry.Vertice import Vertice
from buildings.elements.Window import Window
class Balcony:
def __init__(self, rdata, max_width : int, windows : Window, collumn_style : COLLUMN_STYLE):
def __init__(self,
rdata,
max_width : int,
windows : Window,
collumn_style : COLLUMN_STYLE):
self.rdata = rdata
self.windows = windows
self.max_width = max_width

View File

@@ -5,7 +5,7 @@ class FacadeDetails:
self.zones = zones
self.sizes = self.get_sizes()
def get_sizes(self) -> list[tuple[int]]:
def get_sizes(self) -> list[tuple[int,int,int]]:
# foreach different zone sizes in self.zones, we will gen different details
sizes = []
center_for_symetry = len(self.zones) // 2

View File

@@ -8,7 +8,12 @@ from buildings.geometry.Vertice import Vertice
from buildings.elements.WindowElt.Glass import Glass
class Window:
def __init__(self, rdata, max_width : int, max_height : int, facade_len : int, facade_height : int):
def __init__(self,
rdata,
max_width : int,
max_height : int,
facade_len : int,
facade_height : int):
self.rdata = rdata
self.width, self.height = self.get_size(max_width, max_height)
self.is_grounded = self.is_grounded()
@@ -121,7 +126,7 @@ class Window:
rd.randint(self.rdata["size"]["min_height"],max_height)
)
def get_padding(self, facade_len : int, facade_height : int) -> tuple[int]:
def get_padding(self, facade_len : int, facade_height : int) -> tuple[int,int]:
padding,ypadding = 0,0
if not self.is_grounded: ypadding = (facade_height - self.height)//2

View File

@@ -1,12 +1,12 @@
class Point:
def __init__(self, x : int = 0, y : int = 0, z : int = 0, p : tuple[int] = None):
def __init__(self, x : int = 0, y : int = 0, z : int = 0, p : tuple[int,int,int] = None):
if p != None: x,y,z = p
self.x = x
self.y = y
self.z = z
self.position = (x,y,z)
def set_position(self, x : int = 0, y : int = 0, z : int = 0, p : tuple[int] = None):
def set_position(self, x : int = None, y : int = None, z : int = None, p : tuple[int,int,int] = None):
if p != None: x,y,z = p
self.x = x if x != None else self.x
self.y = y if y != None else self.y
@@ -14,4 +14,7 @@ class Point:
self.position = (self.x,self.y,self.z)
def __repr__(self):
return f"Point({self.position})"
return f"Point({self.position})"
def copy(self) -> 'Point':
return Point(self.x, self.y, self.z)

View File

@@ -18,9 +18,10 @@ class Polygon:
rect.fill(editor, material, y2)
def fill_vertice(self, editor : Editor, material : str, y : int, y2 : int = None):
if y2 == None: y2 = y
if y2 == None: y2 = 0
for vertice in self.vertices:
vertice.fill(editor, Block(material), y, y2)
with editor.pushTransform(Transform((0,y,0))):
vertice.fill(editor, material, y2)
def compress(self, tiles : list[Tile], vertices : list[Vertice]):
remaining_tiles = tiles.copy()
@@ -58,9 +59,9 @@ class Polygon:
has_next2 = self._has_next(neighbors[1], current.facing, remaining_vertices)
if has_next1:
current = Vertice(has_next1.point1, current.point2, current.facing)
current = Vertice(has_next1.point1.copy(), current.point2.copy(), current.facing)
elif has_next2:
current = Vertice(current.point1, has_next2.point2, current.facing)
current = Vertice(current.point1.copy(), has_next2.point2.copy(), current.facing)
else:
self.vertices.append(current)
current = remaining_vertices.pop()
@@ -89,7 +90,7 @@ class Polygon:
for tile in new_line: remaining_tiles.remove(tile)
line = new_line
def _has_neighbor(self, target : tuple[int], tiles : list[Tile]) -> bool|Tile:
def _has_neighbor(self, target : Point, tiles : list[Tile]) -> bool|Tile:
for tile in tiles:
if tile.pos.position == target.position:
return tile

View File

@@ -61,16 +61,16 @@ class Tile:
def get_vertice(self,vertice : int|DIRECTION) -> Vertice:
# gives the corresponding vertice :
# 0 = north, 1 = west, 2 = south, 3 = east
# 0 = north, 1 = east, 2 = south, 3 = west
match(vertice):
case 0 :
return Vertice(self.north_west, self.north_east, DIRECTION.NORTH)
return Vertice(self.north_west.copy(), self.north_east.copy(), DIRECTION.NORTH)
case 1 :
return Vertice(self.north_west, self.south_west, DIRECTION.WEST)
return Vertice(self.north_east.copy(), self.south_east.copy(), DIRECTION.EAST)
case 2 :
return Vertice(self.south_west, self.south_east, DIRECTION.SOUTH)
return Vertice(self.south_west.copy(), self.south_east.copy(), DIRECTION.SOUTH)
case 3 :
return Vertice(self.north_east, self.south_east, DIRECTION.EAST)
return Vertice(self.north_west.copy(), self.south_west.copy(), DIRECTION.WEST)
case DIRECTION.WEST :
return self.west_vertice
case DIRECTION.EAST :
@@ -82,7 +82,7 @@ class Tile:
def set_vertice(self, direction : DIRECTION, vertice : Vertice, height : int):
self.has_vertice = True
vertice.point2.y = height
vertice.point2.set_position(y = height)
match(direction):
case DIRECTION.WEST :
self.west_vertice = vertice

19
main.py
View File

@@ -21,25 +21,26 @@ random_data = y.data
# with editor.pushTransform(Transform(rotation = i)):
# geometry.placeCuboid(editor, (0,0,0), (0,3,5), Block("stone"))
transform = Transform((0,-60,80),rotation = 0)
transform = Transform((0,-60,110),rotation = 0)
editor.transform.push(transform)
geometry.placeCuboid(editor, (-5,0,-8), (170,25,25), Block("air"))
geometry.placeCuboid(editor, (-5,0,-8), (60,10,70), Block("air"))
buildings = []
buildings.append(Building(random_data["buildings"], (0, 0), (20,20), shapes[0]['matrice'], 1))
buildings.append(Building(random_data["buildings"], (25, 0), (30,30), shapes[5]['matrice'], 1))
buildings.append(Building(random_data["buildings"], (0, 35), (30,30), shapes[6]['matrice'], 1))
buildings.append(Building(random_data["buildings"], (35, 35), (20,20), shapes[7]['matrice'], 1))
padd = 0
for i in range(4,13):
building = Building(random_data["buildings"], (padd, 0), (i,i), shapes[0]['matrice'], 3)
building.build(editor, ["stone_bricks","glass_pane","glass","cobblestone_wall","stone_brick_stairs","oak_planks","white_concrete","cobblestone","stone_brick_slab"])
padd += i + 10
for building in buildings :
building.build(editor, ["stone_bricks","glass_pane","glass","cobblestone_wall","stone_brick_stairs","oak_planks","white_concrete","cobblestone","stone_brick_slab","iron_bars"])
# # Get a block
# block = editor.getBlock((0,48,0))
# # Place a block
#editor.placeBlock((0 , 5, 0), Block("stone"))
# editor.placeBlock((0 , 5, 0), Block("stone"))
# # Build a cube
# geometry.placeCuboid(editor, (458, 92, 488), (468, 99, 471), Block("oak_planks"))

View File

@@ -8,7 +8,7 @@ buildings:
collumn_style :
# proportion of each style
none: 1
inner: 1
inner: 5
outer: 1
both: 1
floor:
@@ -62,17 +62,30 @@ buildings:
medium: 1
full: 1
Entrance:
centered: 0.8
different_facade: 0.75
size:
min_height: 5
max_height: 9
inter_floor:
proba: 0.5
border_style:
# bloc used to fill the corner of the interfloor
none: 1
slab: 2
stairs: 2
stairs: 2
entrance:
centered: 0.8
different_facade: 0.75
size:
min_height: 5
max_height: 9
door:
size:
min_height: 2
max_height: 4
min_width: 1
max_width: 3
padding:
max: 2
max_top: 2
roof:
rembard: 0.5