158 lines
5.3 KiB
Swift
158 lines
5.3 KiB
Swift
//
|
|
// BoardThumbnailImage.swift
|
|
// LifeGameApp (iOS)
|
|
//
|
|
// Created by Yusuke Hosonuma on 2020/08/09.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LifeGame
|
|
|
|
//#if os(macOS)
|
|
//private typealias XImage = NSImage
|
|
//#else
|
|
//private typealias XImage = UIImage
|
|
//#endif
|
|
//
|
|
//private let cacheStorage = MemoryCacheStorage<XImage>()
|
|
|
|
// TODO: 内部的に BoardRenderImage を利用するようにしたい。
|
|
|
|
public struct BoardThumbnailImage: View {
|
|
@Environment(\.colorScheme) var colorScheme
|
|
@Environment(\.redactionReasons) var reasons
|
|
|
|
private let board: Board<Cell>
|
|
private let cellColor: Color?
|
|
private let cacheKey: String?
|
|
private let scale: Int
|
|
|
|
public init(board: Board<Cell>, cellColor: Color? = nil, cacheKey: String? = nil) {
|
|
self.board = board.extended(by: .die, count: 1)
|
|
self.cellColor = cellColor
|
|
self.cacheKey = cacheKey
|
|
self.scale = max(2, 140 / board.size)
|
|
}
|
|
|
|
private var fillColor: Color {
|
|
if let color = cellColor {
|
|
return color
|
|
} else {
|
|
return colorScheme == .dark ? .white : .black
|
|
}
|
|
}
|
|
|
|
public var body: some View {
|
|
let renderWidth = CGFloat(board.size * scale + 1)
|
|
|
|
if reasons.isEmpty == false {
|
|
// TODO: 外枠だけレンダリングしたほうがいいような?
|
|
Color.gray.opacity(0.3)
|
|
.scaledToFit()
|
|
} else {
|
|
Canvas { context, size in
|
|
context.scaleBy(x: size.width / renderWidth, y: size.height / renderWidth)
|
|
|
|
//
|
|
// Render cells.
|
|
//
|
|
for (index, cell) in board.cells.enumerated() {
|
|
let x = (index % board.size) * scale
|
|
let y = (index / board.size) * scale
|
|
if cell == .alive {
|
|
context.fill(
|
|
Path(CGRect(origin: CGPoint(x: x, y: y), size: CGSize(width: scale, height: scale))),
|
|
with: .color(fillColor)
|
|
)
|
|
}
|
|
}
|
|
|
|
//
|
|
// Render grid.
|
|
//
|
|
for index in 0...board.size + 1 {
|
|
let length = board.size * scale + 1
|
|
|
|
// Vertical lines
|
|
context.fill(
|
|
Path(CGRect(x: scale * index, y: 0, width: 1, height: length)),
|
|
with: .color(.gridLine)
|
|
)
|
|
|
|
// Horizontal lines
|
|
context.fill(
|
|
Path(CGRect(x: 0, y: scale * index, width: length, height: 1)),
|
|
with: .color(.gridLine)
|
|
)
|
|
}
|
|
}
|
|
.scaledToFit()
|
|
}
|
|
|
|
// TODO: いったん既存のキャッシュ処理は無効化(必要そうだったらまた考える)
|
|
//
|
|
// Image(image: thumbnailImage)
|
|
// .antialiased(false)
|
|
// .resizable()
|
|
// .scaledToFit()
|
|
}
|
|
|
|
// private var thumbnailImage: XImage {
|
|
// guard let cacheKey = cacheKey else {
|
|
// return renderImage()
|
|
// }
|
|
//
|
|
// let key = "\(cacheKey)-\(fillColor.hashValue)-\(gridColor.hashValue)"
|
|
//
|
|
// if let image = cacheStorage.value(forKey: key) {
|
|
// return image
|
|
// } else {
|
|
// let image = renderImage()
|
|
// cacheStorage.store(key: key, image: image)
|
|
// return image
|
|
// }
|
|
// }
|
|
//
|
|
// private func renderImage() -> XImage {
|
|
// let scale = max(2, 140 / board.size)
|
|
// let size = CGSize(width: board.size * scale + 1, height: board.size * scale + 1)
|
|
//
|
|
// return GraphicsImageRenderer(size: size)
|
|
// .image(actions: { context in
|
|
// context.setFillColor(fillColor)
|
|
//
|
|
// for (index, cell) in board.cells.enumerated() {
|
|
// let x = (index % board.size) * scale
|
|
// let y = (index / board.size) * scale
|
|
// if cell == .alive {
|
|
// context.fill(CGRect(origin: CGPoint(x: x, y: y), size: CGSize(width: scale, height: scale)))
|
|
// }
|
|
// }
|
|
//
|
|
// // Draw grid
|
|
// context.setFillColor(gridColor)
|
|
// for index in 0...board.size + 1 {
|
|
// let length = board.size * scale + 1
|
|
// context.fill(CGRect(x: scale * index, y: 0, width: 1, height: length)) // vertical lines
|
|
// context.fill(CGRect(x: 0, y: scale * index, width: length, height: 1)) // horizontal lines
|
|
// }
|
|
// })
|
|
// }
|
|
}
|
|
|
|
struct BoardThumnailImage_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
view(preset: .nebura, colorScheme: .dark)
|
|
view(preset: .nebura, colorScheme: .light)
|
|
view(preset: .spaceShip, colorScheme: .dark)
|
|
}
|
|
|
|
static func view(preset: BoardPreset, colorScheme: ColorScheme) -> some View {
|
|
BoardThumbnailImage(board: preset.board.board)
|
|
.previewLayout(.fixed(width: 200.0, height: 200.0))
|
|
.colorScheme(colorScheme)
|
|
.preferredColorScheme(colorScheme)
|
|
.padding()
|
|
}
|
|
}
|