def _get_colors(self, side: Side, i: int, j: int) -> List[Color]: orientation = Orientation.regular(side) front_side = self.cube.get_side(orientation) colors = [front_side.colors[i, j]] if i == 0 or i == front_side.rows - 1: if i == 0: top_side = self.cube.get_side(orientation.to_top) color = top_side.colors[top_side.rows - 1, j] else: bottom_side = self.cube.get_side(orientation.to_bottom) color = bottom_side.colors[0, j] colors.insert(0 if side in {Side.FRONT, Side.BACK} else 1, color) if j == 0 or j == front_side.columns - 1: if j == 0: left_side = self.cube.get_side(orientation.to_left) color = left_side.colors[i, left_side.columns - 1] else: right_side = self.cube.get_side(orientation.to_right) color = right_side.colors[i, 0] colors.insert(0, color) if len(colors) == 3: return [colors[2], colors[0], colors[1]] return colors
def from_arguments(args: Namespace, cube: Cube, parser: ArgumentParser) -> Optional["Label"]: if args.label_data is None: return None image, scale = args.label_data texture = Texture(image, GL_RGBA, flip=True, mipmap=True) if args.label_side is not None: side = args.label_side else: side = Side.TOP face = cube.get_side(Orientation.regular(side)) if args.label_position is not None: i, j = args.label_position if i < 0 or i >= face.rows: parser.error(f"invalid label row: it must be between 0 and {face.rows - 1}") return None if j < 0 or j >= face.columns: parser.error(f"invalid label column: it must be between 0 and {face.columns - 1}") return None else: i = face.rows // 2 j = face.columns // 2 return Label(scale, texture, side, i, j)
def test_orientation_transform(orientation, turn): cube1 = Cube((3, 3, 3)) cube2 = Cube((3, 3, 3)) turn.perform(cube1, orientation) origin = Orientation() turn.from_orientation(orientation, origin).perform(cube2, origin) for side in Side: o = Orientation.regular(side) assert str(cube1.get_side(o).colors) == str(cube2.get_side(o).colors)
def _generate(self) -> List[CubePart]: parts = [] for side, i, j in self.cube.iterate_components(): x, y, z = self.cube.get_absolute_coordinates(side, i, j) y = self.cube.shape[2] - 1 - y z = self.cube.shape[1] - 1 - z part = self._create_part(x, y, z, self._get_colors(side, i, j)) parts.append(part) self.cube.set_data(Orientation.regular(side), i, j, part) return parts
def assert_solved(cube: Cube): for front in Side: face = cube.get_side(Orientation.regular(front)) color = None for row in range(face.rows): for column in range(face.columns): c = face.colors[row, column] if color is None: color = c else: assert c == color
def _create_turn_animation(self, action: Turn) -> Animation: turns = action.turns if turns == 3: turns = -1 if action.type == TurningType.HORIZONTAL: turns = -turns angle = math.radians(90 * turns) if action.type == TurningType.SLICE: axis = "z" side = Side.FRONT elif action.type == TurningType.VERTICAL: axis = "x" side = Side.LEFT else: axis = "y" side = Side.TOP orientation = Orientation.regular(side) width = self.cube.cube.get_side(orientation).columns components = set() for index in Turn.normalize_indices(action.indices, width): index -= 1 if index == 0: components.update(self._get_parts_front(orientation)) elif index == width - 1: components.update( self._get_parts_front(orientation.to_right.to_right)) components.update( self._get_parts_slice(orientation.to_right, index)) def execution_callback(value: float) -> None: for component in components: component.set_temp_rotation(**{axis: value}) def completion_callback() -> None: for component in components: component.apply_temp_rotation() self._run_animation() self.completed_count += 1 return FloatAnimation(0.0, angle, execution_callback, ease_in_out_quad, completion_callback, fraction_callback=self._fraction_callback)
def __init__(self, cube: CubeModel[CubePart], label: Optional[Label], color_theme: Dict[Color, Tuple[float, float, float]]): self.cube: CubeModel[CubePart] = cube self.label = label self.color_theme = color_theme self.shader = Program("object") self.shader.use() DirectionalLight.push_uniform_array(self.shader, "lights", CubePart.LIGHTS) models_path = Path(__file__).parents[1] / "models" self.vao_corner = load_obj(models_path / "corner.obj") self.vao_edge = load_obj(models_path / "edge.obj") self.vao_flat = load_obj(models_path / "flat.obj") self.stickers_texture = Texture.load("stickers", flip=True, mipmap=True) self.labels_texture = Texture.load("labels", flip=True, mipmap=True) self.parts: List[CubePart] = self._generate() if self.label is not None: orientation = Orientation.regular(self.label.side) side = self.cube.get_side(orientation) row, column = self.label.row, self.label.column rot_i = 0 if row == 0 else 2 if row == side.rows - 1 else 1 rot_j = 0 if column == 0 else 2 if column == side.columns - 1 else 1 part = side[row, column].data rotation, color = CubePart.LABEL_ROTATIONS[ self.label.side][rot_i][rot_j] part.label_rotation = rotation part.label_visible = color self.rotation = IDENTITY self.temp_rotation = [0, 0, 0]
def _iterate_orientations(): for side in Side: orientation = Orientation.regular(side) for i in range(4): yield orientation orientation = orientation.rotate_clockwise()
def test_regular_orientation(front: Side, top: Side) -> None: orientation = Orientation.regular(front) assert orientation.front == front assert orientation.top == top