IDE perf tests for K/N: Produce duplicated *.kt files on demand
This commit is contained in:
+40
@@ -61,6 +61,7 @@ class PerformanceNativeProjectsTest : AbstractPerformanceProjectsTest() {
|
||||
|
||||
private enum class TestProject(
|
||||
val templateName: String,
|
||||
val duplicatesAmount: Int = 2,
|
||||
val filesToHighlight: List<String>
|
||||
) {
|
||||
HELLO_WORLD(
|
||||
@@ -85,6 +86,7 @@ class PerformanceNativeProjectsTest : AbstractPerformanceProjectsTest() {
|
||||
|
||||
init {
|
||||
assertTrue(filesToHighlight.isNotEmpty())
|
||||
assertTrue(duplicatesAmount in 0..100)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +232,44 @@ class PerformanceNativeProjectsTest : AbstractPerformanceProjectsTest() {
|
||||
fail("Some files have not been merged in project root directory: $projectRoot: ${unmergedFiles.joinToString()}")
|
||||
}
|
||||
|
||||
// produce N duplicates of *.kt files inside the project root
|
||||
if (testProject.duplicatesAmount > 0) {
|
||||
val originalKtFiles = projectRoot.walkTopDown()
|
||||
.filter { it.isFile && it.name.endsWith(".kt") }
|
||||
.toList()
|
||||
|
||||
for (originalKtFile in originalKtFiles) {
|
||||
val originalKtFileContents = originalKtFile.readLines()
|
||||
|
||||
assertTrue(
|
||||
"$originalKtFile must have @file:Suppress(\"PackageDirectoryMismatch\") annotation",
|
||||
originalKtFileContents.any { it.startsWith("@file:Suppress") && it.contains("\"PackageDirectoryMismatch\"") }
|
||||
)
|
||||
|
||||
val packageLineIndex = originalKtFileContents.indexOfFirst { it.startsWith("package perfTestPackage1") }
|
||||
assertTrue(
|
||||
"$originalKtFile must have package declaration: package perfTestPackage1",
|
||||
packageLineIndex != -1
|
||||
)
|
||||
|
||||
for (i in 1..testProject.duplicatesAmount) {
|
||||
val n = i + 1
|
||||
val duplicateKtFile = originalKtFile.resolveSibling("${originalKtFile.nameWithoutExtension}$n.kt")
|
||||
duplicateKtFile.writeText(
|
||||
buildString {
|
||||
originalKtFileContents.forEachIndexed { index, line ->
|
||||
if (index == packageLineIndex) {
|
||||
appendln(line.replace("perfTestPackage1", "perfTestPackage$n"))
|
||||
} else {
|
||||
appendln(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check all necessary files are there
|
||||
listOf("build.gradle.kts", "settings.gradle.kts", "gradle.properties")
|
||||
.filter { !projectRoot.resolve(it).exists() }
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package perfTestPackage1 // this package is mandatory
|
||||
|
||||
import kotlinx.cinterop.ByteVar
|
||||
import kotlinx.cinterop.allocArray
|
||||
import kotlinx.cinterop.memScoped
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import kotlinx.cinterop.ByteVar
|
||||
import kotlinx.cinterop.allocArray
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.toKString
|
||||
import kotlinx.cli.ArgParser
|
||||
import kotlinx.cli.ArgType
|
||||
import kotlinx.cli.required
|
||||
import platform.posix.fclose
|
||||
import platform.posix.fgets
|
||||
import platform.posix.fopen
|
||||
import platform.posix.perror
|
||||
import kotlin.collections.set
|
||||
|
||||
private fun parseLine(line: String, separator: Char) : List<String> {
|
||||
val result = mutableListOf<String>()
|
||||
val builder = StringBuilder()
|
||||
var quotes = 0
|
||||
for (ch in line) {
|
||||
when {
|
||||
ch == '\"' -> {
|
||||
quotes++
|
||||
builder.append(ch)
|
||||
}
|
||||
(ch == '\n') || (ch == '\r') -> {}
|
||||
(ch == separator) && (quotes % 2 == 0) -> {
|
||||
result.add(builder.toString())
|
||||
builder.setLength(0)
|
||||
}
|
||||
else -> builder.append(ch)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val argParser = ArgParser("csvparser")
|
||||
val fileName by argParser.argument(ArgType.String, description = "CSV file")
|
||||
val column by argParser.option(ArgType.Int, description = "Column to parse").required()
|
||||
val count by argParser.option(ArgType.Int, description = "Count of lines to parse").required()
|
||||
argParser.parse(args)
|
||||
|
||||
val file = fopen(fileName, "r")
|
||||
if (file == null) {
|
||||
perror("cannot open input file $fileName")
|
||||
return
|
||||
}
|
||||
|
||||
val keyValue = mutableMapOf<String, Int>()
|
||||
|
||||
try {
|
||||
memScoped {
|
||||
val bufferLength = 64 * 1024
|
||||
val buffer = allocArray<ByteVar>(bufferLength)
|
||||
|
||||
for (i in 1..count) {
|
||||
val nextLine = fgets(buffer, bufferLength, file)?.toKString()
|
||||
if (nextLine == null || nextLine.isEmpty()) break
|
||||
|
||||
val records = parseLine(nextLine, ',')
|
||||
val key = records[column]
|
||||
val current = keyValue[key] ?: 0
|
||||
keyValue[key] = current + 1
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fclose(file)
|
||||
}
|
||||
|
||||
keyValue.forEach {
|
||||
println("${it.key} -> ${it.value}")
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import kotlinx.cinterop.ByteVar
|
||||
import kotlinx.cinterop.allocArray
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.toKString
|
||||
import kotlinx.cli.ArgParser
|
||||
import kotlinx.cli.ArgType
|
||||
import kotlinx.cli.required
|
||||
import platform.posix.fclose
|
||||
import platform.posix.fgets
|
||||
import platform.posix.fopen
|
||||
import platform.posix.perror
|
||||
import kotlin.collections.set
|
||||
|
||||
private fun parseLine(line: String, separator: Char) : List<String> {
|
||||
val result = mutableListOf<String>()
|
||||
val builder = StringBuilder()
|
||||
var quotes = 0
|
||||
for (ch in line) {
|
||||
when {
|
||||
ch == '\"' -> {
|
||||
quotes++
|
||||
builder.append(ch)
|
||||
}
|
||||
(ch == '\n') || (ch == '\r') -> {}
|
||||
(ch == separator) && (quotes % 2 == 0) -> {
|
||||
result.add(builder.toString())
|
||||
builder.setLength(0)
|
||||
}
|
||||
else -> builder.append(ch)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val argParser = ArgParser("csvparser")
|
||||
val fileName by argParser.argument(ArgType.String, description = "CSV file")
|
||||
val column by argParser.option(ArgType.Int, description = "Column to parse").required()
|
||||
val count by argParser.option(ArgType.Int, description = "Count of lines to parse").required()
|
||||
argParser.parse(args)
|
||||
|
||||
val file = fopen(fileName, "r")
|
||||
if (file == null) {
|
||||
perror("cannot open input file $fileName")
|
||||
return
|
||||
}
|
||||
|
||||
val keyValue = mutableMapOf<String, Int>()
|
||||
|
||||
try {
|
||||
memScoped {
|
||||
val bufferLength = 64 * 1024
|
||||
val buffer = allocArray<ByteVar>(bufferLength)
|
||||
|
||||
for (i in 1..count) {
|
||||
val nextLine = fgets(buffer, bufferLength, file)?.toKString()
|
||||
if (nextLine == null || nextLine.isEmpty()) break
|
||||
|
||||
val records = parseLine(nextLine, ',')
|
||||
val key = records[column]
|
||||
val current = keyValue[key] ?: 0
|
||||
keyValue[key] = current + 1
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fclose(file)
|
||||
}
|
||||
|
||||
keyValue.forEach {
|
||||
println("${it.key} -> ${it.value}")
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package perfTestPackage1 // this package is mandatory
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("Hello World!")
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("Hello World!")
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("Hello World!")
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package perfTestPackage1 // this package is mandatory
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
private const val GREETING = "Hello, Kotlin/Native!"
|
||||
|
||||
class HelloTest2 {
|
||||
@Test
|
||||
fun testHello() {
|
||||
assertTrue("Kotlin/Native" in GREETING)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
private const val GREETING = "Hello, Kotlin/Native!"
|
||||
|
||||
class HelloTest3 {
|
||||
@Test
|
||||
fun testHello() {
|
||||
assertTrue("Kotlin/Native" in GREETING)
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -3,7 +3,8 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
|
||||
@file:Suppress("PackageDirectoryMismatch", "RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
|
||||
package perfTestPackage1 // this package is mandatory
|
||||
|
||||
import kotlinx.cinterop.FloatVar
|
||||
import kotlinx.cinterop.allocArray
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
|
||||
|
||||
import kotlinx.cinterop.FloatVar
|
||||
import kotlinx.cinterop.allocArray
|
||||
import kotlinx.cinterop.cValuesOf
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.set
|
||||
import kotlinx.cinterop.toCValues
|
||||
import platform.gles.GL_COLOR_BUFFER_BIT
|
||||
import platform.gles.GL_CULL_FACE
|
||||
import platform.gles.GL_CW
|
||||
import platform.gles.GL_DEPTH_BUFFER_BIT
|
||||
import platform.gles.GL_DEPTH_TEST
|
||||
import platform.gles.GL_DIFFUSE
|
||||
import platform.gles.GL_DITHER
|
||||
import platform.gles.GL_FASTEST
|
||||
import platform.gles.GL_FLOAT
|
||||
import platform.gles.GL_FRONT_AND_BACK
|
||||
import platform.gles.GL_LIGHT0
|
||||
import platform.gles.GL_LIGHTING
|
||||
import platform.gles.GL_MODELVIEW
|
||||
import platform.gles.GL_NORMAL_ARRAY
|
||||
import platform.gles.GL_PERSPECTIVE_CORRECTION_HINT
|
||||
import platform.gles.GL_POSITION
|
||||
import platform.gles.GL_PROJECTION
|
||||
import platform.gles.GL_SHININESS
|
||||
import platform.gles.GL_SMOOTH
|
||||
import platform.gles.GL_SPECULAR
|
||||
import platform.gles.GL_TEXTURE_2D
|
||||
import platform.gles.GL_TEXTURE_COORD_ARRAY
|
||||
import platform.gles.GL_TRIANGLES
|
||||
import platform.gles.GL_UNSIGNED_BYTE
|
||||
import platform.gles.GL_VERTEX_ARRAY
|
||||
import platform.gles.glClear
|
||||
import platform.gles.glClearColor
|
||||
import platform.gles.glDisable
|
||||
import platform.gles.glDrawElements
|
||||
import platform.gles.glEnable
|
||||
import platform.gles.glEnableClientState
|
||||
import platform.gles.glFrontFace
|
||||
import platform.gles.glFrustumf
|
||||
import platform.gles.glHint
|
||||
import platform.gles.glLightfv
|
||||
import platform.gles.glLoadIdentity
|
||||
import platform.gles.glMaterialf
|
||||
import platform.gles.glMaterialfv
|
||||
import platform.gles.glMatrixMode
|
||||
import platform.gles.glMultMatrixf
|
||||
import platform.gles.glNormalPointer
|
||||
import platform.gles.glPopMatrix
|
||||
import platform.gles.glPushMatrix
|
||||
import platform.gles.glShadeModel
|
||||
import platform.gles.glTexCoordPointer
|
||||
import platform.gles.glTranslatef
|
||||
import platform.gles.glVertexPointer
|
||||
import platform.gles.glViewport
|
||||
import platform.posix.sqrtf
|
||||
|
||||
private const val WIDTH = 600
|
||||
private const val HEIGHT = 800
|
||||
private const val SCALE = 1.25f
|
||||
|
||||
fun main() = memScoped {
|
||||
glDisable(GL_DITHER)
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
|
||||
glEnable(GL_CULL_FACE)
|
||||
glShadeModel(GL_SMOOTH)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
glViewport(0, 0, WIDTH, HEIGHT)
|
||||
|
||||
val ratio = WIDTH.toFloat() / HEIGHT
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glLoadIdentity()
|
||||
glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f)
|
||||
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
glTranslatef(0.0f, 0.0f, -2.0f)
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, cValuesOf(1.25f, 1.25f, -2.0f, 0.0f))
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, cValuesOf(0.0f, 1.0f, 1.0f, 1.0f))
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, cValuesOf(0.3f, 0.3f, 0.3f, 1.0f))
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0f)
|
||||
|
||||
glPushMatrix()
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
|
||||
|
||||
val matrix = allocArray<FloatVar>(16)
|
||||
for (i in 0..3)
|
||||
for (j in 0..3)
|
||||
matrix[i * 4 + j] = if (i == j) 1.0f else 0.0f
|
||||
|
||||
glMultMatrixf(matrix)
|
||||
|
||||
glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).toUInt())
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY)
|
||||
glEnableClientState(GL_NORMAL_ARRAY)
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||
|
||||
val polygon = RegularPolyhedra.Dodecahedron
|
||||
val vertices = mutableListOf<Float>()
|
||||
val texCoords = mutableListOf<Float>()
|
||||
val triangles = mutableListOf<Byte>()
|
||||
val normals = mutableListOf<Float>()
|
||||
|
||||
val texturePoints = arrayOf(Vector2(0.0f, 0.2f), Vector2(0.0f, 0.8f), Vector2(0.6f, 1.0f), Vector2(1.0f, 0.5f), Vector2(0.8f, 0.0f))
|
||||
|
||||
|
||||
for (face in polygon.faces) {
|
||||
val u = polygon.vertices[face[2].toInt()] - polygon.vertices[face[1].toInt()]
|
||||
val v = polygon.vertices[face[0].toInt()] - polygon.vertices[face[1].toInt()]
|
||||
val normal = u.crossProduct(v).normalized()
|
||||
|
||||
val copiedFace = ByteArray(face.size)
|
||||
for (j in face.indices) {
|
||||
copiedFace[j] = (vertices.size / 4).toByte()
|
||||
polygon.vertices[face[j].toInt()].copyCoordinatesTo(vertices)
|
||||
vertices.add(SCALE)
|
||||
normal.copyCoordinatesTo(normals)
|
||||
texturePoints[j].copyCoordinatesTo(texCoords)
|
||||
}
|
||||
|
||||
for (j in 1..face.size - 2) {
|
||||
triangles.add(copiedFace[0])
|
||||
triangles.add(copiedFace[j])
|
||||
triangles.add(copiedFace[j + 1])
|
||||
}
|
||||
}
|
||||
|
||||
glFrontFace(GL_CW)
|
||||
glVertexPointer(4, GL_FLOAT, 0, vertices.toFloatArray().toCValues().ptr)
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texCoords.toFloatArray().toCValues().ptr)
|
||||
glNormalPointer(GL_FLOAT, 0, normals.toFloatArray().toCValues().ptr)
|
||||
glDrawElements(GL_TRIANGLES, triangles.size, GL_UNSIGNED_BYTE, triangles.toByteArray().toCValues().ptr)
|
||||
|
||||
glPopMatrix()
|
||||
}
|
||||
|
||||
private class Vector2(val x: Float, val y: Float) {
|
||||
val length by lazy { sqrtf(x * x + y * y) }
|
||||
|
||||
fun normalized(): Vector2 {
|
||||
val len = length
|
||||
return Vector2(x / len, y / len)
|
||||
}
|
||||
|
||||
fun copyCoordinatesTo(arr: MutableList<Float>) {
|
||||
arr.add(x)
|
||||
arr.add(y)
|
||||
}
|
||||
|
||||
operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y)
|
||||
operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y)
|
||||
operator fun times(other: Float) = Vector2(x * other, y * other)
|
||||
operator fun div(other: Float) = Vector2(x / other, y / other)
|
||||
|
||||
companion object {
|
||||
val Zero = Vector2(0.0f, 0.0f)
|
||||
}
|
||||
}
|
||||
|
||||
private class Vector3(val x: Float, val y: Float, val z: Float) {
|
||||
val length by lazy { sqrtf(x * x + y * y + z * z) }
|
||||
|
||||
fun crossProduct(other: Vector3): Vector3 =
|
||||
Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x)
|
||||
|
||||
fun normalized(): Vector3 {
|
||||
val len = length
|
||||
return Vector3(x / len, y / len, z / len)
|
||||
}
|
||||
|
||||
fun copyCoordinatesTo(arr: MutableList<Float>) {
|
||||
arr.add(x)
|
||||
arr.add(y)
|
||||
arr.add(z)
|
||||
}
|
||||
|
||||
operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z)
|
||||
operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z)
|
||||
}
|
||||
|
||||
private const val Zero = 0.0f
|
||||
private const val DodeA = 0.93417235896f // (Sqrt(5) + 1) / (2 * Sqrt(3))
|
||||
private const val DodeB = 0.35682208977f // (Sqrt(5) - 1) / (2 * Sqrt(3))
|
||||
private const val DodeC = 0.57735026919f // 1 / Sqrt(3)
|
||||
private const val IcosA = 0.52573111212f // Sqrt(5 - Sqrt(5)) / Sqrt(10)
|
||||
private const val IcosB = 0.85065080835f // Sqrt(5 + Sqrt(5)) / Sqrt(10)
|
||||
|
||||
private enum class RegularPolyhedra(val vertices: Array<Vector3>, val faces: Array<ByteArray>) {
|
||||
Dodecahedron(
|
||||
arrayOf(
|
||||
Vector3(-DodeA, Zero, DodeB), Vector3(-DodeA, Zero, -DodeB), Vector3(DodeA, Zero, -DodeB),
|
||||
Vector3(DodeA, Zero, DodeB), Vector3(DodeB, -DodeA, Zero), Vector3(-DodeB, -DodeA, Zero),
|
||||
Vector3(-DodeB, DodeA, Zero), Vector3(DodeB, DodeA, Zero), Vector3(Zero, DodeB, -DodeA),
|
||||
Vector3(Zero, -DodeB, -DodeA), Vector3(Zero, -DodeB, DodeA), Vector3(Zero, DodeB, DodeA),
|
||||
Vector3(-DodeC, -DodeC, DodeC), Vector3(-DodeC, -DodeC, -DodeC), Vector3(DodeC, -DodeC, -DodeC),
|
||||
Vector3(DodeC, -DodeC, DodeC), Vector3(-DodeC, DodeC, DodeC), Vector3(-DodeC, DodeC, -DodeC),
|
||||
Vector3(DodeC, DodeC, -DodeC), Vector3(DodeC, DodeC, DodeC)
|
||||
),
|
||||
arrayOf(
|
||||
byteArrayOf(0, 12, 10, 11, 16), byteArrayOf(1, 17, 8, 9, 13), byteArrayOf(2, 14, 9, 8, 18),
|
||||
byteArrayOf(3, 19, 11, 10, 15), byteArrayOf(4, 14, 2, 3, 15), byteArrayOf(5, 12, 0, 1, 13),
|
||||
byteArrayOf(6, 17, 1, 0, 16), byteArrayOf(7, 19, 3, 2, 18), byteArrayOf(8, 17, 6, 7, 18),
|
||||
byteArrayOf(9, 14, 4, 5, 13), byteArrayOf(10, 12, 5, 4, 15), byteArrayOf(11, 19, 7, 6, 16)
|
||||
)),
|
||||
Icosahedron(
|
||||
arrayOf(
|
||||
Vector3(-IcosA, Zero, IcosB), Vector3(IcosA, Zero, IcosB), Vector3(-IcosA, Zero, -IcosB),
|
||||
Vector3(IcosA, Zero, -IcosB), Vector3(Zero, IcosB, IcosA), Vector3(Zero, IcosB, -IcosA),
|
||||
Vector3(Zero, -IcosB, IcosA), Vector3(Zero, -IcosB, -IcosA), Vector3(IcosB, IcosA, Zero),
|
||||
Vector3(-IcosB, IcosA, Zero), Vector3(IcosB, -IcosA, Zero), Vector3(-IcosB, -IcosA, Zero)
|
||||
),
|
||||
arrayOf(
|
||||
byteArrayOf(1, 4, 0), byteArrayOf(4, 9, 0), byteArrayOf(4, 5, 9), byteArrayOf(8, 5, 4),
|
||||
byteArrayOf(1, 8, 4), byteArrayOf(1, 10, 8), byteArrayOf(10, 3, 8), byteArrayOf(8, 3, 5),
|
||||
byteArrayOf(3, 2, 5), byteArrayOf(3, 7, 2), byteArrayOf(3, 10, 7), byteArrayOf(10, 6, 7),
|
||||
byteArrayOf(6, 11, 7), byteArrayOf(6, 0, 11), byteArrayOf(6, 1, 0), byteArrayOf(10, 1, 6),
|
||||
byteArrayOf(11, 0, 9), byteArrayOf(2, 11, 9), byteArrayOf(5, 2, 9), byteArrayOf(11, 2, 7)
|
||||
)
|
||||
);
|
||||
|
||||
val verticesPerFace get() = faces[0].size
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("RemoveRedundantCallsOfConversionMethods", "unused", "CanBeParameter")
|
||||
|
||||
import kotlinx.cinterop.FloatVar
|
||||
import kotlinx.cinterop.allocArray
|
||||
import kotlinx.cinterop.cValuesOf
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.set
|
||||
import kotlinx.cinterop.toCValues
|
||||
import platform.gles.GL_COLOR_BUFFER_BIT
|
||||
import platform.gles.GL_CULL_FACE
|
||||
import platform.gles.GL_CW
|
||||
import platform.gles.GL_DEPTH_BUFFER_BIT
|
||||
import platform.gles.GL_DEPTH_TEST
|
||||
import platform.gles.GL_DIFFUSE
|
||||
import platform.gles.GL_DITHER
|
||||
import platform.gles.GL_FASTEST
|
||||
import platform.gles.GL_FLOAT
|
||||
import platform.gles.GL_FRONT_AND_BACK
|
||||
import platform.gles.GL_LIGHT0
|
||||
import platform.gles.GL_LIGHTING
|
||||
import platform.gles.GL_MODELVIEW
|
||||
import platform.gles.GL_NORMAL_ARRAY
|
||||
import platform.gles.GL_PERSPECTIVE_CORRECTION_HINT
|
||||
import platform.gles.GL_POSITION
|
||||
import platform.gles.GL_PROJECTION
|
||||
import platform.gles.GL_SHININESS
|
||||
import platform.gles.GL_SMOOTH
|
||||
import platform.gles.GL_SPECULAR
|
||||
import platform.gles.GL_TEXTURE_2D
|
||||
import platform.gles.GL_TEXTURE_COORD_ARRAY
|
||||
import platform.gles.GL_TRIANGLES
|
||||
import platform.gles.GL_UNSIGNED_BYTE
|
||||
import platform.gles.GL_VERTEX_ARRAY
|
||||
import platform.gles.glClear
|
||||
import platform.gles.glClearColor
|
||||
import platform.gles.glDisable
|
||||
import platform.gles.glDrawElements
|
||||
import platform.gles.glEnable
|
||||
import platform.gles.glEnableClientState
|
||||
import platform.gles.glFrontFace
|
||||
import platform.gles.glFrustumf
|
||||
import platform.gles.glHint
|
||||
import platform.gles.glLightfv
|
||||
import platform.gles.glLoadIdentity
|
||||
import platform.gles.glMaterialf
|
||||
import platform.gles.glMaterialfv
|
||||
import platform.gles.glMatrixMode
|
||||
import platform.gles.glMultMatrixf
|
||||
import platform.gles.glNormalPointer
|
||||
import platform.gles.glPopMatrix
|
||||
import platform.gles.glPushMatrix
|
||||
import platform.gles.glShadeModel
|
||||
import platform.gles.glTexCoordPointer
|
||||
import platform.gles.glTranslatef
|
||||
import platform.gles.glVertexPointer
|
||||
import platform.gles.glViewport
|
||||
import platform.posix.sqrtf
|
||||
|
||||
private const val WIDTH = 600
|
||||
private const val HEIGHT = 800
|
||||
private const val SCALE = 1.25f
|
||||
|
||||
fun main() = memScoped {
|
||||
glDisable(GL_DITHER)
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
|
||||
glEnable(GL_CULL_FACE)
|
||||
glShadeModel(GL_SMOOTH)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
glViewport(0, 0, WIDTH, HEIGHT)
|
||||
|
||||
val ratio = WIDTH.toFloat() / HEIGHT
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glLoadIdentity()
|
||||
glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f)
|
||||
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
glTranslatef(0.0f, 0.0f, -2.0f)
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, cValuesOf(1.25f, 1.25f, -2.0f, 0.0f))
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, cValuesOf(0.0f, 1.0f, 1.0f, 1.0f))
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, cValuesOf(0.3f, 0.3f, 0.3f, 1.0f))
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0f)
|
||||
|
||||
glPushMatrix()
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
|
||||
|
||||
val matrix = allocArray<FloatVar>(16)
|
||||
for (i in 0..3)
|
||||
for (j in 0..3)
|
||||
matrix[i * 4 + j] = if (i == j) 1.0f else 0.0f
|
||||
|
||||
glMultMatrixf(matrix)
|
||||
|
||||
glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).toUInt())
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY)
|
||||
glEnableClientState(GL_NORMAL_ARRAY)
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||
|
||||
val polygon = RegularPolyhedra.Dodecahedron
|
||||
val vertices = mutableListOf<Float>()
|
||||
val texCoords = mutableListOf<Float>()
|
||||
val triangles = mutableListOf<Byte>()
|
||||
val normals = mutableListOf<Float>()
|
||||
|
||||
val texturePoints = arrayOf(Vector2(0.0f, 0.2f), Vector2(0.0f, 0.8f), Vector2(0.6f, 1.0f), Vector2(1.0f, 0.5f), Vector2(0.8f, 0.0f))
|
||||
|
||||
|
||||
for (face in polygon.faces) {
|
||||
val u = polygon.vertices[face[2].toInt()] - polygon.vertices[face[1].toInt()]
|
||||
val v = polygon.vertices[face[0].toInt()] - polygon.vertices[face[1].toInt()]
|
||||
val normal = u.crossProduct(v).normalized()
|
||||
|
||||
val copiedFace = ByteArray(face.size)
|
||||
for (j in face.indices) {
|
||||
copiedFace[j] = (vertices.size / 4).toByte()
|
||||
polygon.vertices[face[j].toInt()].copyCoordinatesTo(vertices)
|
||||
vertices.add(SCALE)
|
||||
normal.copyCoordinatesTo(normals)
|
||||
texturePoints[j].copyCoordinatesTo(texCoords)
|
||||
}
|
||||
|
||||
for (j in 1..face.size - 2) {
|
||||
triangles.add(copiedFace[0])
|
||||
triangles.add(copiedFace[j])
|
||||
triangles.add(copiedFace[j + 1])
|
||||
}
|
||||
}
|
||||
|
||||
glFrontFace(GL_CW)
|
||||
glVertexPointer(4, GL_FLOAT, 0, vertices.toFloatArray().toCValues().ptr)
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texCoords.toFloatArray().toCValues().ptr)
|
||||
glNormalPointer(GL_FLOAT, 0, normals.toFloatArray().toCValues().ptr)
|
||||
glDrawElements(GL_TRIANGLES, triangles.size, GL_UNSIGNED_BYTE, triangles.toByteArray().toCValues().ptr)
|
||||
|
||||
glPopMatrix()
|
||||
}
|
||||
|
||||
private class Vector2(val x: Float, val y: Float) {
|
||||
val length by lazy { sqrtf(x * x + y * y) }
|
||||
|
||||
fun normalized(): Vector2 {
|
||||
val len = length
|
||||
return Vector2(x / len, y / len)
|
||||
}
|
||||
|
||||
fun copyCoordinatesTo(arr: MutableList<Float>) {
|
||||
arr.add(x)
|
||||
arr.add(y)
|
||||
}
|
||||
|
||||
operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y)
|
||||
operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y)
|
||||
operator fun times(other: Float) = Vector2(x * other, y * other)
|
||||
operator fun div(other: Float) = Vector2(x / other, y / other)
|
||||
|
||||
companion object {
|
||||
val Zero = Vector2(0.0f, 0.0f)
|
||||
}
|
||||
}
|
||||
|
||||
private class Vector3(val x: Float, val y: Float, val z: Float) {
|
||||
val length by lazy { sqrtf(x * x + y * y + z * z) }
|
||||
|
||||
fun crossProduct(other: Vector3): Vector3 =
|
||||
Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x)
|
||||
|
||||
fun normalized(): Vector3 {
|
||||
val len = length
|
||||
return Vector3(x / len, y / len, z / len)
|
||||
}
|
||||
|
||||
fun copyCoordinatesTo(arr: MutableList<Float>) {
|
||||
arr.add(x)
|
||||
arr.add(y)
|
||||
arr.add(z)
|
||||
}
|
||||
|
||||
operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z)
|
||||
operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z)
|
||||
}
|
||||
|
||||
private const val Zero = 0.0f
|
||||
private const val DodeA = 0.93417235896f // (Sqrt(5) + 1) / (2 * Sqrt(3))
|
||||
private const val DodeB = 0.35682208977f // (Sqrt(5) - 1) / (2 * Sqrt(3))
|
||||
private const val DodeC = 0.57735026919f // 1 / Sqrt(3)
|
||||
private const val IcosA = 0.52573111212f // Sqrt(5 - Sqrt(5)) / Sqrt(10)
|
||||
private const val IcosB = 0.85065080835f // Sqrt(5 + Sqrt(5)) / Sqrt(10)
|
||||
|
||||
private enum class RegularPolyhedra(val vertices: Array<Vector3>, val faces: Array<ByteArray>) {
|
||||
Dodecahedron(
|
||||
arrayOf(
|
||||
Vector3(-DodeA, Zero, DodeB), Vector3(-DodeA, Zero, -DodeB), Vector3(DodeA, Zero, -DodeB),
|
||||
Vector3(DodeA, Zero, DodeB), Vector3(DodeB, -DodeA, Zero), Vector3(-DodeB, -DodeA, Zero),
|
||||
Vector3(-DodeB, DodeA, Zero), Vector3(DodeB, DodeA, Zero), Vector3(Zero, DodeB, -DodeA),
|
||||
Vector3(Zero, -DodeB, -DodeA), Vector3(Zero, -DodeB, DodeA), Vector3(Zero, DodeB, DodeA),
|
||||
Vector3(-DodeC, -DodeC, DodeC), Vector3(-DodeC, -DodeC, -DodeC), Vector3(DodeC, -DodeC, -DodeC),
|
||||
Vector3(DodeC, -DodeC, DodeC), Vector3(-DodeC, DodeC, DodeC), Vector3(-DodeC, DodeC, -DodeC),
|
||||
Vector3(DodeC, DodeC, -DodeC), Vector3(DodeC, DodeC, DodeC)
|
||||
),
|
||||
arrayOf(
|
||||
byteArrayOf(0, 12, 10, 11, 16), byteArrayOf(1, 17, 8, 9, 13), byteArrayOf(2, 14, 9, 8, 18),
|
||||
byteArrayOf(3, 19, 11, 10, 15), byteArrayOf(4, 14, 2, 3, 15), byteArrayOf(5, 12, 0, 1, 13),
|
||||
byteArrayOf(6, 17, 1, 0, 16), byteArrayOf(7, 19, 3, 2, 18), byteArrayOf(8, 17, 6, 7, 18),
|
||||
byteArrayOf(9, 14, 4, 5, 13), byteArrayOf(10, 12, 5, 4, 15), byteArrayOf(11, 19, 7, 6, 16)
|
||||
)),
|
||||
Icosahedron(
|
||||
arrayOf(
|
||||
Vector3(-IcosA, Zero, IcosB), Vector3(IcosA, Zero, IcosB), Vector3(-IcosA, Zero, -IcosB),
|
||||
Vector3(IcosA, Zero, -IcosB), Vector3(Zero, IcosB, IcosA), Vector3(Zero, IcosB, -IcosA),
|
||||
Vector3(Zero, -IcosB, IcosA), Vector3(Zero, -IcosB, -IcosA), Vector3(IcosB, IcosA, Zero),
|
||||
Vector3(-IcosB, IcosA, Zero), Vector3(IcosB, -IcosA, Zero), Vector3(-IcosB, -IcosA, Zero)
|
||||
),
|
||||
arrayOf(
|
||||
byteArrayOf(1, 4, 0), byteArrayOf(4, 9, 0), byteArrayOf(4, 5, 9), byteArrayOf(8, 5, 4),
|
||||
byteArrayOf(1, 8, 4), byteArrayOf(1, 10, 8), byteArrayOf(10, 3, 8), byteArrayOf(8, 3, 5),
|
||||
byteArrayOf(3, 2, 5), byteArrayOf(3, 7, 2), byteArrayOf(3, 10, 7), byteArrayOf(10, 6, 7),
|
||||
byteArrayOf(6, 11, 7), byteArrayOf(6, 0, 11), byteArrayOf(6, 1, 0), byteArrayOf(10, 1, 6),
|
||||
byteArrayOf(11, 0, 9), byteArrayOf(2, 11, 9), byteArrayOf(5, 2, 9), byteArrayOf(11, 2, 7)
|
||||
)
|
||||
);
|
||||
|
||||
val verticesPerFace get() = faces[0].size
|
||||
}
|
||||
@@ -3,6 +3,9 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package perfTestPackage1 // this package is mandatory
|
||||
|
||||
import kotlinx.cinterop.ExportObjCClass
|
||||
import kotlinx.cinterop.ObjCAction
|
||||
import kotlinx.cinterop.ObjCOutlet
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import kotlinx.cinterop.ExportObjCClass
|
||||
import kotlinx.cinterop.ObjCAction
|
||||
import kotlinx.cinterop.ObjCOutlet
|
||||
import kotlinx.cinterop.autoreleasepool
|
||||
import kotlinx.cinterop.cstr
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.toCValues
|
||||
import kotlinx.cinterop.useContents
|
||||
import platform.CoreGraphics.CGPointMake
|
||||
import platform.CoreGraphics.CGRectMake
|
||||
import platform.Foundation.NSCoder
|
||||
import platform.Foundation.NSSelectorFromString
|
||||
import platform.Foundation.NSStringFromClass
|
||||
import platform.UIKit.NSTextAlignmentCenter
|
||||
import platform.UIKit.UIApplication
|
||||
import platform.UIKit.UIApplicationDelegateProtocol
|
||||
import platform.UIKit.UIApplicationDelegateProtocolMeta
|
||||
import platform.UIKit.UIApplicationMain
|
||||
import platform.UIKit.UIButton
|
||||
import platform.UIKit.UIColor
|
||||
import platform.UIKit.UIControlEventTouchUpInside
|
||||
import platform.UIKit.UIControlStateNormal
|
||||
import platform.UIKit.UIFont
|
||||
import platform.UIKit.UILabel
|
||||
import platform.UIKit.UIResponder
|
||||
import platform.UIKit.UIResponderMeta
|
||||
import platform.UIKit.UIScreen
|
||||
import platform.UIKit.UIView
|
||||
import platform.UIKit.UIViewController
|
||||
import platform.UIKit.UIWindow
|
||||
import platform.UIKit.addSubview
|
||||
import platform.UIKit.backgroundColor
|
||||
import platform.UIKit.font
|
||||
import platform.UIKit.heightAnchor
|
||||
import platform.UIKit.leadingAnchor
|
||||
import platform.UIKit.setFrame
|
||||
import platform.UIKit.topAnchor
|
||||
import platform.UIKit.translatesAutoresizingMaskIntoConstraints
|
||||
import platform.UIKit.widthAnchor
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
memScoped {
|
||||
val argc = args.size + 1
|
||||
val argv = (arrayOf("konan") + args).map { it.cstr.ptr }.toCValues()
|
||||
|
||||
autoreleasepool {
|
||||
UIApplicationMain(argc, argv, null, NSStringFromClass(AppDelegate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AppDelegate : UIResponder, UIApplicationDelegateProtocol {
|
||||
companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta {}
|
||||
|
||||
@OverrideInit
|
||||
constructor() : super()
|
||||
|
||||
private var _window: UIWindow? = null
|
||||
override fun window() = _window
|
||||
override fun setWindow(window: UIWindow?) {
|
||||
_window = window
|
||||
}
|
||||
|
||||
override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean {
|
||||
window = UIWindow(frame = UIScreen.mainScreen.bounds)
|
||||
window!!.rootViewController = ViewController()
|
||||
window!!.makeKeyAndVisible()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ExportObjCClass
|
||||
private class ViewController : UIViewController {
|
||||
|
||||
@OverrideInit
|
||||
constructor() : super(nibName = null, bundle = null)
|
||||
|
||||
@OverrideInit
|
||||
constructor(coder: NSCoder) : super(coder)
|
||||
|
||||
@ObjCOutlet
|
||||
lateinit var label: UILabel
|
||||
|
||||
@ObjCOutlet
|
||||
lateinit var button: UIButton
|
||||
|
||||
var pressed = 0
|
||||
|
||||
@ObjCAction
|
||||
fun buttonPressed() {
|
||||
label.text = "Hello #${pressed++} from Konan!"
|
||||
println("Button pressed")
|
||||
}
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val (width, height) = UIScreen.mainScreen.bounds.useContents {
|
||||
this.size.width to this.size.height
|
||||
}
|
||||
|
||||
val header = UIView().apply {
|
||||
backgroundColor = UIColor.lightGrayColor
|
||||
view.addSubview(this)
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
|
||||
topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
|
||||
widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
|
||||
heightAnchor.constraintEqualToAnchor(view.heightAnchor).active = true
|
||||
}
|
||||
|
||||
label = UILabel().apply {
|
||||
setFrame(CGRectMake(x = 10.0, y = 10.0, width = width - 100.0, height = 40.0))
|
||||
center = CGPointMake(x = width / 2, y = 40.0 )
|
||||
textAlignment = NSTextAlignmentCenter
|
||||
text = "Press OK"
|
||||
header.addSubview(this)
|
||||
}
|
||||
|
||||
button = UIButton().apply {
|
||||
setFrame(CGRectMake(x = 10.0, y = height - 100.0, width = width - 100.0, height = 40.0))
|
||||
center = CGPointMake(x = width / 2, y = height / 2)
|
||||
backgroundColor = UIColor.blueColor
|
||||
setTitle("OK", forState = UIControlStateNormal)
|
||||
font = UIFont.fontWithName(fontName = font.fontName, size = 28.0)!!
|
||||
layer.borderWidth = 1.0
|
||||
layer.borderColor = UIColor.colorWithRed(0x47 / 255.0, 0x43 / 255.0, 0x70 / 255.0, 1.0).CGColor
|
||||
layer.masksToBounds = true
|
||||
addTarget(target = this@ViewController, action = NSSelectorFromString("buttonPressed"),
|
||||
forControlEvents = UIControlEventTouchUpInside)
|
||||
header.addSubview(this)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import kotlinx.cinterop.ExportObjCClass
|
||||
import kotlinx.cinterop.ObjCAction
|
||||
import kotlinx.cinterop.ObjCOutlet
|
||||
import kotlinx.cinterop.autoreleasepool
|
||||
import kotlinx.cinterop.cstr
|
||||
import kotlinx.cinterop.memScoped
|
||||
import kotlinx.cinterop.toCValues
|
||||
import kotlinx.cinterop.useContents
|
||||
import platform.CoreGraphics.CGPointMake
|
||||
import platform.CoreGraphics.CGRectMake
|
||||
import platform.Foundation.NSCoder
|
||||
import platform.Foundation.NSSelectorFromString
|
||||
import platform.Foundation.NSStringFromClass
|
||||
import platform.UIKit.NSTextAlignmentCenter
|
||||
import platform.UIKit.UIApplication
|
||||
import platform.UIKit.UIApplicationDelegateProtocol
|
||||
import platform.UIKit.UIApplicationDelegateProtocolMeta
|
||||
import platform.UIKit.UIApplicationMain
|
||||
import platform.UIKit.UIButton
|
||||
import platform.UIKit.UIColor
|
||||
import platform.UIKit.UIControlEventTouchUpInside
|
||||
import platform.UIKit.UIControlStateNormal
|
||||
import platform.UIKit.UIFont
|
||||
import platform.UIKit.UILabel
|
||||
import platform.UIKit.UIResponder
|
||||
import platform.UIKit.UIResponderMeta
|
||||
import platform.UIKit.UIScreen
|
||||
import platform.UIKit.UIView
|
||||
import platform.UIKit.UIViewController
|
||||
import platform.UIKit.UIWindow
|
||||
import platform.UIKit.addSubview
|
||||
import platform.UIKit.backgroundColor
|
||||
import platform.UIKit.font
|
||||
import platform.UIKit.heightAnchor
|
||||
import platform.UIKit.leadingAnchor
|
||||
import platform.UIKit.setFrame
|
||||
import platform.UIKit.topAnchor
|
||||
import platform.UIKit.translatesAutoresizingMaskIntoConstraints
|
||||
import platform.UIKit.widthAnchor
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
memScoped {
|
||||
val argc = args.size + 1
|
||||
val argv = (arrayOf("konan") + args).map { it.cstr.ptr }.toCValues()
|
||||
|
||||
autoreleasepool {
|
||||
UIApplicationMain(argc, argv, null, NSStringFromClass(AppDelegate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AppDelegate : UIResponder, UIApplicationDelegateProtocol {
|
||||
companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta {}
|
||||
|
||||
@OverrideInit
|
||||
constructor() : super()
|
||||
|
||||
private var _window: UIWindow? = null
|
||||
override fun window() = _window
|
||||
override fun setWindow(window: UIWindow?) {
|
||||
_window = window
|
||||
}
|
||||
|
||||
override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean {
|
||||
window = UIWindow(frame = UIScreen.mainScreen.bounds)
|
||||
window!!.rootViewController = ViewController()
|
||||
window!!.makeKeyAndVisible()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ExportObjCClass
|
||||
private class ViewController : UIViewController {
|
||||
|
||||
@OverrideInit
|
||||
constructor() : super(nibName = null, bundle = null)
|
||||
|
||||
@OverrideInit
|
||||
constructor(coder: NSCoder) : super(coder)
|
||||
|
||||
@ObjCOutlet
|
||||
lateinit var label: UILabel
|
||||
|
||||
@ObjCOutlet
|
||||
lateinit var button: UIButton
|
||||
|
||||
var pressed = 0
|
||||
|
||||
@ObjCAction
|
||||
fun buttonPressed() {
|
||||
label.text = "Hello #${pressed++} from Konan!"
|
||||
println("Button pressed")
|
||||
}
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val (width, height) = UIScreen.mainScreen.bounds.useContents {
|
||||
this.size.width to this.size.height
|
||||
}
|
||||
|
||||
val header = UIView().apply {
|
||||
backgroundColor = UIColor.lightGrayColor
|
||||
view.addSubview(this)
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
|
||||
topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
|
||||
widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
|
||||
heightAnchor.constraintEqualToAnchor(view.heightAnchor).active = true
|
||||
}
|
||||
|
||||
label = UILabel().apply {
|
||||
setFrame(CGRectMake(x = 10.0, y = 10.0, width = width - 100.0, height = 40.0))
|
||||
center = CGPointMake(x = width / 2, y = 40.0 )
|
||||
textAlignment = NSTextAlignmentCenter
|
||||
text = "Press OK"
|
||||
header.addSubview(this)
|
||||
}
|
||||
|
||||
button = UIButton().apply {
|
||||
setFrame(CGRectMake(x = 10.0, y = height - 100.0, width = width - 100.0, height = 40.0))
|
||||
center = CGPointMake(x = width / 2, y = height / 2)
|
||||
backgroundColor = UIColor.blueColor
|
||||
setTitle("OK", forState = UIControlStateNormal)
|
||||
font = UIFont.fontWithName(fontName = font.fontName, size = 28.0)!!
|
||||
layer.borderWidth = 1.0
|
||||
layer.borderColor = UIColor.colorWithRed(0x47 / 255.0, 0x43 / 255.0, 0x70 / 255.0, 1.0).CGColor
|
||||
layer.masksToBounds = true
|
||||
addTarget(target = this@ViewController, action = NSSelectorFromString("buttonPressed"),
|
||||
forControlEvents = UIControlEventTouchUpInside)
|
||||
header.addSubview(this)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user